4 * Copyright 1993 Alexandre Julliard
6 * Copyright 2002,2003 Shachar Shemesh
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "wine/port.h"
35 #include "gdi_private.h"
36 #include "wine/unicode.h"
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(font);
41 /* Device -> World size conversion */
43 /* Performs a device to world transformation on the specified width (which
44 * is in integer format).
46 static inline INT INTERNAL_XDSTOWS(DC *dc, INT width)
50 /* Perform operation with floating point */
51 floatWidth = (double)width * dc->xformVport2World.eM11;
52 /* Round to integers */
53 return GDI_ROUND(floatWidth);
56 /* Performs a device to world transformation on the specified size (which
57 * is in integer format).
59 static inline INT INTERNAL_YDSTOWS(DC *dc, INT height)
63 /* Perform operation with floating point */
64 floatHeight = (double)height * dc->xformVport2World.eM22;
65 /* Round to integers */
66 return GDI_ROUND(floatHeight);
69 static inline INT INTERNAL_XWSTODS(DC *dc, INT width)
72 pt[0].x = pt[0].y = 0;
75 LPtoDP(dc->hSelf, pt, 2);
76 return pt[1].x - pt[0].x;
79 static inline INT INTERNAL_YWSTODS(DC *dc, INT height)
82 pt[0].x = pt[0].y = 0;
85 LPtoDP(dc->hSelf, pt, 2);
86 return pt[1].y - pt[0].y;
89 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc );
90 static INT FONT_GetObjectA( HGDIOBJ handle, INT count, LPVOID buffer );
91 static INT FONT_GetObjectW( HGDIOBJ handle, INT count, LPVOID buffer );
92 static BOOL FONT_DeleteObject( HGDIOBJ handle );
94 static const struct gdi_obj_funcs font_funcs =
96 FONT_SelectObject, /* pSelectObject */
97 FONT_GetObjectA, /* pGetObjectA */
98 FONT_GetObjectW, /* pGetObjectW */
99 NULL, /* pUnrealizeObject */
100 FONT_DeleteObject /* pDeleteObject */
103 #define ENUM_UNICODE 0x00000001
104 #define ENUM_CALLED 0x00000002
114 LPLOGFONTW lpLogFontParam;
115 FONTENUMPROCW lpEnumFunc;
122 * For TranslateCharsetInfo
124 #define MAXTCIINDEX 32
125 static const CHARSETINFO FONT_tci[MAXTCIINDEX] = {
127 { ANSI_CHARSET, 1252, {{0,0,0,0},{FS_LATIN1,0}} },
128 { EASTEUROPE_CHARSET, 1250, {{0,0,0,0},{FS_LATIN2,0}} },
129 { RUSSIAN_CHARSET, 1251, {{0,0,0,0},{FS_CYRILLIC,0}} },
130 { GREEK_CHARSET, 1253, {{0,0,0,0},{FS_GREEK,0}} },
131 { TURKISH_CHARSET, 1254, {{0,0,0,0},{FS_TURKISH,0}} },
132 { HEBREW_CHARSET, 1255, {{0,0,0,0},{FS_HEBREW,0}} },
133 { ARABIC_CHARSET, 1256, {{0,0,0,0},{FS_ARABIC,0}} },
134 { BALTIC_CHARSET, 1257, {{0,0,0,0},{FS_BALTIC,0}} },
135 { VIETNAMESE_CHARSET, 1258, {{0,0,0,0},{FS_VIETNAMESE,0}} },
136 /* reserved by ANSI */
137 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
138 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
139 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
140 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
141 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
142 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
143 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
145 { THAI_CHARSET, 874, {{0,0,0,0},{FS_THAI,0}} },
146 { SHIFTJIS_CHARSET, 932, {{0,0,0,0},{FS_JISJAPAN,0}} },
147 { GB2312_CHARSET, 936, {{0,0,0,0},{FS_CHINESESIMP,0}} },
148 { HANGEUL_CHARSET, 949, {{0,0,0,0},{FS_WANSUNG,0}} },
149 { CHINESEBIG5_CHARSET, 950, {{0,0,0,0},{FS_CHINESETRAD,0}} },
150 { JOHAB_CHARSET, 1361, {{0,0,0,0},{FS_JOHAB,0}} },
151 /* reserved for alternate ANSI and OEM */
152 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
153 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
154 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
155 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
156 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
157 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
158 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
159 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
160 /* reserved for system */
161 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
162 { SYMBOL_CHARSET, CP_SYMBOL, {{0,0,0,0},{FS_SYMBOL,0}} }
165 static void FONT_LogFontAToW( const LOGFONTA *fontA, LPLOGFONTW fontW )
167 memcpy(fontW, fontA, sizeof(LOGFONTA) - LF_FACESIZE);
168 MultiByteToWideChar(CP_ACP, 0, fontA->lfFaceName, -1, fontW->lfFaceName,
170 fontW->lfFaceName[LF_FACESIZE-1] = 0;
173 static void FONT_LogFontWToA( const LOGFONTW *fontW, LPLOGFONTA fontA )
175 memcpy(fontA, fontW, sizeof(LOGFONTA) - LF_FACESIZE);
176 WideCharToMultiByte(CP_ACP, 0, fontW->lfFaceName, -1, fontA->lfFaceName,
177 LF_FACESIZE, NULL, NULL);
178 fontA->lfFaceName[LF_FACESIZE-1] = 0;
181 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEXA fontA )
183 FONT_LogFontWToA( (const LOGFONTW *)fontW, (LPLOGFONTA)fontA);
185 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
186 (LPSTR) fontA->elfFullName, LF_FULLFACESIZE, NULL, NULL );
187 fontA->elfFullName[LF_FULLFACESIZE-1] = '\0';
188 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
189 (LPSTR) fontA->elfStyle, LF_FACESIZE, NULL, NULL );
190 fontA->elfStyle[LF_FACESIZE-1] = '\0';
191 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
192 (LPSTR) fontA->elfScript, LF_FACESIZE, NULL, NULL );
193 fontA->elfScript[LF_FACESIZE-1] = '\0';
196 /***********************************************************************
197 * TEXTMETRIC conversion functions.
199 static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
201 ptmA->tmHeight = ptmW->tmHeight;
202 ptmA->tmAscent = ptmW->tmAscent;
203 ptmA->tmDescent = ptmW->tmDescent;
204 ptmA->tmInternalLeading = ptmW->tmInternalLeading;
205 ptmA->tmExternalLeading = ptmW->tmExternalLeading;
206 ptmA->tmAveCharWidth = ptmW->tmAveCharWidth;
207 ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth;
208 ptmA->tmWeight = ptmW->tmWeight;
209 ptmA->tmOverhang = ptmW->tmOverhang;
210 ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX;
211 ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
212 ptmA->tmFirstChar = min(ptmW->tmFirstChar, 255);
213 if (ptmW->tmCharSet == SYMBOL_CHARSET)
215 ptmA->tmFirstChar = 0x1e;
216 ptmA->tmLastChar = 0xff; /* win9x behaviour - we need the OS2 table data to calculate correctly */
220 ptmA->tmFirstChar = ptmW->tmDefaultChar - 1;
221 ptmA->tmLastChar = min(ptmW->tmLastChar, 0xff);
223 ptmA->tmDefaultChar = ptmW->tmDefaultChar;
224 ptmA->tmBreakChar = ptmW->tmBreakChar;
225 ptmA->tmItalic = ptmW->tmItalic;
226 ptmA->tmUnderlined = ptmW->tmUnderlined;
227 ptmA->tmStruckOut = ptmW->tmStruckOut;
228 ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
229 ptmA->tmCharSet = ptmW->tmCharSet;
233 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW *ptmW, NEWTEXTMETRICEXA *ptmA )
235 FONT_TextMetricWToA((const TEXTMETRICW *)ptmW, (LPTEXTMETRICA)ptmA);
236 ptmA->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
237 ptmA->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
238 ptmA->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
239 ptmA->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
240 memcpy(&ptmA->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
244 /***********************************************************************
245 * GdiGetCodePage (GDI32.@)
247 DWORD WINAPI GdiGetCodePage( HDC hdc )
250 DC *dc = get_dc_ptr( hdc );
254 cp = dc->font_code_page;
255 release_dc_ptr( dc );
260 /***********************************************************************
263 * Returns a Unicode translation of str using the charset of the
264 * currently selected font in hdc. If count is -1 then str is assumed
265 * to be '\0' terminated, otherwise it contains the number of bytes to
266 * convert. If plenW is non-NULL, on return it will point to the
267 * number of WCHARs that have been written. If pCP is non-NULL, on
268 * return it will point to the codepage used in the conversion. The
269 * caller should free the returned LPWSTR from the process heap
272 static LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
278 cp = GdiGetCodePage( hdc );
280 if(count == -1) count = strlen(str);
281 lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
282 strW = HeapAlloc(GetProcessHeap(), 0, lenW*sizeof(WCHAR));
283 MultiByteToWideChar(cp, 0, str, count, strW, lenW);
284 TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW));
285 if(plenW) *plenW = lenW;
291 /***********************************************************************
292 * CreateFontIndirectA (GDI32.@)
294 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *plfA )
300 FONT_LogFontAToW( plfA, &lfW );
301 return CreateFontIndirectW( &lfW );
304 /***********************************************************************
305 * CreateFontIndirectW (GDI32.@)
307 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
314 if (!(fontPtr = HeapAlloc( GetProcessHeap(), 0, sizeof(*fontPtr) ))) return 0;
316 fontPtr->logfont = *plf;
318 if (plf->lfEscapement != plf->lfOrientation)
320 /* this should really depend on whether GM_ADVANCED is set */
321 fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
322 WARN("orientation angle %f set to "
323 "escapement angle %f for new font %p\n",
324 plf->lfOrientation/10., plf->lfEscapement/10., fontPtr);
327 if (!(hFont = alloc_gdi_handle( &fontPtr->header, OBJ_FONT, &font_funcs )))
329 HeapFree( GetProcessHeap(), 0, fontPtr );
333 TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
334 plf->lfHeight, plf->lfWidth,
335 plf->lfEscapement, plf->lfOrientation,
336 plf->lfPitchAndFamily,
337 plf->lfOutPrecision, plf->lfClipPrecision,
338 plf->lfQuality, plf->lfCharSet,
339 debugstr_w(plf->lfFaceName),
340 plf->lfWeight > 400 ? "Bold" : "",
341 plf->lfItalic ? "Italic" : "",
342 plf->lfUnderline ? "Underline" : "", hFont);
347 /*************************************************************************
348 * CreateFontA (GDI32.@)
350 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
351 INT orient, INT weight, DWORD italic,
352 DWORD underline, DWORD strikeout, DWORD charset,
353 DWORD outpres, DWORD clippres, DWORD quality,
354 DWORD pitch, LPCSTR name )
358 logfont.lfHeight = height;
359 logfont.lfWidth = width;
360 logfont.lfEscapement = esc;
361 logfont.lfOrientation = orient;
362 logfont.lfWeight = weight;
363 logfont.lfItalic = italic;
364 logfont.lfUnderline = underline;
365 logfont.lfStrikeOut = strikeout;
366 logfont.lfCharSet = charset;
367 logfont.lfOutPrecision = outpres;
368 logfont.lfClipPrecision = clippres;
369 logfont.lfQuality = quality;
370 logfont.lfPitchAndFamily = pitch;
373 lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
375 logfont.lfFaceName[0] = '\0';
377 return CreateFontIndirectA( &logfont );
380 /*************************************************************************
381 * CreateFontW (GDI32.@)
383 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
384 INT orient, INT weight, DWORD italic,
385 DWORD underline, DWORD strikeout, DWORD charset,
386 DWORD outpres, DWORD clippres, DWORD quality,
387 DWORD pitch, LPCWSTR name )
391 logfont.lfHeight = height;
392 logfont.lfWidth = width;
393 logfont.lfEscapement = esc;
394 logfont.lfOrientation = orient;
395 logfont.lfWeight = weight;
396 logfont.lfItalic = italic;
397 logfont.lfUnderline = underline;
398 logfont.lfStrikeOut = strikeout;
399 logfont.lfCharSet = charset;
400 logfont.lfOutPrecision = outpres;
401 logfont.lfClipPrecision = clippres;
402 logfont.lfQuality = quality;
403 logfont.lfPitchAndFamily = pitch;
406 lstrcpynW(logfont.lfFaceName, name,
407 sizeof(logfont.lfFaceName) / sizeof(WCHAR));
409 logfont.lfFaceName[0] = '\0';
411 return CreateFontIndirectW( &logfont );
414 static void update_font_code_page( DC *dc )
417 int charset = DEFAULT_CHARSET;
420 charset = WineEngGetTextCharsetInfo( dc->gdiFont, NULL, 0 );
422 /* Hmm, nicely designed api this one! */
423 if (TranslateCharsetInfo( ULongToPtr(charset), &csi, TCI_SRCCHARSET) )
424 dc->font_code_page = csi.ciACP;
428 dc->font_code_page = GetOEMCP();
430 case DEFAULT_CHARSET:
431 dc->font_code_page = GetACP();
441 /* FIXME: These have no place here, but because x11drv
442 enumerates fonts with these (made up) charsets some apps
443 might use them and then the FIXME below would become
444 annoying. Now we could pick the intended codepage for
445 each of these, but since it's broken anyway we'll just
446 use CP_ACP and hope it'll go away...
448 dc->font_code_page = CP_ACP;
452 FIXME("Can't find codepage for charset %d\n", charset);
453 dc->font_code_page = CP_ACP;
458 TRACE("charset %d => cp %d\n", charset, dc->font_code_page);
461 /***********************************************************************
464 * If the driver supports vector fonts we create a gdi font first and
465 * then call the driver to give it a chance to supply its own device
466 * font. If the driver wants to do this it returns TRUE and we can
467 * delete the gdi font, if the driver wants to use the gdi font it
468 * should return FALSE, to signal an error return GDI_ERROR. For
469 * drivers that don't support vector fonts they must supply their own
472 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc )
475 DC *dc = get_dc_ptr( hdc );
479 if (!GDI_inc_ref_count( handle ))
481 release_dc_ptr( dc );
485 if (GetDeviceCaps( dc->hSelf, TEXTCAPS ) & TC_VA_ABLE)
486 dc->gdiFont = WineEngCreateFontInstance( dc, handle );
488 if (dc->funcs->pSelectFont) ret = dc->funcs->pSelectFont( dc->physDev, handle, dc->gdiFont );
490 if (ret && dc->gdiFont) dc->gdiFont = 0;
492 if (ret == HGDI_ERROR)
494 GDI_dec_ref_count( handle );
495 ret = 0; /* SelectObject returns 0 on error */
501 update_font_code_page( dc );
502 GDI_dec_ref_count( ret );
504 release_dc_ptr( dc );
509 /***********************************************************************
512 static INT FONT_GetObjectA( HGDIOBJ handle, INT count, LPVOID buffer )
514 FONTOBJ *font = GDI_GetObjPtr( handle, OBJ_FONT );
520 FONT_LogFontWToA( &font->logfont, &lfA );
521 if (count > sizeof(lfA)) count = sizeof(lfA);
522 memcpy( buffer, &lfA, count );
524 else count = sizeof(lfA);
525 GDI_ReleaseObj( handle );
529 /***********************************************************************
532 static INT FONT_GetObjectW( HGDIOBJ handle, INT count, LPVOID buffer )
534 FONTOBJ *font = GDI_GetObjPtr( handle, OBJ_FONT );
539 if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
540 memcpy( buffer, &font->logfont, count );
542 else count = sizeof(LOGFONTW);
543 GDI_ReleaseObj( handle );
548 /***********************************************************************
551 static BOOL FONT_DeleteObject( HGDIOBJ handle )
555 WineEngDestroyFontInstance( handle );
557 if (!(obj = free_gdi_handle( handle ))) return FALSE;
558 return HeapFree( GetProcessHeap(), 0, obj );
562 /***********************************************************************
565 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
566 * We have to use other types because of the FONTENUMPROCW definition.
568 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
569 DWORD fType, LPARAM lp )
571 fontEnum32 *pfe = (fontEnum32*)lp;
574 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
575 if ((!pfe->lpLogFontParam ||
576 pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
577 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
578 (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
580 /* convert font metrics */
581 ENUMLOGFONTEXA logfont;
582 NEWTEXTMETRICEXA tmA;
584 pfe->dwFlags |= ENUM_CALLED;
585 if (!(pfe->dwFlags & ENUM_UNICODE))
587 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
588 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
589 plf = (LOGFONTW *)&logfont.elfLogFont;
590 ptm = (TEXTMETRICW *)&tmA;
593 ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
598 /***********************************************************************
599 * FONT_EnumFontFamiliesEx
601 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf,
602 FONTENUMPROCW efproc,
603 LPARAM lParam, DWORD dwUnicode)
606 DC *dc = get_dc_ptr( hDC );
613 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName),
615 fe32.lpLogFontParam = plf;
616 fe32.lpEnumFunc = efproc;
617 fe32.lpData = lParam;
618 fe32.dwFlags = dwUnicode;
621 enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE;
623 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
630 ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
631 fe32.dwFlags &= ~ENUM_CALLED;
632 if (ret && dc->funcs->pEnumDeviceFonts) {
633 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, plf, FONT_EnumInstance, (LPARAM)&fe32 );
634 if(fe32.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
638 release_dc_ptr( dc );
642 /***********************************************************************
643 * EnumFontFamiliesExW (GDI32.@)
645 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
646 FONTENUMPROCW efproc,
647 LPARAM lParam, DWORD dwFlags )
649 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, ENUM_UNICODE );
652 /***********************************************************************
653 * EnumFontFamiliesExA (GDI32.@)
655 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
656 FONTENUMPROCA efproc,
657 LPARAM lParam, DWORD dwFlags)
663 FONT_LogFontAToW( plf, &lfW );
668 return FONT_EnumFontFamiliesEx( hDC, plfW, (FONTENUMPROCW)efproc, lParam, 0);
671 /***********************************************************************
672 * EnumFontFamiliesA (GDI32.@)
674 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
675 FONTENUMPROCA efproc, LPARAM lpData )
681 if (!*lpFamily) return 1;
682 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
683 lf.lfCharSet = DEFAULT_CHARSET;
684 lf.lfPitchAndFamily = 0;
689 return EnumFontFamiliesExA( hDC, plf, efproc, lpData, 0 );
692 /***********************************************************************
693 * EnumFontFamiliesW (GDI32.@)
695 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
696 FONTENUMPROCW efproc, LPARAM lpData )
702 if (!*lpFamily) return 1;
703 lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
704 lf.lfCharSet = DEFAULT_CHARSET;
705 lf.lfPitchAndFamily = 0;
710 return EnumFontFamiliesExW( hDC, plf, efproc, lpData, 0 );
713 /***********************************************************************
714 * EnumFontsA (GDI32.@)
716 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
719 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
722 /***********************************************************************
723 * EnumFontsW (GDI32.@)
725 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
728 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
732 /***********************************************************************
733 * GetTextCharacterExtra (GDI32.@)
735 INT WINAPI GetTextCharacterExtra( HDC hdc )
738 DC *dc = get_dc_ptr( hdc );
739 if (!dc) return 0x80000000;
741 release_dc_ptr( dc );
746 /***********************************************************************
747 * SetTextCharacterExtra (GDI32.@)
749 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
752 DC * dc = get_dc_ptr( hdc );
753 if (!dc) return 0x80000000;
754 if (dc->funcs->pSetTextCharacterExtra)
755 prev = dc->funcs->pSetTextCharacterExtra( dc->physDev, extra );
758 prev = dc->charExtra;
759 dc->charExtra = extra;
761 release_dc_ptr( dc );
766 /***********************************************************************
767 * SetTextJustification (GDI32.@)
769 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
772 DC * dc = get_dc_ptr( hdc );
773 if (!dc) return FALSE;
774 if (dc->funcs->pSetTextJustification)
775 ret = dc->funcs->pSetTextJustification( dc->physDev, extra, breaks );
778 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
779 if (!extra) breaks = 0;
782 dc->breakExtra = extra / breaks;
783 dc->breakRem = extra - (breaks * dc->breakExtra);
791 release_dc_ptr( dc );
796 /***********************************************************************
797 * GetTextFaceA (GDI32.@)
799 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
801 INT res = GetTextFaceW(hdc, 0, NULL);
802 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
803 GetTextFaceW( hdc, res, nameW );
809 res = WideCharToMultiByte(CP_ACP, 0, nameW, -1, name, count, NULL, NULL);
813 /* GetTextFaceA does NOT include the nul byte in the return count. */
820 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
821 HeapFree( GetProcessHeap(), 0, nameW );
825 /***********************************************************************
826 * GetTextFaceW (GDI32.@)
828 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
833 DC * dc = get_dc_ptr( hdc );
837 ret = WineEngGetTextFace(dc->gdiFont, count, name);
838 else if ((font = GDI_GetObjPtr( dc->hFont, OBJ_FONT )))
840 INT n = strlenW(font->logfont.lfFaceName) + 1;
843 lstrcpynW( name, font->logfont.lfFaceName, count );
847 GDI_ReleaseObj( dc->hFont );
849 release_dc_ptr( dc );
854 /***********************************************************************
855 * GetTextExtentPoint32A (GDI32.@)
857 * See GetTextExtentPoint32W.
859 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
864 LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
867 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
868 HeapFree( GetProcessHeap(), 0, p );
871 TRACE("(%p %s %d %p): returning %d x %d\n",
872 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
877 /***********************************************************************
878 * GetTextExtentPoint32W [GDI32.@]
880 * Computes width/height for a string.
882 * Computes width and height of the specified string.
888 BOOL WINAPI GetTextExtentPoint32W(
889 HDC hdc, /* [in] Handle of device context */
890 LPCWSTR str, /* [in] Address of text string */
891 INT count, /* [in] Number of characters in string */
892 LPSIZE size) /* [out] Address of structure for string size */
894 return GetTextExtentExPointW(hdc, str, count, 0, NULL, NULL, size);
897 /***********************************************************************
898 * GetTextExtentExPointI [GDI32.@]
900 * Computes width and height of the array of glyph indices.
903 * hdc [I] Handle of device context.
904 * indices [I] Glyph index array.
905 * count [I] Number of glyphs in array.
906 * max_ext [I] Maximum width in glyphs.
907 * nfit [O] Maximum number of characters.
908 * dxs [O] Partial string widths.
909 * size [O] Returned string size.
915 BOOL WINAPI GetTextExtentExPointI( HDC hdc, const WORD *indices, INT count, INT max_ext,
916 LPINT nfit, LPINT dxs, LPSIZE size )
919 DC * dc = get_dc_ptr( hdc );
920 if (!dc) return FALSE;
923 ret = WineEngGetTextExtentExPointI(dc->gdiFont, indices, count, max_ext, nfit, dxs, size);
924 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
925 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
926 size->cx += count * dc->charExtra;
928 else if(dc->funcs->pGetTextExtentExPoint) {
929 FIXME("calling GetTextExtentExPoint\n");
930 ret = dc->funcs->pGetTextExtentExPoint( dc->physDev, indices, count,
931 max_ext, nfit, dxs, size );
934 release_dc_ptr( dc );
936 TRACE("(%p %p %d %p): returning %d x %d\n",
937 hdc, indices, count, size, size->cx, size->cy );
941 /***********************************************************************
942 * GetTextExtentPointI [GDI32.@]
944 * Computes width and height of the array of glyph indices.
947 * hdc [I] Handle of device context.
948 * indices [I] Glyph index array.
949 * count [I] Number of glyphs in array.
950 * size [O] Returned string size.
956 BOOL WINAPI GetTextExtentPointI( HDC hdc, const WORD *indices, INT count, LPSIZE size )
958 return GetTextExtentExPointI( hdc, indices, count, 0, NULL, NULL, size );
962 /***********************************************************************
963 * GetTextExtentPointA (GDI32.@)
965 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
968 TRACE("not bug compatible.\n");
969 return GetTextExtentPoint32A( hdc, str, count, size );
972 /***********************************************************************
973 * GetTextExtentPointW (GDI32.@)
975 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
978 TRACE("not bug compatible.\n");
979 return GetTextExtentPoint32W( hdc, str, count, size );
983 /***********************************************************************
984 * GetTextExtentExPointA (GDI32.@)
986 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
987 INT maxExt, LPINT lpnFit,
988 LPINT alpDx, LPSIZE size )
996 NULL == (walpDx = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT))))
999 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1000 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
1003 INT n = lpnFit ? *lpnFit : wlen;
1005 for(i = 0, j = 0; i < n; i++, j++)
1007 alpDx[j] = walpDx[i];
1008 if (IsDBCSLeadByte(str[j])) alpDx[++j] = walpDx[i];
1011 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1012 HeapFree( GetProcessHeap(), 0, p );
1013 HeapFree( GetProcessHeap(), 0, walpDx );
1018 /***********************************************************************
1019 * GetTextExtentExPointW (GDI32.@)
1021 * Return the size of the string as it would be if it was output properly by
1024 * This should include
1025 * - Intercharacter spacing
1026 * - justification spacing (not yet done)
1027 * - kerning? see below
1029 * Kerning. Since kerning would be carried out by the rendering code it should
1030 * be done by the driver. However they don't support it yet. Also I am not
1031 * yet persuaded that (certainly under Win95) any kerning is actually done.
1033 * str: According to MSDN this should be null-terminated. That is not true; a
1034 * null will not terminate it early.
1035 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1036 * than count. I have seen it be either the size of the full string or
1037 * 1 less than the size of the full string. I have not seen it bear any
1038 * resemblance to the portion that would fit.
1039 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1040 * trailing intercharacter spacing and any trailing justification.
1043 * Currently we do this by measuring each character etc. We should do it by
1044 * passing the request to the driver, perhaps by extending the
1045 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1046 * thinking about kerning issues and rounding issues in the justification.
1049 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1050 INT maxExt, LPINT lpnFit,
1051 LPINT alpDx, LPSIZE size )
1059 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1061 dc = get_dc_ptr(hdc);
1065 GetTextMetricsW(hdc, &tm);
1067 /* If we need to calculate nFit, then we need the partial extents even if
1068 the user hasn't provided us with an array. */
1071 dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]);
1075 SetLastError(ERROR_OUTOFMEMORY);
1083 ret = WineEngGetTextExtentExPoint(dc->gdiFont, str, count,
1084 0, NULL, dxs, size);
1085 else if (dc->funcs->pGetTextExtentExPoint)
1086 ret = dc->funcs->pGetTextExtentExPoint(dc->physDev, str, count,
1087 0, NULL, dxs, size);
1089 /* Perform device size to world size transformations. */
1092 INT extra = dc->charExtra,
1093 breakExtra = dc->breakExtra,
1094 breakRem = dc->breakRem,
1099 for (i = 0; i < count; ++i)
1101 dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
1102 dxs[i] += (i+1) * extra;
1103 if (count > 1 && (breakExtra || breakRem) && str[i] == tm.tmBreakChar)
1105 dxs[i] += breakExtra;
1112 if (dxs[i] <= maxExt)
1115 breakRem = dc->breakRem;
1117 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1118 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1120 if (!dxs && count > 1 && (breakExtra || breakRem))
1122 for (i = 0; i < count; i++)
1124 if (str[i] == tm.tmBreakChar)
1126 size->cx += breakExtra;
1141 HeapFree(GetProcessHeap(), 0, dxs);
1143 release_dc_ptr( dc );
1145 TRACE("returning %d %d x %d\n",nFit,size->cx,size->cy);
1149 /***********************************************************************
1150 * GetTextMetricsA (GDI32.@)
1152 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1156 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1157 FONT_TextMetricWToA( &tm32, metrics );
1161 /***********************************************************************
1162 * GetTextMetricsW (GDI32.@)
1164 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1167 DC * dc = get_dc_ptr( hdc );
1168 if (!dc) return FALSE;
1171 ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1172 else if (dc->funcs->pGetTextMetrics)
1173 ret = dc->funcs->pGetTextMetrics( dc->physDev, metrics );
1177 /* device layer returns values in device units
1178 * therefore we have to convert them to logical */
1180 metrics->tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1181 metrics->tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1183 #define WDPTOLP(x) ((x<0)? \
1184 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1185 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1186 #define HDPTOLP(y) ((y<0)? \
1187 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1188 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1190 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1191 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1192 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1193 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1194 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1195 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1196 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1197 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1201 TRACE("text metrics:\n"
1202 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1203 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1204 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1205 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1206 " PitchAndFamily = %02x\n"
1207 " --------------------\n"
1208 " InternalLeading = %i\n"
1212 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1213 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1214 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1215 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1216 metrics->tmPitchAndFamily,
1217 metrics->tmInternalLeading,
1220 metrics->tmHeight );
1222 release_dc_ptr( dc );
1227 /***********************************************************************
1228 * GetOutlineTextMetricsA (GDI32.@)
1229 * Gets metrics for TrueType fonts.
1232 * If the supplied buffer isn't big enough Windows partially fills it up to
1233 * its given length and returns that length.
1236 * Success: Non-zero or size of required buffer
1239 UINT WINAPI GetOutlineTextMetricsA(
1240 HDC hdc, /* [in] Handle of device context */
1241 UINT cbData, /* [in] Size of metric data array */
1242 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1244 char buf[512], *ptr;
1246 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1247 OUTLINETEXTMETRICA *output = lpOTM;
1250 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1252 if(ret > sizeof(buf))
1253 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1254 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1256 needed = sizeof(OUTLINETEXTMETRICA);
1257 if(lpOTMW->otmpFamilyName)
1258 needed += WideCharToMultiByte(CP_ACP, 0,
1259 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1260 NULL, 0, NULL, NULL);
1261 if(lpOTMW->otmpFaceName)
1262 needed += WideCharToMultiByte(CP_ACP, 0,
1263 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1264 NULL, 0, NULL, NULL);
1265 if(lpOTMW->otmpStyleName)
1266 needed += WideCharToMultiByte(CP_ACP, 0,
1267 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1268 NULL, 0, NULL, NULL);
1269 if(lpOTMW->otmpFullName)
1270 needed += WideCharToMultiByte(CP_ACP, 0,
1271 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1272 NULL, 0, NULL, NULL);
1279 TRACE("needed = %d\n", needed);
1281 /* Since the supplied buffer isn't big enough, we'll alloc one
1282 that is and memcpy the first cbData bytes into the lpOTM at
1284 output = HeapAlloc(GetProcessHeap(), 0, needed);
1286 ret = output->otmSize = min(needed, cbData);
1287 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1288 output->otmFiller = 0;
1289 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1290 output->otmfsSelection = lpOTMW->otmfsSelection;
1291 output->otmfsType = lpOTMW->otmfsType;
1292 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1293 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1294 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1295 output->otmEMSquare = lpOTMW->otmEMSquare;
1296 output->otmAscent = lpOTMW->otmAscent;
1297 output->otmDescent = lpOTMW->otmDescent;
1298 output->otmLineGap = lpOTMW->otmLineGap;
1299 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1300 output->otmsXHeight = lpOTMW->otmsXHeight;
1301 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1302 output->otmMacAscent = lpOTMW->otmMacAscent;
1303 output->otmMacDescent = lpOTMW->otmMacDescent;
1304 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1305 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1306 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1307 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1308 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1309 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1310 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1311 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1312 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1313 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1316 ptr = (char*)(output + 1);
1317 left = needed - sizeof(*output);
1319 if(lpOTMW->otmpFamilyName) {
1320 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1321 len = WideCharToMultiByte(CP_ACP, 0,
1322 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1323 ptr, left, NULL, NULL);
1327 output->otmpFamilyName = 0;
1329 if(lpOTMW->otmpFaceName) {
1330 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1331 len = WideCharToMultiByte(CP_ACP, 0,
1332 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1333 ptr, left, NULL, NULL);
1337 output->otmpFaceName = 0;
1339 if(lpOTMW->otmpStyleName) {
1340 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1341 len = WideCharToMultiByte(CP_ACP, 0,
1342 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1343 ptr, left, NULL, NULL);
1347 output->otmpStyleName = 0;
1349 if(lpOTMW->otmpFullName) {
1350 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1351 len = WideCharToMultiByte(CP_ACP, 0,
1352 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1353 ptr, left, NULL, NULL);
1356 output->otmpFullName = 0;
1360 if(output != lpOTM) {
1361 memcpy(lpOTM, output, cbData);
1362 HeapFree(GetProcessHeap(), 0, output);
1364 /* check if the string offsets really fit into the provided size */
1365 /* FIXME: should we check string length as well? */
1366 /* make sure that we don't read/write beyond the provided buffer */
1367 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(LPSTR))
1369 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1370 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1373 /* make sure that we don't read/write beyond the provided buffer */
1374 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(LPSTR))
1376 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1377 lpOTM->otmpFaceName = 0; /* doesn't fit */
1380 /* make sure that we don't read/write beyond the provided buffer */
1381 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(LPSTR))
1383 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1384 lpOTM->otmpStyleName = 0; /* doesn't fit */
1387 /* make sure that we don't read/write beyond the provided buffer */
1388 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(LPSTR))
1390 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1391 lpOTM->otmpFullName = 0; /* doesn't fit */
1396 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1397 HeapFree(GetProcessHeap(), 0, lpOTMW);
1403 /***********************************************************************
1404 * GetOutlineTextMetricsW [GDI32.@]
1406 UINT WINAPI GetOutlineTextMetricsW(
1407 HDC hdc, /* [in] Handle of device context */
1408 UINT cbData, /* [in] Size of metric data array */
1409 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1411 DC *dc = get_dc_ptr( hdc );
1412 OUTLINETEXTMETRICW *output = lpOTM;
1415 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1419 ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, output);
1422 output = HeapAlloc(GetProcessHeap(), 0, ret);
1423 WineEngGetOutlineTextMetrics(dc->gdiFont, ret, output);
1426 output->otmTextMetrics.tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1427 output->otmTextMetrics.tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1429 #define WDPTOLP(x) ((x<0)? \
1430 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1431 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1432 #define HDPTOLP(y) ((y<0)? \
1433 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1434 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1436 output->otmTextMetrics.tmHeight = HDPTOLP(output->otmTextMetrics.tmHeight);
1437 output->otmTextMetrics.tmAscent = HDPTOLP(output->otmTextMetrics.tmAscent);
1438 output->otmTextMetrics.tmDescent = HDPTOLP(output->otmTextMetrics.tmDescent);
1439 output->otmTextMetrics.tmInternalLeading = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1440 output->otmTextMetrics.tmExternalLeading = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1441 output->otmTextMetrics.tmAveCharWidth = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1442 output->otmTextMetrics.tmMaxCharWidth = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1443 output->otmTextMetrics.tmOverhang = WDPTOLP(output->otmTextMetrics.tmOverhang);
1444 output->otmAscent = HDPTOLP(output->otmAscent);
1445 output->otmDescent = HDPTOLP(output->otmDescent);
1446 output->otmLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmLineGap));
1447 output->otmsCapEmHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsCapEmHeight));
1448 output->otmsXHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsXHeight));
1449 output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1450 output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1451 output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1452 output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1453 output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1454 output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1455 output->otmMacLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmMacLineGap));
1456 output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1457 output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1458 output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1459 output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1460 output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1461 output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1462 output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1463 output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1464 output->otmsStrikeoutSize = abs(INTERNAL_YDSTOWS(dc,output->otmsStrikeoutSize));
1465 output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1466 output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1467 output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1470 if(output != lpOTM) {
1471 memcpy(lpOTM, output, cbData);
1472 HeapFree(GetProcessHeap(), 0, output);
1478 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1479 but really this should just be a return 0. */
1481 ret = sizeof(*lpOTM);
1486 memset(lpOTM, 0, ret);
1487 lpOTM->otmSize = sizeof(*lpOTM);
1488 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1490 Further fill of the structure not implemented,
1491 Needs real values for the structure members
1501 /***********************************************************************
1502 * GetCharWidthW (GDI32.@)
1503 * GetCharWidth32W (GDI32.@)
1505 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1510 DC * dc = get_dc_ptr( hdc );
1511 if (!dc) return FALSE;
1514 ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1515 else if (dc->funcs->pGetCharWidth)
1516 ret = dc->funcs->pGetCharWidth( dc->physDev, firstChar, lastChar, buffer);
1520 /* convert device units to logical */
1521 for( i = firstChar; i <= lastChar; i++, buffer++ )
1522 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1525 release_dc_ptr( dc );
1530 /***********************************************************************
1531 * GetCharWidthA (GDI32.@)
1532 * GetCharWidth32A (GDI32.@)
1534 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1537 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1542 if(count <= 0) return FALSE;
1544 str = HeapAlloc(GetProcessHeap(), 0, count);
1545 for(i = 0; i < count; i++)
1546 str[i] = (BYTE)(firstChar + i);
1548 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1550 for(i = 0; i < wlen; i++)
1552 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1560 HeapFree(GetProcessHeap(), 0, str);
1561 HeapFree(GetProcessHeap(), 0, wstr);
1567 /***********************************************************************
1568 * ExtTextOutA (GDI32.@)
1572 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1573 const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1581 if (flags & ETO_GLYPH_INDEX)
1582 return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
1584 p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
1587 unsigned int i = 0, j = 0;
1589 /* allocate enough for a ETO_PDY */
1590 lpDxW = HeapAlloc( GetProcessHeap(), 0, 2*wlen*sizeof(INT));
1592 if(IsDBCSLeadByteEx(codepage, str[i]))
1596 lpDxW[j++] = lpDx[i * 2] + lpDx[(i + 1) * 2];
1597 lpDxW[j++] = lpDx[i * 2 + 1] + lpDx[(i + 1) * 2 + 1];
1600 lpDxW[j++] = lpDx[i] + lpDx[i + 1];
1607 lpDxW[j++] = lpDx[i * 2];
1608 lpDxW[j++] = lpDx[i * 2 + 1];
1611 lpDxW[j++] = lpDx[i];
1617 ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1619 HeapFree( GetProcessHeap(), 0, p );
1620 HeapFree( GetProcessHeap(), 0, lpDxW );
1625 /***********************************************************************
1626 * ExtTextOutW (GDI32.@)
1628 * Draws text using the currently selected font, background color, and text color.
1632 * x,y [I] coordinates of string
1634 * ETO_GRAYED - undocumented on MSDN
1635 * ETO_OPAQUE - use background color for fill the rectangle
1636 * ETO_CLIPPED - clipping text to the rectangle
1637 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1638 * than encoded characters. Implies ETO_IGNORELANGUAGE
1639 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1640 * Affects BiDi ordering
1641 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1642 * ETO_PDY - unimplemented
1643 * ETO_NUMERICSLATIN - unimplemented always assumed -
1644 * do not translate numbers into locale representations
1645 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1646 * lprect [I] dimensions for clipping or/and opaquing
1647 * str [I] text string
1648 * count [I] number of symbols in string
1649 * lpDx [I] optional parameter with distance between drawing characters
1655 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1656 const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1659 LPWSTR reordered_str = (LPWSTR)str;
1660 WORD *glyphs = NULL;
1661 UINT align = GetTextAlign( hdc );
1665 double cosEsc, sinEsc;
1669 BOOL done_extents = FALSE;
1670 POINT *deltas = NULL, width = {0, 0};
1672 DC * dc = get_dc_ptr( hdc );
1674 static int quietfixme = 0;
1676 if (!dc) return FALSE;
1678 breakRem = dc->breakRem;
1680 if (quietfixme == 0 && flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN))
1682 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN unimplemented\n");
1685 if (!dc->funcs->pExtTextOut && !PATH_IsPathOpen(dc->path))
1687 release_dc_ptr( dc );
1692 type = GetObjectType(hdc);
1693 if(type == OBJ_METADC || type == OBJ_ENHMETADC)
1695 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, flags, lprect, str, count, lpDx);
1696 release_dc_ptr( dc );
1701 flags &= ~ETO_CLIPPED;
1703 if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && count > 0 )
1705 reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1707 BIDI_Reorder( hdc, str, count, GCP_REORDER,
1708 ((flags&ETO_RTLREADING)!=0 || (GetTextAlign(hdc)&TA_RTLREADING)!=0)?
1709 WINE_GCPW_FORCE_RTL:WINE_GCPW_FORCE_LTR,
1710 reordered_str, count, NULL, &glyphs );
1712 flags |= ETO_IGNORELANGUAGE;
1714 flags |= ETO_GLYPH_INDEX;
1716 else if(flags & ETO_GLYPH_INDEX)
1717 glyphs = reordered_str;
1719 TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc, x, y, flags,
1720 lprect, debugstr_wn(str, count), count, lpDx);
1723 TRACE("rect: %d,%d - %d,%d\n", lprect->left, lprect->top, lprect->right,
1725 TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
1727 if(align & TA_UPDATECP)
1729 GetCurrentPositionEx( hdc, &pt );
1734 GetTextMetricsW(hdc, &tm);
1735 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1737 if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
1738 lf.lfEscapement = 0;
1740 if(lf.lfEscapement != 0)
1742 cosEsc = cos(lf.lfEscapement * M_PI / 1800);
1743 sinEsc = sin(lf.lfEscapement * M_PI / 1800);
1751 if(flags & (ETO_CLIPPED | ETO_OPAQUE))
1755 if(flags & ETO_GLYPH_INDEX)
1756 GetTextExtentPointI(hdc, glyphs, count, &sz);
1758 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1760 done_extents = TRUE;
1763 rc.right = x + sz.cx;
1764 rc.bottom = y + sz.cy;
1771 LPtoDP(hdc, (POINT*)&rc, 2);
1773 if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
1774 if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
1777 if ((flags & ETO_OPAQUE) && !PATH_IsPathOpen(dc->path))
1778 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1788 LPtoDP(hdc, &pt, 1);
1792 char_extra = GetTextCharacterExtra(hdc);
1793 if(char_extra || dc->breakExtra || breakRem || lpDx || lf.lfEscapement != 0)
1797 POINT total = {0, 0}, desired[2];
1799 deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
1800 for(i = 0; i < count; i++)
1806 deltas[i].x = lpDx[i * 2] + char_extra;
1807 deltas[i].y = -lpDx[i * 2 + 1];
1811 deltas[i].x = lpDx[i] + char_extra;
1818 if(flags & ETO_GLYPH_INDEX)
1819 GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
1821 GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
1823 deltas[i].x = tmpsz.cx;
1827 if (!(flags & ETO_GLYPH_INDEX) && (dc->breakExtra || breakRem) && reordered_str[i] == tm.tmBreakChar)
1829 deltas[i].x = deltas[i].x + dc->breakExtra;
1836 total.x += deltas[i].x;
1837 total.y += deltas[i].y;
1839 desired[0].x = desired[0].y = 0;
1841 desired[1].x = cosEsc * total.x + sinEsc * total.y;
1842 desired[1].y = -sinEsc * total.x + cosEsc * total.y;
1844 LPtoDP(hdc, desired, 2);
1845 desired[1].x -= desired[0].x;
1846 desired[1].y -= desired[0].y;
1848 deltas[i].x = desired[1].x - width.x;
1849 deltas[i].y = desired[1].y - width.y;
1859 if(flags & ETO_GLYPH_INDEX)
1860 GetTextExtentPointI(hdc, glyphs, count, &sz);
1862 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1863 done_extents = TRUE;
1865 width.x = INTERNAL_XWSTODS(dc, sz.cx);
1869 tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
1870 tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
1871 switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
1874 if (align & TA_UPDATECP)
1878 DPtoLP(hdc, &pt, 1);
1879 MoveToEx(hdc, pt.x, pt.y, NULL);
1891 if (align & TA_UPDATECP)
1895 DPtoLP(hdc, &pt, 1);
1896 MoveToEx(hdc, pt.x, pt.y, NULL);
1901 switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
1904 y += tm.tmAscent * cosEsc;
1905 x += tm.tmAscent * sinEsc;
1909 y -= tm.tmDescent * cosEsc;
1910 x -= tm.tmDescent * sinEsc;
1917 if (GetBkMode(hdc) != TRANSPARENT && !PATH_IsPathOpen(dc->path))
1919 if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
1921 if(!(flags & ETO_OPAQUE) || x < rc.left || x + width.x >= rc.right ||
1922 y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
1926 rc.right = x + width.x;
1927 rc.top = y - tm.tmAscent;
1928 rc.bottom = y + tm.tmDescent;
1929 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1934 if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
1936 HFONT orig_font = dc->hFont, cur_font;
1939 POINT *offsets = NULL;
1942 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
1943 for(i = 0; i < count; i++)
1945 WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
1946 if(cur_font != dc->hFont)
1951 offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
1952 offsets[0].x = offsets[0].y = 0;
1957 for(j = 1; j < count; j++)
1959 GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
1960 offsets[j].x = offsets[j - 1].x + INTERNAL_XWSTODS(dc, tmpsz.cx);
1966 for(j = 1; j < count; j++)
1968 offsets[j].x = offsets[j - 1].x + deltas[j].x;
1969 offsets[j].y = offsets[j - 1].y + deltas[j].y;
1975 if (PATH_IsPathOpen(dc->path))
1976 ret = PATH_ExtTextOut(dc, x + offsets[i - span].x, y + offsets[i - span].y,
1977 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
1978 glyphs, span, deltas ? (INT*)(deltas + (i - span)) : NULL);
1980 dc->funcs->pExtTextOut(dc->physDev, x + offsets[i - span].x, y + offsets[i - span].y,
1981 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
1982 glyphs, span, deltas ? (INT*)(deltas + (i - span)) : NULL);
1985 SelectObject(hdc, cur_font);
1987 glyphs[span++] = glyph;
1991 if (PATH_IsPathOpen(dc->path))
1992 ret = PATH_ExtTextOut(dc, x + (offsets ? offsets[count - span].x : 0),
1993 y + (offsets ? offsets[count - span].y : 0),
1994 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
1995 glyphs, span, deltas ? (INT*)(deltas + (count - span)) : NULL);
1997 ret = dc->funcs->pExtTextOut(dc->physDev, x + (offsets ? offsets[count - span].x : 0),
1998 y + (offsets ? offsets[count - span].y : 0),
1999 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2000 glyphs, span, deltas ? (INT*)(deltas + (count - span)) : NULL);
2001 SelectObject(hdc, orig_font);
2002 HeapFree(GetProcessHeap(), 0, offsets);
2008 if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
2010 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2011 GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
2012 flags |= ETO_GLYPH_INDEX;
2015 if (PATH_IsPathOpen(dc->path))
2016 ret = PATH_ExtTextOut(dc, x, y, (flags & ~ETO_OPAQUE), &rc,
2017 glyphs ? glyphs : reordered_str, count, (INT*)deltas);
2019 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, (flags & ~ETO_OPAQUE), &rc,
2020 glyphs ? glyphs : reordered_str, count, (INT*)deltas);
2024 HeapFree(GetProcessHeap(), 0, deltas);
2025 if(glyphs != reordered_str)
2026 HeapFree(GetProcessHeap(), 0, glyphs);
2027 if(reordered_str != str)
2028 HeapFree(GetProcessHeap(), 0, reordered_str);
2030 release_dc_ptr( dc );
2032 if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2034 int underlinePos, strikeoutPos;
2035 int underlineWidth, strikeoutWidth;
2036 UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2037 OUTLINETEXTMETRICW* otm = NULL;
2042 underlineWidth = tm.tmAscent / 20 + 1;
2043 strikeoutPos = tm.tmAscent / 2;
2044 strikeoutWidth = underlineWidth;
2048 otm = HeapAlloc(GetProcessHeap(), 0, size);
2049 GetOutlineTextMetricsW(hdc, size, otm);
2050 underlinePos = otm->otmsUnderscorePosition;
2051 underlineWidth = otm->otmsUnderscoreSize;
2052 strikeoutPos = otm->otmsStrikeoutPosition;
2053 strikeoutWidth = otm->otmsStrikeoutSize;
2054 HeapFree(GetProcessHeap(), 0, otm);
2057 if (PATH_IsPathOpen(dc->path))
2061 HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2063 hbrush = SelectObject(hdc, hbrush);
2064 hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2068 pts[0].x = x - underlinePos * sinEsc;
2069 pts[0].y = y - underlinePos * cosEsc;
2070 pts[1].x = x + width.x - underlinePos * sinEsc;
2071 pts[1].y = y - width.y - underlinePos * cosEsc;
2072 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2073 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2074 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2075 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2076 pts[4].x = pts[0].x;
2077 pts[4].y = pts[0].y;
2078 DPtoLP(hdc, pts, 5);
2079 Polygon(hdc, pts, 5);
2084 pts[0].x = x - strikeoutPos * sinEsc;
2085 pts[0].y = y - strikeoutPos * cosEsc;
2086 pts[1].x = x + width.x - strikeoutPos * sinEsc;
2087 pts[1].y = y - width.y - strikeoutPos * cosEsc;
2088 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2089 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2090 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2091 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2092 pts[4].x = pts[0].x;
2093 pts[4].y = pts[0].y;
2094 DPtoLP(hdc, pts, 5);
2095 Polygon(hdc, pts, 5);
2098 SelectObject(hdc, hpen);
2099 hbrush = SelectObject(hdc, hbrush);
2100 DeleteObject(hbrush);
2104 POINT pts[2], oldpt;
2109 hpen = CreatePen(PS_SOLID, underlineWidth, GetTextColor(hdc));
2110 hpen = SelectObject(hdc, hpen);
2113 pts[1].x = x + width.x;
2114 pts[1].y = y - width.y;
2115 DPtoLP(hdc, pts, 2);
2116 MoveToEx(hdc, pts[0].x - underlinePos * sinEsc, pts[0].y - underlinePos * cosEsc, &oldpt);
2117 LineTo(hdc, pts[1].x - underlinePos * sinEsc, pts[1].y - underlinePos * cosEsc);
2118 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2119 DeleteObject(SelectObject(hdc, hpen));
2124 hpen = CreatePen(PS_SOLID, strikeoutWidth, GetTextColor(hdc));
2125 hpen = SelectObject(hdc, hpen);
2128 pts[1].x = x + width.x;
2129 pts[1].y = y - width.y;
2130 DPtoLP(hdc, pts, 2);
2131 MoveToEx(hdc, pts[0].x - strikeoutPos * sinEsc, pts[0].y - strikeoutPos * cosEsc, &oldpt);
2132 LineTo(hdc, pts[1].x - strikeoutPos * sinEsc, pts[1].y - strikeoutPos * cosEsc);
2133 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2134 DeleteObject(SelectObject(hdc, hpen));
2143 /***********************************************************************
2144 * TextOutA (GDI32.@)
2146 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2148 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2152 /***********************************************************************
2153 * TextOutW (GDI32.@)
2155 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2157 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2161 /***********************************************************************
2162 * PolyTextOutA (GDI32.@)
2166 BOOL WINAPI PolyTextOutA( HDC hdc, const POLYTEXTA *pptxt, INT cStrings )
2168 for (; cStrings>0; cStrings--, pptxt++)
2169 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2176 /***********************************************************************
2177 * PolyTextOutW (GDI32.@)
2179 * Draw several Strings
2185 BOOL WINAPI PolyTextOutW( HDC hdc, const POLYTEXTW *pptxt, INT cStrings )
2187 for (; cStrings>0; cStrings--, pptxt++)
2188 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2194 /* FIXME: all following APIs ******************************************/
2197 /***********************************************************************
2198 * SetMapperFlags (GDI32.@)
2200 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
2202 DC *dc = get_dc_ptr( hDC );
2205 if(dc->funcs->pSetMapperFlags)
2207 ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
2208 /* FIXME: ret is just a success flag, we should return a proper value */
2211 FIXME("(%p, 0x%08x): stub - harmless\n", hDC, dwFlag);
2212 release_dc_ptr( dc );
2216 /***********************************************************************
2217 * GetAspectRatioFilterEx (GDI32.@)
2219 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2221 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2226 /***********************************************************************
2227 * GetCharABCWidthsA (GDI32.@)
2229 * See GetCharABCWidthsW.
2231 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2234 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
2239 if(count <= 0) return FALSE;
2241 str = HeapAlloc(GetProcessHeap(), 0, count);
2242 for(i = 0; i < count; i++)
2243 str[i] = (BYTE)(firstChar + i);
2245 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
2247 for(i = 0; i < wlen; i++)
2249 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2257 HeapFree(GetProcessHeap(), 0, str);
2258 HeapFree(GetProcessHeap(), 0, wstr);
2264 /******************************************************************************
2265 * GetCharABCWidthsW [GDI32.@]
2267 * Retrieves widths of characters in range.
2270 * hdc [I] Handle of device context
2271 * firstChar [I] First character in range to query
2272 * lastChar [I] Last character in range to query
2273 * abc [O] Address of character-width structure
2276 * Only works with TrueType fonts
2282 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2285 DC *dc = get_dc_ptr(hdc);
2289 if (!dc) return FALSE;
2293 release_dc_ptr( dc );
2298 ret = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
2304 /* convert device units to logical */
2305 for( i = firstChar; i <= lastChar; i++, abc++ ) {
2306 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2307 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2308 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2313 release_dc_ptr( dc );
2318 /******************************************************************************
2319 * GetCharABCWidthsI [GDI32.@]
2321 * Retrieves widths of characters in range.
2324 * hdc [I] Handle of device context
2325 * firstChar [I] First glyphs in range to query
2326 * count [I] Last glyphs in range to query
2327 * pgi [i] Array of glyphs to query
2328 * abc [O] Address of character-width structure
2331 * Only works with TrueType fonts
2337 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2338 LPWORD pgi, LPABC abc)
2340 DC *dc = get_dc_ptr(hdc);
2344 if (!dc) return FALSE;
2348 release_dc_ptr( dc );
2353 ret = WineEngGetCharABCWidthsI( dc->gdiFont, firstChar, count, pgi, abc );
2359 /* convert device units to logical */
2360 for( i = 0; i < count; i++, abc++ ) {
2361 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2362 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2363 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2368 release_dc_ptr( dc );
2373 /***********************************************************************
2374 * GetGlyphOutlineA (GDI32.@)
2376 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2377 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2378 LPVOID lpBuffer, const MAT2 *lpmat2 )
2384 if (!lpmat2) return GDI_ERROR;
2386 if(!(fuFormat & GGO_GLYPH_INDEX)) {
2389 if(uChar > 0xff) { /* but, 2 bytes character only */
2391 mbchs[0] = (uChar & 0xff00) >> 8;
2392 mbchs[1] = (uChar & 0xff);
2395 mbchs[0] = (uChar & 0xff);
2397 p = FONT_mbtowc(hdc, mbchs, len, NULL, NULL);
2401 ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
2403 HeapFree(GetProcessHeap(), 0, p);
2407 /***********************************************************************
2408 * GetGlyphOutlineW (GDI32.@)
2410 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2411 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2412 LPVOID lpBuffer, const MAT2 *lpmat2 )
2417 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2418 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2420 if (!lpmat2) return GDI_ERROR;
2422 dc = get_dc_ptr(hdc);
2423 if(!dc) return GDI_ERROR;
2426 ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
2427 cbBuffer, lpBuffer, lpmat2);
2431 release_dc_ptr( dc );
2436 /***********************************************************************
2437 * CreateScalableFontResourceA (GDI32.@)
2439 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2440 LPCSTR lpszResourceFile,
2441 LPCSTR lpszFontFile,
2442 LPCSTR lpszCurrentPath )
2444 LPWSTR lpszResourceFileW = NULL;
2445 LPWSTR lpszFontFileW = NULL;
2446 LPWSTR lpszCurrentPathW = NULL;
2450 if (lpszResourceFile)
2452 len = MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, NULL, 0);
2453 lpszResourceFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2454 MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, lpszResourceFileW, len);
2459 len = MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, NULL, 0);
2460 lpszFontFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2461 MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, lpszFontFileW, len);
2464 if (lpszCurrentPath)
2466 len = MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, NULL, 0);
2467 lpszCurrentPathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2468 MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, lpszCurrentPathW, len);
2471 ret = CreateScalableFontResourceW(fHidden, lpszResourceFileW,
2472 lpszFontFileW, lpszCurrentPathW);
2474 HeapFree(GetProcessHeap(), 0, lpszResourceFileW);
2475 HeapFree(GetProcessHeap(), 0, lpszFontFileW);
2476 HeapFree(GetProcessHeap(), 0, lpszCurrentPathW);
2481 /***********************************************************************
2482 * CreateScalableFontResourceW (GDI32.@)
2484 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2485 LPCWSTR lpszResourceFile,
2486 LPCWSTR lpszFontFile,
2487 LPCWSTR lpszCurrentPath )
2490 FIXME("(%d,%s,%s,%s): stub\n",
2491 fHidden, debugstr_w(lpszResourceFile), debugstr_w(lpszFontFile),
2492 debugstr_w(lpszCurrentPath) );
2494 /* fHidden=1 - only visible for the calling app, read-only, not
2495 * enumerated with EnumFonts/EnumFontFamilies
2496 * lpszCurrentPath can be NULL
2499 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2500 if ((f = CreateFileW(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2502 SetLastError(ERROR_FILE_EXISTS);
2505 return FALSE; /* create failed */
2508 /*************************************************************************
2509 * GetKerningPairsA (GDI32.@)
2511 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2512 LPKERNINGPAIR kern_pairA )
2516 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2517 KERNINGPAIR *kern_pairW;
2519 if (!cPairs && kern_pairA)
2521 SetLastError(ERROR_INVALID_PARAMETER);
2525 cp = GdiGetCodePage(hDC);
2527 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2528 * to fail on an invalid character for CP_SYMBOL.
2530 cpi.DefaultChar[0] = 0;
2531 if (cp != CP_SYMBOL && !GetCPInfo(cp, &cpi))
2533 FIXME("Can't find codepage %u info\n", cp);
2537 total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2538 if (!total_kern_pairs) return 0;
2540 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2541 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2543 for (i = 0; i < total_kern_pairs; i++)
2547 if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2550 if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2553 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2558 if (kern_pairs_copied >= cPairs) break;
2560 kern_pairA->wFirst = (BYTE)first;
2561 kern_pairA->wSecond = (BYTE)second;
2562 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2565 kern_pairs_copied++;
2568 HeapFree(GetProcessHeap(), 0, kern_pairW);
2570 return kern_pairs_copied;
2573 /*************************************************************************
2574 * GetKerningPairsW (GDI32.@)
2576 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2577 LPKERNINGPAIR lpKerningPairs )
2582 TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2584 if (!cPairs && lpKerningPairs)
2586 SetLastError(ERROR_INVALID_PARAMETER);
2590 dc = get_dc_ptr(hDC);
2594 ret = WineEngGetKerningPairs(dc->gdiFont, cPairs, lpKerningPairs);
2596 release_dc_ptr( dc );
2600 /*************************************************************************
2601 * TranslateCharsetInfo [GDI32.@]
2603 * Fills a CHARSETINFO structure for a character set, code page, or
2604 * font. This allows making the correspondence between different labels
2605 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2606 * of the same encoding.
2608 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2609 * only one codepage should be set in *lpSrc.
2612 * TRUE on success, FALSE on failure.
2615 BOOL WINAPI TranslateCharsetInfo(
2616 LPDWORD lpSrc, /* [in]
2617 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2618 if flags == TCI_SRCCHARSET: a character set value
2619 if flags == TCI_SRCCODEPAGE: a code page value
2621 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2622 DWORD flags /* [in] determines interpretation of lpSrc */)
2626 case TCI_SRCFONTSIG:
2627 while (index < MAXTCIINDEX && !(*lpSrc>>index & 0x0001)) index++;
2629 case TCI_SRCCODEPAGE:
2630 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciACP) index++;
2632 case TCI_SRCCHARSET:
2633 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciCharset) index++;
2638 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2639 *lpCs = FONT_tci[index];
2643 /*************************************************************************
2644 * GetFontLanguageInfo (GDI32.@)
2646 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2648 FONTSIGNATURE fontsig;
2649 static const DWORD GCP_DBCS_MASK=0x003F0000,
2650 GCP_DIACRITIC_MASK=0x00000000,
2651 FLI_GLYPHS_MASK=0x00000000,
2652 GCP_GLYPHSHAPE_MASK=0x00000040,
2653 GCP_KASHIDA_MASK=0x00000000,
2654 GCP_LIGATE_MASK=0x00000000,
2655 GCP_USEKERNING_MASK=0x00000000,
2656 GCP_REORDER_MASK=0x00000060;
2660 GetTextCharsetInfo( hdc, &fontsig, 0 );
2661 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2663 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2666 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2667 result|=GCP_DIACRITIC;
2669 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2672 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2673 result|=GCP_GLYPHSHAPE;
2675 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2676 result|=GCP_KASHIDA;
2678 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2681 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2682 result|=GCP_USEKERNING;
2684 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2685 if( GetTextAlign( hdc) & TA_RTLREADING )
2686 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2687 result|=GCP_REORDER;
2693 /*************************************************************************
2694 * GetFontData [GDI32.@]
2696 * Retrieve data for TrueType font.
2700 * success: Number of bytes returned
2701 * failure: GDI_ERROR
2705 * Calls SetLastError()
2708 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2709 LPVOID buffer, DWORD length)
2711 DC *dc = get_dc_ptr(hdc);
2712 DWORD ret = GDI_ERROR;
2714 if(!dc) return GDI_ERROR;
2717 ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2719 release_dc_ptr( dc );
2723 /*************************************************************************
2724 * GetGlyphIndicesA [GDI32.@]
2726 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2727 LPWORD pgi, DWORD flags)
2733 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2734 hdc, debugstr_an(lpstr, count), count, pgi, flags);
2736 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2737 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2738 HeapFree(GetProcessHeap(), 0, lpstrW);
2743 /*************************************************************************
2744 * GetGlyphIndicesW [GDI32.@]
2746 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2747 LPWORD pgi, DWORD flags)
2749 DC *dc = get_dc_ptr(hdc);
2750 DWORD ret = GDI_ERROR;
2752 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2753 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2755 if(!dc) return GDI_ERROR;
2758 ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2760 release_dc_ptr( dc );
2764 /*************************************************************************
2765 * GetCharacterPlacementA [GDI32.@]
2767 * See GetCharacterPlacementW.
2770 * the web browser control of ie4 calls this with dwFlags=0
2773 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2774 INT nMaxExtent, GCP_RESULTSA *lpResults,
2779 GCP_RESULTSW resultsW;
2783 TRACE("%s, %d, %d, 0x%08x\n",
2784 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2786 /* both structs are equal in size */
2787 memcpy(&resultsW, lpResults, sizeof(resultsW));
2789 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2790 if(lpResults->lpOutString)
2791 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2793 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2795 lpResults->nGlyphs = resultsW.nGlyphs;
2796 lpResults->nMaxFit = resultsW.nMaxFit;
2798 if(lpResults->lpOutString) {
2799 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2800 lpResults->lpOutString, uCount, NULL, NULL );
2803 HeapFree(GetProcessHeap(), 0, lpStringW);
2804 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2809 /*************************************************************************
2810 * GetCharacterPlacementW [GDI32.@]
2812 * Retrieve information about a string. This includes the width, reordering,
2813 * Glyphing and so on.
2817 * The width and height of the string if successful, 0 if failed.
2821 * All flags except GCP_REORDER are not yet implemented.
2822 * Reordering is not 100% compliant to the Windows BiDi method.
2823 * Caret positioning is not yet implemented for BiDi.
2824 * Classes are not yet implemented.
2828 GetCharacterPlacementW(
2829 HDC hdc, /* [in] Device context for which the rendering is to be done */
2830 LPCWSTR lpString, /* [in] The string for which information is to be returned */
2831 INT uCount, /* [in] Number of WORDS in string. */
2832 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
2833 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2834 DWORD dwFlags /* [in] Flags specifying how to process the string */
2841 TRACE("%s, %d, %d, 0x%08x\n",
2842 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2844 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2845 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2846 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2847 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2848 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2850 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08x ignored\n", dwFlags);
2851 if(lpResults->lpClass) FIXME("classes not implemented\n");
2852 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2853 FIXME("Caret positions for complex scripts not implemented\n");
2855 nSet = (UINT)uCount;
2856 if(nSet > lpResults->nGlyphs)
2857 nSet = lpResults->nGlyphs;
2859 /* return number of initialized fields */
2860 lpResults->nGlyphs = nSet;
2862 if((dwFlags&GCP_REORDER)==0 )
2864 /* Treat the case where no special handling was requested in a fastpath way */
2865 /* copy will do if the GCP_REORDER flag is not set */
2866 if(lpResults->lpOutString)
2867 memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
2869 if(lpResults->lpOrder)
2871 for(i = 0; i < nSet; i++)
2872 lpResults->lpOrder[i] = i;
2876 BIDI_Reorder(NULL, lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
2877 nSet, lpResults->lpOrder, NULL );
2880 /* FIXME: Will use the placement chars */
2881 if (lpResults->lpDx)
2884 for (i = 0; i < nSet; i++)
2886 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
2887 lpResults->lpDx[i]= c;
2891 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
2895 lpResults->lpCaretPos[0] = 0;
2896 for (i = 1; i < nSet; i++)
2897 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
2898 lpResults->lpCaretPos[i] = (pos += size.cx);
2901 if(lpResults->lpGlyphs)
2902 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
2904 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
2905 ret = MAKELONG(size.cx, size.cy);
2910 /*************************************************************************
2911 * GetCharABCWidthsFloatA [GDI32.@]
2913 * See GetCharABCWidthsFloatW.
2915 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
2917 INT i, wlen, count = (INT)(last - first + 1);
2922 if (count <= 0) return FALSE;
2924 str = HeapAlloc(GetProcessHeap(), 0, count);
2926 for(i = 0; i < count; i++)
2927 str[i] = (BYTE)(first + i);
2929 wstr = FONT_mbtowc( hdc, str, count, &wlen, NULL );
2931 for (i = 0; i < wlen; i++)
2933 if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
2941 HeapFree( GetProcessHeap(), 0, str );
2942 HeapFree( GetProcessHeap(), 0, wstr );
2947 /*************************************************************************
2948 * GetCharABCWidthsFloatW [GDI32.@]
2950 * Retrieves widths of a range of characters.
2953 * hdc [I] Handle to device context.
2954 * first [I] First character in range to query.
2955 * last [I] Last character in range to query.
2956 * abcf [O] Array of LPABCFLOAT structures.
2962 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
2966 DC *dc = get_dc_ptr( hdc );
2968 TRACE("%p, %d, %d, %p\n", hdc, first, last, abcf);
2970 if (!dc) return FALSE;
2974 release_dc_ptr( dc );
2979 ret = WineEngGetCharABCWidthsFloat( dc->gdiFont, first, last, abcf );
2985 /* convert device units to logical */
2986 for (i = first; i <= last; i++, abcf++)
2988 abcf->abcfA = abcf->abcfA * dc->xformVport2World.eM11;
2989 abcf->abcfB = abcf->abcfB * dc->xformVport2World.eM11;
2990 abcf->abcfC = abcf->abcfC * dc->xformVport2World.eM11;
2994 release_dc_ptr( dc );
2998 /*************************************************************************
2999 * GetCharWidthFloatA [GDI32.@]
3001 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
3002 UINT iLastChar, PFLOAT pxBuffer)
3004 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3008 /*************************************************************************
3009 * GetCharWidthFloatW [GDI32.@]
3011 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
3012 UINT iLastChar, PFLOAT pxBuffer)
3014 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3019 /***********************************************************************
3021 * Font Resource API *
3023 ***********************************************************************/
3025 /***********************************************************************
3026 * AddFontResourceA (GDI32.@)
3028 INT WINAPI AddFontResourceA( LPCSTR str )
3030 return AddFontResourceExA( str, 0, NULL);
3033 /***********************************************************************
3034 * AddFontResourceW (GDI32.@)
3036 INT WINAPI AddFontResourceW( LPCWSTR str )
3038 return AddFontResourceExW(str, 0, NULL);
3042 /***********************************************************************
3043 * AddFontResourceExA (GDI32.@)
3045 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3047 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3048 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3051 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3052 ret = AddFontResourceExW(strW, fl, pdv);
3053 HeapFree(GetProcessHeap(), 0, strW);
3057 static BOOL CALLBACK load_enumed_resource(HMODULE hModule, LPCWSTR type, LPWSTR name, LONG_PTR lParam)
3059 HRSRC rsrc = FindResourceW(hModule, name, type);
3060 HGLOBAL hMem = LoadResource(hModule, rsrc);
3061 LPVOID *pMem = LockResource(hMem);
3062 int *num_total = (int *)lParam;
3065 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type));
3066 if (!AddFontMemResourceEx(pMem, SizeofResource(hModule, rsrc), NULL, &num_in_res))
3068 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule, hMem);
3072 *num_total += num_in_res;
3076 /***********************************************************************
3077 * AddFontResourceExW (GDI32.@)
3079 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3081 int ret = WineEngAddFontResourceEx(str, fl, pdv);
3084 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3085 HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
3086 if (hModule != NULL)
3088 int num_resources = 0;
3089 LPWSTR rt_font = (LPWSTR)((ULONG_PTR)8); /* we don't want to include winuser.h */
3091 TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3092 wine_dbgstr_w(str));
3093 if (EnumResourceNamesW(hModule, rt_font, load_enumed_resource, (LONG_PTR)&num_resources))
3094 ret = num_resources;
3095 FreeLibrary(hModule);
3101 /***********************************************************************
3102 * RemoveFontResourceA (GDI32.@)
3104 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3106 return RemoveFontResourceExA(str, 0, 0);
3109 /***********************************************************************
3110 * RemoveFontResourceW (GDI32.@)
3112 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3114 return RemoveFontResourceExW(str, 0, 0);
3117 /***********************************************************************
3118 * AddFontMemResourceEx (GDI32.@)
3120 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3122 return WineEngAddFontMemResourceEx(pbFont, cbFont, pdv, pcFonts);
3125 /***********************************************************************
3126 * RemoveFontMemResourceEx (GDI32.@)
3128 BOOL WINAPI RemoveFontMemResourceEx( HANDLE fh )
3130 FIXME("(%p) stub\n", fh);
3134 /***********************************************************************
3135 * RemoveFontResourceExA (GDI32.@)
3137 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3139 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3140 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3143 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3144 ret = RemoveFontResourceExW(strW, fl, pdv);
3145 HeapFree(GetProcessHeap(), 0, strW);
3149 /***********************************************************************
3150 * RemoveFontResourceExW (GDI32.@)
3152 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3154 return WineEngRemoveFontResourceEx(str, fl, pdv);
3157 /***********************************************************************
3158 * GetTextCharset (GDI32.@)
3160 UINT WINAPI GetTextCharset(HDC hdc)
3162 /* MSDN docs say this is equivalent */
3163 return GetTextCharsetInfo(hdc, NULL, 0);
3166 /***********************************************************************
3167 * GetTextCharsetInfo (GDI32.@)
3169 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3171 UINT ret = DEFAULT_CHARSET;
3172 DC *dc = get_dc_ptr(hdc);
3177 ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
3179 release_dc_ptr( dc );
3182 if (ret == DEFAULT_CHARSET && fs)
3183 memset(fs, 0, sizeof(FONTSIGNATURE));
3187 /***********************************************************************
3188 * GdiGetCharDimensions (GDI32.@)
3190 * Gets the average width of the characters in the English alphabet.
3193 * hdc [I] Handle to the device context to measure on.
3194 * lptm [O] Pointer to memory to store the text metrics into.
3195 * height [O] On exit, the maximum height of characters in the English alphabet.
3198 * The average width of characters in the English alphabet.
3201 * This function is used by the dialog manager to get the size of a dialog
3202 * unit. It should also be used by other pieces of code that need to know
3203 * the size of a dialog unit in logical units without having access to the
3204 * window handle of the dialog.
3205 * Windows caches the font metrics from this function, but we don't and
3206 * there doesn't appear to be an immediate advantage to do so.
3209 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3211 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3214 static const WCHAR alphabet[] = {
3215 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3216 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3217 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3219 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3221 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3223 if (height) *height = sz.cy;
3224 return (sz.cx / 26 + 1) / 2;
3227 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3229 FIXME("(%d): stub\n", fEnableEUDC);
3233 /***********************************************************************
3234 * GetCharWidthI (GDI32.@)
3236 * Retrieve widths of characters.
3239 * hdc [I] Handle to a device context.
3240 * first [I] First glyph in range to query.
3241 * count [I] Number of glyph indices to query.
3242 * glyphs [I] Array of glyphs to query.
3243 * buffer [O] Buffer to receive character widths.
3246 * Only works with TrueType fonts.
3252 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3257 TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3259 if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3262 if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3264 HeapFree(GetProcessHeap(), 0, abc);
3268 for (i = 0; i < count; i++)
3269 buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3271 HeapFree(GetProcessHeap(), 0, abc);
3275 /***********************************************************************
3276 * GetFontUnicodeRanges (GDI32.@)
3278 * Retrieve a list of supported Unicode characters in a font.
3281 * hdc [I] Handle to a device context.
3282 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3285 * Success: Number of bytes written to the buffer pointed to by lpgs.
3289 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3292 DC *dc = get_dc_ptr(hdc);
3294 TRACE("(%p, %p)\n", hdc, lpgs);
3298 if (dc->gdiFont) ret = WineEngGetFontUnicodeRanges(dc->gdiFont, lpgs);
3304 /*************************************************************
3305 * FontIsLinked (GDI32.@)
3307 BOOL WINAPI FontIsLinked(HDC hdc)
3309 DC *dc = get_dc_ptr(hdc);
3312 if (!dc) return FALSE;
3313 if (dc->gdiFont) ret = WineEngFontIsLinked(dc->gdiFont);
3315 TRACE("returning %d\n", ret);
3319 /*************************************************************
3320 * GdiRealizationInfo (GDI32.@)
3322 * Returns a structure that contains some font information.
3324 BOOL WINAPI GdiRealizationInfo(HDC hdc, realization_info_t *info)
3326 DC *dc = get_dc_ptr(hdc);
3329 if (!dc) return FALSE;
3330 if (dc->gdiFont) ret = WineEngRealizationInfo(dc->gdiFont, info);