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/exception.h"
37 #include "wine/unicode.h"
38 #include "wine/debug.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(font);
42 /* Device -> World size conversion */
44 /* Performs a device to world transformation on the specified width (which
45 * is in integer format).
47 static inline INT INTERNAL_XDSTOWS(DC *dc, INT width)
51 /* Perform operation with floating point */
52 floatWidth = (double)width * dc->xformVport2World.eM11;
53 /* Round to integers */
54 return GDI_ROUND(floatWidth);
57 /* Performs a device to world transformation on the specified size (which
58 * is in integer format).
60 static inline INT INTERNAL_YDSTOWS(DC *dc, INT height)
64 /* Perform operation with floating point */
65 floatHeight = (double)height * dc->xformVport2World.eM22;
66 /* Round to integers */
67 return GDI_ROUND(floatHeight);
70 static inline INT INTERNAL_XWSTODS(DC *dc, INT width)
73 pt[0].x = pt[0].y = 0;
76 LPtoDP(dc->hSelf, pt, 2);
77 return pt[1].x - pt[0].x;
80 static inline INT INTERNAL_YWSTODS(DC *dc, INT height)
83 pt[0].x = pt[0].y = 0;
86 LPtoDP(dc->hSelf, pt, 2);
87 return pt[1].y - pt[0].y;
90 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc );
91 static INT FONT_GetObjectA( HGDIOBJ handle, INT count, LPVOID buffer );
92 static INT FONT_GetObjectW( HGDIOBJ handle, INT count, LPVOID buffer );
93 static BOOL FONT_DeleteObject( HGDIOBJ handle );
95 static const struct gdi_obj_funcs font_funcs =
97 FONT_SelectObject, /* pSelectObject */
98 FONT_GetObjectA, /* pGetObjectA */
99 FONT_GetObjectW, /* pGetObjectW */
100 NULL, /* pUnrealizeObject */
101 FONT_DeleteObject /* pDeleteObject */
112 LPLOGFONTW lpLogFontParam;
113 FONTENUMPROCW lpEnumFunc;
120 * For TranslateCharsetInfo
122 #define MAXTCIINDEX 32
123 static const CHARSETINFO FONT_tci[MAXTCIINDEX] = {
125 { ANSI_CHARSET, 1252, {{0,0,0,0},{FS_LATIN1,0}} },
126 { EASTEUROPE_CHARSET, 1250, {{0,0,0,0},{FS_LATIN2,0}} },
127 { RUSSIAN_CHARSET, 1251, {{0,0,0,0},{FS_CYRILLIC,0}} },
128 { GREEK_CHARSET, 1253, {{0,0,0,0},{FS_GREEK,0}} },
129 { TURKISH_CHARSET, 1254, {{0,0,0,0},{FS_TURKISH,0}} },
130 { HEBREW_CHARSET, 1255, {{0,0,0,0},{FS_HEBREW,0}} },
131 { ARABIC_CHARSET, 1256, {{0,0,0,0},{FS_ARABIC,0}} },
132 { BALTIC_CHARSET, 1257, {{0,0,0,0},{FS_BALTIC,0}} },
133 { VIETNAMESE_CHARSET, 1258, {{0,0,0,0},{FS_VIETNAMESE,0}} },
134 /* reserved by ANSI */
135 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
136 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
137 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
138 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
139 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
140 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
141 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
143 { THAI_CHARSET, 874, {{0,0,0,0},{FS_THAI,0}} },
144 { SHIFTJIS_CHARSET, 932, {{0,0,0,0},{FS_JISJAPAN,0}} },
145 { GB2312_CHARSET, 936, {{0,0,0,0},{FS_CHINESESIMP,0}} },
146 { HANGEUL_CHARSET, 949, {{0,0,0,0},{FS_WANSUNG,0}} },
147 { CHINESEBIG5_CHARSET, 950, {{0,0,0,0},{FS_CHINESETRAD,0}} },
148 { JOHAB_CHARSET, 1361, {{0,0,0,0},{FS_JOHAB,0}} },
149 /* reserved for alternate ANSI and OEM */
150 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
151 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
152 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
153 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
154 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
155 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
156 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
157 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
158 /* reserved for system */
159 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
160 { SYMBOL_CHARSET, CP_SYMBOL, {{0,0,0,0},{FS_SYMBOL,0}} }
163 static void FONT_LogFontAToW( const LOGFONTA *fontA, LPLOGFONTW fontW )
165 memcpy(fontW, fontA, sizeof(LOGFONTA) - LF_FACESIZE);
166 MultiByteToWideChar(CP_ACP, 0, fontA->lfFaceName, -1, fontW->lfFaceName,
168 fontW->lfFaceName[LF_FACESIZE-1] = 0;
171 static void FONT_LogFontWToA( const LOGFONTW *fontW, LPLOGFONTA fontA )
173 memcpy(fontA, fontW, sizeof(LOGFONTA) - LF_FACESIZE);
174 WideCharToMultiByte(CP_ACP, 0, fontW->lfFaceName, -1, fontA->lfFaceName,
175 LF_FACESIZE, NULL, NULL);
176 fontA->lfFaceName[LF_FACESIZE-1] = 0;
179 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEXA fontA )
181 FONT_LogFontWToA( &fontW->elfLogFont, &fontA->elfLogFont );
183 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
184 (LPSTR) fontA->elfFullName, LF_FULLFACESIZE, NULL, NULL );
185 fontA->elfFullName[LF_FULLFACESIZE-1] = '\0';
186 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
187 (LPSTR) fontA->elfStyle, LF_FACESIZE, NULL, NULL );
188 fontA->elfStyle[LF_FACESIZE-1] = '\0';
189 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
190 (LPSTR) fontA->elfScript, LF_FACESIZE, NULL, NULL );
191 fontA->elfScript[LF_FACESIZE-1] = '\0';
194 static void FONT_EnumLogFontExAToW( const ENUMLOGFONTEXA *fontA, LPENUMLOGFONTEXW fontW )
196 FONT_LogFontAToW( &fontA->elfLogFont, &fontW->elfLogFont );
198 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfFullName, -1,
199 fontW->elfFullName, LF_FULLFACESIZE );
200 fontW->elfFullName[LF_FULLFACESIZE-1] = '\0';
201 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfStyle, -1,
202 fontW->elfStyle, LF_FACESIZE );
203 fontW->elfStyle[LF_FACESIZE-1] = '\0';
204 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfScript, -1,
205 fontW->elfScript, LF_FACESIZE );
206 fontW->elfScript[LF_FACESIZE-1] = '\0';
209 /***********************************************************************
210 * TEXTMETRIC conversion functions.
212 static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
214 ptmA->tmHeight = ptmW->tmHeight;
215 ptmA->tmAscent = ptmW->tmAscent;
216 ptmA->tmDescent = ptmW->tmDescent;
217 ptmA->tmInternalLeading = ptmW->tmInternalLeading;
218 ptmA->tmExternalLeading = ptmW->tmExternalLeading;
219 ptmA->tmAveCharWidth = ptmW->tmAveCharWidth;
220 ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth;
221 ptmA->tmWeight = ptmW->tmWeight;
222 ptmA->tmOverhang = ptmW->tmOverhang;
223 ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX;
224 ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
225 ptmA->tmFirstChar = min(ptmW->tmFirstChar, 255);
226 if (ptmW->tmCharSet == SYMBOL_CHARSET)
228 ptmA->tmFirstChar = 0x1e;
229 ptmA->tmLastChar = 0xff; /* win9x behaviour - we need the OS2 table data to calculate correctly */
231 else if (ptmW->tmPitchAndFamily & TMPF_TRUETYPE)
233 ptmA->tmFirstChar = ptmW->tmDefaultChar - 1;
234 ptmA->tmLastChar = min(ptmW->tmLastChar, 0xff);
238 ptmA->tmFirstChar = min(ptmW->tmFirstChar, 0xff);
239 ptmA->tmLastChar = min(ptmW->tmLastChar, 0xff);
241 ptmA->tmDefaultChar = ptmW->tmDefaultChar;
242 ptmA->tmBreakChar = ptmW->tmBreakChar;
243 ptmA->tmItalic = ptmW->tmItalic;
244 ptmA->tmUnderlined = ptmW->tmUnderlined;
245 ptmA->tmStruckOut = ptmW->tmStruckOut;
246 ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
247 ptmA->tmCharSet = ptmW->tmCharSet;
251 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW *ptmW, NEWTEXTMETRICEXA *ptmA )
253 FONT_TextMetricWToA((const TEXTMETRICW *)ptmW, (LPTEXTMETRICA)ptmA);
254 ptmA->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
255 ptmA->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
256 ptmA->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
257 ptmA->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
258 memcpy(&ptmA->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
262 UINT get_font_aa_flags( HDC hdc )
266 if (GetObjectType( hdc ) == OBJ_MEMDC)
269 GetObjectW( GetCurrentObject( hdc, OBJ_BITMAP ), sizeof(bm), &bm );
270 if (bm.bmBitsPixel <= 8) return GGO_BITMAP;
272 else if (GetDeviceCaps( hdc, BITSPIXEL ) <= 8) return GGO_BITMAP;
274 GetObjectW( GetCurrentObject( hdc, OBJ_FONT ), sizeof(lf), &lf );
275 if (lf.lfQuality == NONANTIALIASED_QUALITY) return GGO_BITMAP;
277 /* FIXME, check gasp and user prefs */
278 return GGO_GRAY4_BITMAP;
281 /***********************************************************************
282 * GdiGetCodePage (GDI32.@)
284 DWORD WINAPI GdiGetCodePage( HDC hdc )
287 DC *dc = get_dc_ptr( hdc );
291 cp = dc->font_code_page;
292 release_dc_ptr( dc );
297 /***********************************************************************
300 * Returns a Unicode translation of str using the charset of the
301 * currently selected font in hdc. If count is -1 then str is assumed
302 * to be '\0' terminated, otherwise it contains the number of bytes to
303 * convert. If plenW is non-NULL, on return it will point to the
304 * number of WCHARs that have been written. If pCP is non-NULL, on
305 * return it will point to the codepage used in the conversion. The
306 * caller should free the returned LPWSTR from the process heap
309 static LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
315 cp = GdiGetCodePage( hdc );
317 if(count == -1) count = strlen(str);
318 lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
319 strW = HeapAlloc(GetProcessHeap(), 0, lenW*sizeof(WCHAR));
320 MultiByteToWideChar(cp, 0, str, count, strW, lenW);
321 TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW));
322 if(plenW) *plenW = lenW;
327 /***********************************************************************
328 * CreateFontIndirectExA (GDI32.@)
330 HFONT WINAPI CreateFontIndirectExA( const ENUMLOGFONTEXDVA *penumexA )
332 ENUMLOGFONTEXDVW enumexW;
334 if (!penumexA) return 0;
336 FONT_EnumLogFontExAToW( &penumexA->elfEnumLogfontEx, &enumexW.elfEnumLogfontEx );
337 enumexW.elfDesignVector = penumexA->elfDesignVector;
338 return CreateFontIndirectExW( &enumexW );
341 /***********************************************************************
342 * CreateFontIndirectExW (GDI32.@)
344 HFONT WINAPI CreateFontIndirectExW( const ENUMLOGFONTEXDVW *penumex )
350 if (!penumex) return 0;
352 if (penumex->elfEnumLogfontEx.elfFullName[0] ||
353 penumex->elfEnumLogfontEx.elfStyle[0] ||
354 penumex->elfEnumLogfontEx.elfScript[0])
356 FIXME("some fields ignored. fullname=%s, style=%s, script=%s\n",
357 debugstr_w(penumex->elfEnumLogfontEx.elfFullName),
358 debugstr_w(penumex->elfEnumLogfontEx.elfStyle),
359 debugstr_w(penumex->elfEnumLogfontEx.elfScript));
362 plf = &penumex->elfEnumLogfontEx.elfLogFont;
363 if (!(fontPtr = HeapAlloc( GetProcessHeap(), 0, sizeof(*fontPtr) ))) return 0;
365 fontPtr->logfont = *plf;
367 if (plf->lfEscapement != plf->lfOrientation)
369 /* this should really depend on whether GM_ADVANCED is set */
370 fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
371 WARN("orientation angle %f set to "
372 "escapement angle %f for new font %p\n",
373 plf->lfOrientation/10., plf->lfEscapement/10., fontPtr);
376 if (!(hFont = alloc_gdi_handle( &fontPtr->header, OBJ_FONT, &font_funcs )))
378 HeapFree( GetProcessHeap(), 0, fontPtr );
382 TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
383 plf->lfHeight, plf->lfWidth,
384 plf->lfEscapement, plf->lfOrientation,
385 plf->lfPitchAndFamily,
386 plf->lfOutPrecision, plf->lfClipPrecision,
387 plf->lfQuality, plf->lfCharSet,
388 debugstr_w(plf->lfFaceName),
389 plf->lfWeight > 400 ? "Bold" : "",
390 plf->lfItalic ? "Italic" : "",
391 plf->lfUnderline ? "Underline" : "", hFont);
396 /***********************************************************************
397 * CreateFontIndirectA (GDI32.@)
399 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *plfA )
405 FONT_LogFontAToW( plfA, &lfW );
406 return CreateFontIndirectW( &lfW );
409 /***********************************************************************
410 * CreateFontIndirectW (GDI32.@)
412 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
414 ENUMLOGFONTEXDVW exdv;
418 exdv.elfEnumLogfontEx.elfLogFont = *plf;
419 exdv.elfEnumLogfontEx.elfFullName[0] = 0;
420 exdv.elfEnumLogfontEx.elfStyle[0] = 0;
421 exdv.elfEnumLogfontEx.elfScript[0] = 0;
422 return CreateFontIndirectExW( &exdv );
425 /*************************************************************************
426 * CreateFontA (GDI32.@)
428 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
429 INT orient, INT weight, DWORD italic,
430 DWORD underline, DWORD strikeout, DWORD charset,
431 DWORD outpres, DWORD clippres, DWORD quality,
432 DWORD pitch, LPCSTR name )
436 logfont.lfHeight = height;
437 logfont.lfWidth = width;
438 logfont.lfEscapement = esc;
439 logfont.lfOrientation = orient;
440 logfont.lfWeight = weight;
441 logfont.lfItalic = italic;
442 logfont.lfUnderline = underline;
443 logfont.lfStrikeOut = strikeout;
444 logfont.lfCharSet = charset;
445 logfont.lfOutPrecision = outpres;
446 logfont.lfClipPrecision = clippres;
447 logfont.lfQuality = quality;
448 logfont.lfPitchAndFamily = pitch;
451 lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
453 logfont.lfFaceName[0] = '\0';
455 return CreateFontIndirectA( &logfont );
458 /*************************************************************************
459 * CreateFontW (GDI32.@)
461 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
462 INT orient, INT weight, DWORD italic,
463 DWORD underline, DWORD strikeout, DWORD charset,
464 DWORD outpres, DWORD clippres, DWORD quality,
465 DWORD pitch, LPCWSTR name )
469 logfont.lfHeight = height;
470 logfont.lfWidth = width;
471 logfont.lfEscapement = esc;
472 logfont.lfOrientation = orient;
473 logfont.lfWeight = weight;
474 logfont.lfItalic = italic;
475 logfont.lfUnderline = underline;
476 logfont.lfStrikeOut = strikeout;
477 logfont.lfCharSet = charset;
478 logfont.lfOutPrecision = outpres;
479 logfont.lfClipPrecision = clippres;
480 logfont.lfQuality = quality;
481 logfont.lfPitchAndFamily = pitch;
484 lstrcpynW(logfont.lfFaceName, name,
485 sizeof(logfont.lfFaceName) / sizeof(WCHAR));
487 logfont.lfFaceName[0] = '\0';
489 return CreateFontIndirectW( &logfont );
492 static void update_font_code_page( DC *dc )
495 int charset = GetTextCharsetInfo( dc->hSelf, NULL, 0 );
497 /* Hmm, nicely designed api this one! */
498 if (TranslateCharsetInfo( ULongToPtr(charset), &csi, TCI_SRCCHARSET) )
499 dc->font_code_page = csi.ciACP;
503 dc->font_code_page = GetOEMCP();
505 case DEFAULT_CHARSET:
506 dc->font_code_page = GetACP();
516 /* FIXME: These have no place here, but because x11drv
517 enumerates fonts with these (made up) charsets some apps
518 might use them and then the FIXME below would become
519 annoying. Now we could pick the intended codepage for
520 each of these, but since it's broken anyway we'll just
521 use CP_ACP and hope it'll go away...
523 dc->font_code_page = CP_ACP;
527 FIXME("Can't find codepage for charset %d\n", charset);
528 dc->font_code_page = CP_ACP;
533 TRACE("charset %d => cp %d\n", charset, dc->font_code_page);
536 /***********************************************************************
539 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc )
542 DC *dc = get_dc_ptr( hdc );
547 if (!GDI_inc_ref_count( handle ))
549 release_dc_ptr( dc );
553 physdev = GET_DC_PHYSDEV( dc, pSelectFont );
554 if (physdev->funcs->pSelectFont( physdev, handle ))
558 update_font_code_page( dc );
559 GDI_dec_ref_count( ret );
561 else GDI_dec_ref_count( handle );
563 release_dc_ptr( dc );
568 /***********************************************************************
571 static INT FONT_GetObjectA( HGDIOBJ handle, INT count, LPVOID buffer )
573 FONTOBJ *font = GDI_GetObjPtr( handle, OBJ_FONT );
579 FONT_LogFontWToA( &font->logfont, &lfA );
580 if (count > sizeof(lfA)) count = sizeof(lfA);
581 memcpy( buffer, &lfA, count );
583 else count = sizeof(lfA);
584 GDI_ReleaseObj( handle );
588 /***********************************************************************
591 static INT FONT_GetObjectW( HGDIOBJ handle, INT count, LPVOID buffer )
593 FONTOBJ *font = GDI_GetObjPtr( handle, OBJ_FONT );
598 if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
599 memcpy( buffer, &font->logfont, count );
601 else count = sizeof(LOGFONTW);
602 GDI_ReleaseObj( handle );
607 /***********************************************************************
610 static BOOL FONT_DeleteObject( HGDIOBJ handle )
614 WineEngDestroyFontInstance( handle );
616 if (!(obj = free_gdi_handle( handle ))) return FALSE;
617 return HeapFree( GetProcessHeap(), 0, obj );
621 /***********************************************************************
624 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
625 * We have to use other types because of the FONTENUMPROCW definition.
627 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
628 DWORD fType, LPARAM lp )
630 struct font_enum *pfe = (struct font_enum *)lp;
633 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
634 if ((!pfe->lpLogFontParam ||
635 pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
636 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
637 (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
639 /* convert font metrics */
640 ENUMLOGFONTEXA logfont;
641 NEWTEXTMETRICEXA tmA;
645 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
646 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
647 plf = (LOGFONTW *)&logfont.elfLogFont;
648 ptm = (TEXTMETRICW *)&tmA;
650 ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
655 /***********************************************************************
656 * FONT_EnumFontFamiliesEx
658 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf, FONTENUMPROCW efproc,
659 LPARAM lParam, BOOL unicode )
662 DC *dc = get_dc_ptr( hDC );
667 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pEnumFonts );
669 if (plf) TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName), plf->lfCharSet);
670 fe.lpLogFontParam = plf;
671 fe.lpEnumFunc = efproc;
673 fe.unicode = unicode;
675 ret = physdev->funcs->pEnumFonts( physdev, plf, FONT_EnumInstance, (LPARAM)&fe );
676 release_dc_ptr( dc );
681 /***********************************************************************
682 * EnumFontFamiliesExW (GDI32.@)
684 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
685 FONTENUMPROCW efproc,
686 LPARAM lParam, DWORD dwFlags )
688 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, TRUE );
691 /***********************************************************************
692 * EnumFontFamiliesExA (GDI32.@)
694 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
695 FONTENUMPROCA efproc,
696 LPARAM lParam, DWORD dwFlags)
702 FONT_LogFontAToW( plf, &lfW );
707 return FONT_EnumFontFamiliesEx( hDC, plfW, (FONTENUMPROCW)efproc, lParam, FALSE );
710 /***********************************************************************
711 * EnumFontFamiliesA (GDI32.@)
713 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
714 FONTENUMPROCA efproc, LPARAM lpData )
720 if (!*lpFamily) return 1;
721 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
722 lf.lfCharSet = DEFAULT_CHARSET;
723 lf.lfPitchAndFamily = 0;
728 return EnumFontFamiliesExA( hDC, plf, efproc, lpData, 0 );
731 /***********************************************************************
732 * EnumFontFamiliesW (GDI32.@)
734 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
735 FONTENUMPROCW efproc, LPARAM lpData )
741 if (!*lpFamily) return 1;
742 lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
743 lf.lfCharSet = DEFAULT_CHARSET;
744 lf.lfPitchAndFamily = 0;
749 return EnumFontFamiliesExW( hDC, plf, efproc, lpData, 0 );
752 /***********************************************************************
753 * EnumFontsA (GDI32.@)
755 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
758 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
761 /***********************************************************************
762 * EnumFontsW (GDI32.@)
764 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
767 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
771 /***********************************************************************
772 * GetTextCharacterExtra (GDI32.@)
774 INT WINAPI GetTextCharacterExtra( HDC hdc )
777 DC *dc = get_dc_ptr( hdc );
778 if (!dc) return 0x80000000;
780 release_dc_ptr( dc );
785 /***********************************************************************
786 * SetTextCharacterExtra (GDI32.@)
788 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
790 INT ret = 0x80000000;
791 DC * dc = get_dc_ptr( hdc );
795 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetTextCharacterExtra );
796 extra = physdev->funcs->pSetTextCharacterExtra( physdev, extra );
797 if (extra != 0x80000000)
800 dc->charExtra = extra;
802 release_dc_ptr( dc );
808 /***********************************************************************
809 * SetTextJustification (GDI32.@)
811 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
815 DC * dc = get_dc_ptr( hdc );
817 if (!dc) return FALSE;
819 physdev = GET_DC_PHYSDEV( dc, pSetTextJustification );
820 ret = physdev->funcs->pSetTextJustification( physdev, extra, breaks );
823 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
824 if (!extra) breaks = 0;
827 dc->breakExtra = extra / breaks;
828 dc->breakRem = extra - (breaks * dc->breakExtra);
836 release_dc_ptr( dc );
841 /***********************************************************************
842 * GetTextFaceA (GDI32.@)
844 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
846 INT res = GetTextFaceW(hdc, 0, NULL);
847 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
848 GetTextFaceW( hdc, res, nameW );
854 res = WideCharToMultiByte(CP_ACP, 0, nameW, -1, name, count, NULL, NULL);
858 /* GetTextFaceA does NOT include the nul byte in the return count. */
865 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
866 HeapFree( GetProcessHeap(), 0, nameW );
870 /***********************************************************************
871 * GetTextFaceW (GDI32.@)
873 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
878 DC * dc = get_dc_ptr( hdc );
881 dev = GET_DC_PHYSDEV( dc, pGetTextFace );
882 ret = dev->funcs->pGetTextFace( dev, count, name );
883 release_dc_ptr( dc );
888 /***********************************************************************
889 * GetTextExtentPoint32A (GDI32.@)
891 * See GetTextExtentPoint32W.
893 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
900 if (count < 0) return FALSE;
902 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
906 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
907 HeapFree( GetProcessHeap(), 0, p );
910 TRACE("(%p %s %d %p): returning %d x %d\n",
911 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
916 /***********************************************************************
917 * GetTextExtentPoint32W [GDI32.@]
919 * Computes width/height for a string.
921 * Computes width and height of the specified string.
927 BOOL WINAPI GetTextExtentPoint32W(
928 HDC hdc, /* [in] Handle of device context */
929 LPCWSTR str, /* [in] Address of text string */
930 INT count, /* [in] Number of characters in string */
931 LPSIZE size) /* [out] Address of structure for string size */
933 return GetTextExtentExPointW(hdc, str, count, 0, NULL, NULL, size);
936 /***********************************************************************
937 * GetTextExtentExPointI [GDI32.@]
939 * Computes width and height of the array of glyph indices.
942 * hdc [I] Handle of device context.
943 * indices [I] Glyph index array.
944 * count [I] Number of glyphs in array.
945 * max_ext [I] Maximum width in glyphs.
946 * nfit [O] Maximum number of characters.
947 * dxs [O] Partial string widths.
948 * size [O] Returned string size.
954 BOOL WINAPI GetTextExtentExPointI( HDC hdc, const WORD *indices, INT count, INT max_ext,
955 LPINT nfit, LPINT dxs, LPSIZE size )
961 if (count < 0) return FALSE;
963 dc = get_dc_ptr( hdc );
964 if (!dc) return FALSE;
966 dev = GET_DC_PHYSDEV( dc, pGetTextExtentExPointI );
967 ret = dev->funcs->pGetTextExtentExPointI( dev, indices, count, max_ext, nfit, dxs, size );
968 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
969 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
970 size->cx += count * dc->charExtra;
971 release_dc_ptr( dc );
973 TRACE("(%p %p %d %p): returning %d x %d\n",
974 hdc, indices, count, size, size->cx, size->cy );
978 /***********************************************************************
979 * GetTextExtentPointI [GDI32.@]
981 * Computes width and height of the array of glyph indices.
984 * hdc [I] Handle of device context.
985 * indices [I] Glyph index array.
986 * count [I] Number of glyphs in array.
987 * size [O] Returned string size.
993 BOOL WINAPI GetTextExtentPointI( HDC hdc, const WORD *indices, INT count, LPSIZE size )
995 return GetTextExtentExPointI( hdc, indices, count, 0, NULL, NULL, size );
999 /***********************************************************************
1000 * GetTextExtentPointA (GDI32.@)
1002 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
1005 TRACE("not bug compatible.\n");
1006 return GetTextExtentPoint32A( hdc, str, count, size );
1009 /***********************************************************************
1010 * GetTextExtentPointW (GDI32.@)
1012 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1015 TRACE("not bug compatible.\n");
1016 return GetTextExtentPoint32W( hdc, str, count, size );
1020 /***********************************************************************
1021 * GetTextExtentExPointA (GDI32.@)
1023 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1024 INT maxExt, LPINT lpnFit,
1025 LPINT alpDx, LPSIZE size )
1032 if (count < 0) return FALSE;
1036 walpDx = HeapAlloc( GetProcessHeap(), 0, count * sizeof(INT) );
1037 if (!walpDx) return FALSE;
1040 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1041 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
1044 INT n = lpnFit ? *lpnFit : wlen;
1046 for(i = 0, j = 0; i < n; i++, j++)
1048 alpDx[j] = walpDx[i];
1049 if (IsDBCSLeadByte(str[j])) alpDx[++j] = walpDx[i];
1052 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1053 HeapFree( GetProcessHeap(), 0, p );
1054 HeapFree( GetProcessHeap(), 0, walpDx );
1059 /***********************************************************************
1060 * GetTextExtentExPointW (GDI32.@)
1062 * Return the size of the string as it would be if it was output properly by
1065 * This should include
1066 * - Intercharacter spacing
1067 * - justification spacing (not yet done)
1068 * - kerning? see below
1070 * Kerning. Since kerning would be carried out by the rendering code it should
1071 * be done by the driver. However they don't support it yet. Also I am not
1072 * yet persuaded that (certainly under Win95) any kerning is actually done.
1074 * str: According to MSDN this should be null-terminated. That is not true; a
1075 * null will not terminate it early.
1076 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1077 * than count. I have seen it be either the size of the full string or
1078 * 1 less than the size of the full string. I have not seen it bear any
1079 * resemblance to the portion that would fit.
1080 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1081 * trailing intercharacter spacing and any trailing justification.
1084 * Currently we do this by measuring each character etc. We should do it by
1085 * passing the request to the driver, perhaps by extending the
1086 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1087 * thinking about kerning issues and rounding issues in the justification.
1090 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1091 INT maxExt, LPINT lpnFit,
1092 LPINT alpDx, LPSIZE size )
1101 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1103 if (count < 0) return FALSE;
1105 dc = get_dc_ptr(hdc);
1106 if (!dc) return FALSE;
1108 GetTextMetricsW(hdc, &tm);
1110 /* If we need to calculate nFit, then we need the partial extents even if
1111 the user hasn't provided us with an array. */
1114 dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]);
1118 SetLastError(ERROR_OUTOFMEMORY);
1125 dev = GET_DC_PHYSDEV( dc, pGetTextExtentExPoint );
1126 ret = dev->funcs->pGetTextExtentExPoint(dev, str, count, 0, NULL, dxs, size);
1128 /* Perform device size to world size transformations. */
1131 INT extra = dc->charExtra,
1132 breakExtra = dc->breakExtra,
1133 breakRem = dc->breakRem,
1138 for (i = 0; i < count; ++i)
1140 dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
1141 dxs[i] += (i+1) * extra;
1142 if (count > 1 && (breakExtra || breakRem) && str[i] == tm.tmBreakChar)
1144 dxs[i] += breakExtra;
1151 if (dxs[i] <= maxExt)
1154 breakRem = dc->breakRem;
1156 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1157 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1159 if (!dxs && count > 1 && (breakExtra || breakRem))
1161 for (i = 0; i < count; i++)
1163 if (str[i] == tm.tmBreakChar)
1165 size->cx += breakExtra;
1180 HeapFree(GetProcessHeap(), 0, dxs);
1182 release_dc_ptr( dc );
1184 TRACE("returning %d %d x %d\n",nFit,size->cx,size->cy);
1188 /***********************************************************************
1189 * GetTextMetricsA (GDI32.@)
1191 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1195 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1196 FONT_TextMetricWToA( &tm32, metrics );
1200 /***********************************************************************
1201 * GetTextMetricsW (GDI32.@)
1203 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1207 DC * dc = get_dc_ptr( hdc );
1208 if (!dc) return FALSE;
1210 physdev = GET_DC_PHYSDEV( dc, pGetTextMetrics );
1211 ret = physdev->funcs->pGetTextMetrics( physdev, metrics );
1215 /* device layer returns values in device units
1216 * therefore we have to convert them to logical */
1218 metrics->tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1219 metrics->tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1221 #define WDPTOLP(x) ((x<0)? \
1222 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1223 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1224 #define HDPTOLP(y) ((y<0)? \
1225 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1226 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1228 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1229 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1230 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1231 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1232 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1233 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1234 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1235 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1239 TRACE("text metrics:\n"
1240 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1241 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1242 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1243 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1244 " PitchAndFamily = %02x\n"
1245 " --------------------\n"
1246 " InternalLeading = %i\n"
1250 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1251 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1252 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1253 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1254 metrics->tmPitchAndFamily,
1255 metrics->tmInternalLeading,
1258 metrics->tmHeight );
1260 release_dc_ptr( dc );
1265 /***********************************************************************
1266 * GetOutlineTextMetricsA (GDI32.@)
1267 * Gets metrics for TrueType fonts.
1270 * If the supplied buffer isn't big enough Windows partially fills it up to
1271 * its given length and returns that length.
1274 * Success: Non-zero or size of required buffer
1277 UINT WINAPI GetOutlineTextMetricsA(
1278 HDC hdc, /* [in] Handle of device context */
1279 UINT cbData, /* [in] Size of metric data array */
1280 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1282 char buf[512], *ptr;
1284 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1285 OUTLINETEXTMETRICA *output = lpOTM;
1288 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1290 if(ret > sizeof(buf))
1291 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1292 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1294 needed = sizeof(OUTLINETEXTMETRICA);
1295 if(lpOTMW->otmpFamilyName)
1296 needed += WideCharToMultiByte(CP_ACP, 0,
1297 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1298 NULL, 0, NULL, NULL);
1299 if(lpOTMW->otmpFaceName)
1300 needed += WideCharToMultiByte(CP_ACP, 0,
1301 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1302 NULL, 0, NULL, NULL);
1303 if(lpOTMW->otmpStyleName)
1304 needed += WideCharToMultiByte(CP_ACP, 0,
1305 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1306 NULL, 0, NULL, NULL);
1307 if(lpOTMW->otmpFullName)
1308 needed += WideCharToMultiByte(CP_ACP, 0,
1309 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1310 NULL, 0, NULL, NULL);
1317 TRACE("needed = %d\n", needed);
1319 /* Since the supplied buffer isn't big enough, we'll alloc one
1320 that is and memcpy the first cbData bytes into the lpOTM at
1322 output = HeapAlloc(GetProcessHeap(), 0, needed);
1324 ret = output->otmSize = min(needed, cbData);
1325 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1326 output->otmFiller = 0;
1327 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1328 output->otmfsSelection = lpOTMW->otmfsSelection;
1329 output->otmfsType = lpOTMW->otmfsType;
1330 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1331 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1332 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1333 output->otmEMSquare = lpOTMW->otmEMSquare;
1334 output->otmAscent = lpOTMW->otmAscent;
1335 output->otmDescent = lpOTMW->otmDescent;
1336 output->otmLineGap = lpOTMW->otmLineGap;
1337 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1338 output->otmsXHeight = lpOTMW->otmsXHeight;
1339 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1340 output->otmMacAscent = lpOTMW->otmMacAscent;
1341 output->otmMacDescent = lpOTMW->otmMacDescent;
1342 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1343 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1344 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1345 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1346 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1347 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1348 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1349 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1350 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1351 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1354 ptr = (char*)(output + 1);
1355 left = needed - sizeof(*output);
1357 if(lpOTMW->otmpFamilyName) {
1358 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1359 len = WideCharToMultiByte(CP_ACP, 0,
1360 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1361 ptr, left, NULL, NULL);
1365 output->otmpFamilyName = 0;
1367 if(lpOTMW->otmpFaceName) {
1368 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1369 len = WideCharToMultiByte(CP_ACP, 0,
1370 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1371 ptr, left, NULL, NULL);
1375 output->otmpFaceName = 0;
1377 if(lpOTMW->otmpStyleName) {
1378 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1379 len = WideCharToMultiByte(CP_ACP, 0,
1380 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1381 ptr, left, NULL, NULL);
1385 output->otmpStyleName = 0;
1387 if(lpOTMW->otmpFullName) {
1388 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1389 len = WideCharToMultiByte(CP_ACP, 0,
1390 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1391 ptr, left, NULL, NULL);
1394 output->otmpFullName = 0;
1398 if(output != lpOTM) {
1399 memcpy(lpOTM, output, cbData);
1400 HeapFree(GetProcessHeap(), 0, output);
1402 /* check if the string offsets really fit into the provided size */
1403 /* FIXME: should we check string length as well? */
1404 /* make sure that we don't read/write beyond the provided buffer */
1405 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(LPSTR))
1407 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1408 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1411 /* make sure that we don't read/write beyond the provided buffer */
1412 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(LPSTR))
1414 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1415 lpOTM->otmpFaceName = 0; /* doesn't fit */
1418 /* make sure that we don't read/write beyond the provided buffer */
1419 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(LPSTR))
1421 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1422 lpOTM->otmpStyleName = 0; /* doesn't fit */
1425 /* make sure that we don't read/write beyond the provided buffer */
1426 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(LPSTR))
1428 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1429 lpOTM->otmpFullName = 0; /* doesn't fit */
1434 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1435 HeapFree(GetProcessHeap(), 0, lpOTMW);
1441 /***********************************************************************
1442 * GetOutlineTextMetricsW [GDI32.@]
1444 UINT WINAPI GetOutlineTextMetricsW(
1445 HDC hdc, /* [in] Handle of device context */
1446 UINT cbData, /* [in] Size of metric data array */
1447 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1449 DC *dc = get_dc_ptr( hdc );
1450 OUTLINETEXTMETRICW *output = lpOTM;
1454 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1457 dev = GET_DC_PHYSDEV( dc, pGetOutlineTextMetrics );
1458 ret = dev->funcs->pGetOutlineTextMetrics( dev, cbData, output );
1460 if (lpOTM && ret > cbData)
1462 output = HeapAlloc(GetProcessHeap(), 0, ret);
1463 ret = dev->funcs->pGetOutlineTextMetrics( dev, ret, output );
1468 output->otmTextMetrics.tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1469 output->otmTextMetrics.tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1471 #define WDPTOLP(x) ((x<0)? \
1472 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1473 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1474 #define HDPTOLP(y) ((y<0)? \
1475 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1476 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1478 output->otmTextMetrics.tmHeight = HDPTOLP(output->otmTextMetrics.tmHeight);
1479 output->otmTextMetrics.tmAscent = HDPTOLP(output->otmTextMetrics.tmAscent);
1480 output->otmTextMetrics.tmDescent = HDPTOLP(output->otmTextMetrics.tmDescent);
1481 output->otmTextMetrics.tmInternalLeading = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1482 output->otmTextMetrics.tmExternalLeading = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1483 output->otmTextMetrics.tmAveCharWidth = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1484 output->otmTextMetrics.tmMaxCharWidth = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1485 output->otmTextMetrics.tmOverhang = WDPTOLP(output->otmTextMetrics.tmOverhang);
1486 output->otmAscent = HDPTOLP(output->otmAscent);
1487 output->otmDescent = HDPTOLP(output->otmDescent);
1488 output->otmLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmLineGap));
1489 output->otmsCapEmHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsCapEmHeight));
1490 output->otmsXHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsXHeight));
1491 output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1492 output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1493 output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1494 output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1495 output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1496 output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1497 output->otmMacLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmMacLineGap));
1498 output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1499 output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1500 output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1501 output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1502 output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1503 output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1504 output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1505 output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1506 output->otmsStrikeoutSize = abs(INTERNAL_YDSTOWS(dc,output->otmsStrikeoutSize));
1507 output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1508 output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1509 output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1514 memcpy(lpOTM, output, cbData);
1515 HeapFree(GetProcessHeap(), 0, output);
1523 static LPSTR FONT_GetCharsByRangeA(HDC hdc, UINT firstChar, UINT lastChar, PINT pByteLen)
1525 INT i, count = lastChar - firstChar + 1;
1532 switch (GdiGetCodePage(hdc))
1539 if (lastChar > 0xffff)
1541 if ((firstChar ^ lastChar) > 0xff)
1545 if (lastChar > 0xff)
1550 str = HeapAlloc(GetProcessHeap(), 0, count * 2 + 1);
1554 for(i = 0, c = firstChar; c <= lastChar; i++, c++)
1557 str[i++] = (BYTE)(c >> 8);
1567 /***********************************************************************
1568 * GetCharWidthW (GDI32.@)
1569 * GetCharWidth32W (GDI32.@)
1571 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1577 DC * dc = get_dc_ptr( hdc );
1579 if (!dc) return FALSE;
1581 dev = GET_DC_PHYSDEV( dc, pGetCharWidth );
1582 ret = dev->funcs->pGetCharWidth( dev, firstChar, lastChar, buffer );
1586 /* convert device units to logical */
1587 for( i = firstChar; i <= lastChar; i++, buffer++ )
1588 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1590 release_dc_ptr( dc );
1595 /***********************************************************************
1596 * GetCharWidthA (GDI32.@)
1597 * GetCharWidth32A (GDI32.@)
1599 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1607 str = FONT_GetCharsByRangeA(hdc, firstChar, lastChar, &i);
1611 wstr = FONT_mbtowc(hdc, str, i, &wlen, NULL);
1613 for(i = 0; i < wlen; i++)
1615 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1623 HeapFree(GetProcessHeap(), 0, str);
1624 HeapFree(GetProcessHeap(), 0, wstr);
1630 /* helper for nulldrv_ExtTextOut */
1631 static DWORD get_glyph_bitmap( HDC hdc, UINT index, UINT aa_flags,
1632 GLYPHMETRICS *metrics, struct gdi_image_bits *image )
1634 UINT ggo_flags = aa_flags | GGO_GLYPH_INDEX;
1635 static const MAT2 identity = { {0,1}, {0,0}, {0,0}, {0,1} };
1636 UINT indices[3] = {0, 0, 0x20};
1643 for (i = 0; i < sizeof(indices) / sizeof(indices[0]); i++)
1646 ret = GetGlyphOutlineW( hdc, index, ggo_flags, metrics, 0, NULL, &identity );
1647 if (ret != GDI_ERROR) break;
1650 if (ret == GDI_ERROR) return ERROR_NOT_FOUND;
1651 if (!image) return ERROR_SUCCESS;
1655 if (!ret) return ERROR_SUCCESS; /* empty glyph */
1657 stride = get_dib_stride( metrics->gmBlackBoxX, 1 );
1658 size = metrics->gmBlackBoxY * stride;
1660 if (!(image->ptr = HeapAlloc( GetProcessHeap(), 0, size ))) return ERROR_OUTOFMEMORY;
1661 image->is_copy = TRUE;
1662 image->free = free_heap_bits;
1664 ret = GetGlyphOutlineW( hdc, index, ggo_flags, metrics, size, image->ptr, &identity );
1665 if (ret == GDI_ERROR)
1667 HeapFree( GetProcessHeap(), 0, image->ptr );
1668 return ERROR_NOT_FOUND;
1670 return ERROR_SUCCESS;
1673 /* helper for nulldrv_ExtTextOut */
1674 static RECT get_total_extents( HDC hdc, INT x, INT y, UINT flags, UINT aa_flags,
1675 LPCWSTR str, UINT count, const INT *dx )
1680 rect.left = rect.top = INT_MAX;
1681 rect.right = rect.bottom = INT_MIN;
1682 for (i = 0; i < count; i++)
1684 GLYPHMETRICS metrics;
1686 if (get_glyph_bitmap( hdc, (UINT)str[i], aa_flags, &metrics, NULL )) continue;
1688 rect.left = min( rect.left, x + metrics.gmptGlyphOrigin.x );
1689 rect.top = min( rect.top, y - metrics.gmptGlyphOrigin.y );
1690 rect.right = max( rect.right, x + metrics.gmptGlyphOrigin.x + (int)metrics.gmBlackBoxX );
1691 rect.bottom = max( rect.bottom, y - metrics.gmptGlyphOrigin.y + (int)metrics.gmBlackBoxY );
1695 if (flags & ETO_PDY)
1698 y += dx[ i * 2 + 1];
1704 x += metrics.gmCellIncX;
1705 y += metrics.gmCellIncY;
1711 /* helper for nulldrv_ExtTextOut */
1712 static void draw_glyph( HDC hdc, INT origin_x, INT origin_y, const GLYPHMETRICS *metrics,
1713 const struct gdi_image_bits *image, const RECT *clip )
1715 static const BYTE masks[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
1716 UINT x, y, i, count;
1717 BYTE *ptr = image->ptr;
1718 int stride = get_dib_stride( metrics->gmBlackBoxX, 1 );
1720 RECT rect, clipped_rect;
1722 rect.left = origin_x + metrics->gmptGlyphOrigin.x;
1723 rect.top = origin_y - metrics->gmptGlyphOrigin.y;
1724 rect.right = rect.left + metrics->gmBlackBoxX;
1725 rect.bottom = rect.top + metrics->gmBlackBoxY;
1726 if (!clip) clipped_rect = rect;
1727 else if (!intersect_rect( &clipped_rect, &rect, clip )) return;
1729 pts = HeapAlloc( GetProcessHeap(), 0,
1730 max(2,metrics->gmBlackBoxX) * metrics->gmBlackBoxY * sizeof(*pts) );
1734 ptr += (clipped_rect.top - rect.top) * stride;
1735 for (y = clipped_rect.top; y < clipped_rect.bottom; y++, ptr += stride)
1737 for (x = clipped_rect.left - rect.left; x < clipped_rect.right - rect.left; x++)
1739 while (x < clipped_rect.right - rect.left && !(ptr[x / 8] & masks[x % 8])) x++;
1740 pts[count].x = rect.left + x;
1741 while (x < clipped_rect.right - rect.left && (ptr[x / 8] & masks[x % 8])) x++;
1742 pts[count + 1].x = rect.left + x;
1743 if (pts[count + 1].x > pts[count].x)
1745 pts[count].y = pts[count + 1].y = y;
1750 DPtoLP( hdc, pts, count );
1751 for (i = 0; i < count; i += 2) Polyline( hdc, pts + i, 2 );
1752 HeapFree( GetProcessHeap(), 0, pts );
1755 /***********************************************************************
1756 * nulldrv_ExtTextOut
1758 BOOL nulldrv_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags, const RECT *rect,
1759 LPCWSTR str, UINT count, const INT *dx )
1761 DC *dc = get_nulldrv_dc( dev );
1767 if (flags & ETO_OPAQUE)
1770 HBRUSH brush = CreateSolidBrush( GetNearestColor( dev->hdc, GetBkColor(dev->hdc) ));
1774 orig = SelectObject( dev->hdc, brush );
1775 DPtoLP( dev->hdc, (POINT *)&rc, 2 );
1776 PatBlt( dev->hdc, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, PATCOPY );
1777 SelectObject( dev->hdc, orig );
1778 DeleteObject( brush );
1782 if (!count) return TRUE;
1784 aa_flags = get_font_aa_flags( dev->hdc );
1786 if (aa_flags != GGO_BITMAP)
1788 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1789 BITMAPINFO *info = (BITMAPINFO *)buffer;
1790 struct gdi_image_bits bits;
1791 struct bitblt_coords src, dst;
1795 dst_dev = GET_DC_PHYSDEV( dc, pPutImage );
1796 src.visrect = get_total_extents( dev->hdc, x, y, flags, aa_flags, str, count, dx );
1797 if (flags & ETO_CLIPPED) intersect_rect( &src.visrect, &src.visrect, rect );
1798 if (get_clip_box( dc, &clip )) intersect_rect( &src.visrect, &src.visrect, &clip );
1799 if (is_rect_empty( &src.visrect )) return TRUE;
1801 /* FIXME: check for ETO_OPAQUE and avoid GetImage */
1802 src.x = src.visrect.left;
1803 src.y = src.visrect.top;
1804 src.width = src.visrect.right - src.visrect.left;
1805 src.height = src.visrect.bottom - src.visrect.top;
1807 if ((flags & ETO_OPAQUE) && (src.visrect.left >= rect->left) && (src.visrect.top >= rect->top) &&
1808 (src.visrect.right <= rect->right) && (src.visrect.bottom <= rect->bottom))
1810 /* we can avoid the GetImage, just query the needed format */
1811 memset( &info->bmiHeader, 0, sizeof(info->bmiHeader) );
1812 info->bmiHeader.biSize = sizeof(info->bmiHeader);
1813 info->bmiHeader.biWidth = src.width;
1814 info->bmiHeader.biHeight = -src.height;
1815 err = dst_dev->funcs->pPutImage( dst_dev, 0, 0, info, NULL, NULL, NULL, 0 );
1816 if (!err || err == ERROR_BAD_FORMAT)
1818 /* make the source rectangle relative to the source bits */
1820 src.visrect.left = src.visrect.top = 0;
1821 src.visrect.right = src.width;
1822 src.visrect.bottom = src.height;
1824 bits.ptr = HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( info ));
1825 if (!bits.ptr) return ERROR_OUTOFMEMORY;
1826 bits.is_copy = TRUE;
1827 bits.free = free_heap_bits;
1828 err = ERROR_SUCCESS;
1833 PHYSDEV src_dev = GET_DC_PHYSDEV( dc, pGetImage );
1834 err = src_dev->funcs->pGetImage( src_dev, 0, info, &bits, &src );
1835 if (!err && !bits.is_copy)
1837 void *ptr = HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( info ));
1840 if (bits.free) bits.free( &bits );
1841 return ERROR_OUTOFMEMORY;
1843 memcpy( ptr, bits.ptr, get_dib_image_size( info ));
1844 if (bits.free) bits.free( &bits );
1846 bits.is_copy = TRUE;
1847 bits.free = free_heap_bits;
1852 /* make x,y relative to the image bits */
1853 x += src.visrect.left - dst.visrect.left;
1854 y += src.visrect.top - dst.visrect.top;
1855 render_aa_text_bitmapinfo( dev->hdc, info, &bits, &src, x, y, flags,
1856 aa_flags, str, count, dx );
1857 err = dst_dev->funcs->pPutImage( dst_dev, 0, 0, info, &bits, &src, &dst, SRCCOPY );
1858 if (bits.free) bits.free( &bits );
1863 pen = CreatePen( PS_SOLID, 1, GetTextColor(dev->hdc) );
1864 orig = SelectObject( dev->hdc, pen );
1866 for (i = 0; i < count; i++)
1868 GLYPHMETRICS metrics;
1869 struct gdi_image_bits image;
1871 err = get_glyph_bitmap( dev->hdc, (UINT)str[i], GGO_BITMAP, &metrics, &image );
1874 if (image.ptr) draw_glyph( dev->hdc, x, y, &metrics, &image, (flags & ETO_CLIPPED) ? rect : NULL );
1875 if (image.free) image.free( &image );
1879 if (flags & ETO_PDY)
1882 y += dx[ i * 2 + 1];
1888 x += metrics.gmCellIncX;
1889 y += metrics.gmCellIncY;
1893 SelectObject( dev->hdc, orig );
1894 DeleteObject( pen );
1899 /***********************************************************************
1900 * ExtTextOutA (GDI32.@)
1904 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1905 const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1913 if (flags & ETO_GLYPH_INDEX)
1914 return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
1916 p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
1919 unsigned int i = 0, j = 0;
1921 /* allocate enough for a ETO_PDY */
1922 lpDxW = HeapAlloc( GetProcessHeap(), 0, 2*wlen*sizeof(INT));
1924 if(IsDBCSLeadByteEx(codepage, str[i]))
1928 lpDxW[j++] = lpDx[i * 2] + lpDx[(i + 1) * 2];
1929 lpDxW[j++] = lpDx[i * 2 + 1] + lpDx[(i + 1) * 2 + 1];
1932 lpDxW[j++] = lpDx[i] + lpDx[i + 1];
1939 lpDxW[j++] = lpDx[i * 2];
1940 lpDxW[j++] = lpDx[i * 2 + 1];
1943 lpDxW[j++] = lpDx[i];
1949 ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1951 HeapFree( GetProcessHeap(), 0, p );
1952 HeapFree( GetProcessHeap(), 0, lpDxW );
1957 /***********************************************************************
1958 * ExtTextOutW (GDI32.@)
1960 * Draws text using the currently selected font, background color, and text color.
1964 * x,y [I] coordinates of string
1966 * ETO_GRAYED - undocumented on MSDN
1967 * ETO_OPAQUE - use background color for fill the rectangle
1968 * ETO_CLIPPED - clipping text to the rectangle
1969 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1970 * than encoded characters. Implies ETO_IGNORELANGUAGE
1971 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1972 * Affects BiDi ordering
1973 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1974 * ETO_PDY - unimplemented
1975 * ETO_NUMERICSLATIN - unimplemented always assumed -
1976 * do not translate numbers into locale representations
1977 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1978 * lprect [I] dimensions for clipping or/and opaquing
1979 * str [I] text string
1980 * count [I] number of symbols in string
1981 * lpDx [I] optional parameter with distance between drawing characters
1987 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1988 const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1991 LPWSTR reordered_str = (LPWSTR)str;
1992 WORD *glyphs = NULL;
1993 UINT align = GetTextAlign( hdc );
1994 DWORD layout = GetLayout( hdc );
1998 double cosEsc, sinEsc;
2002 BOOL done_extents = FALSE;
2003 POINT *deltas = NULL, width = {0, 0};
2005 DC * dc = get_dc_ptr( hdc );
2008 static int quietfixme = 0;
2010 if (!dc) return FALSE;
2012 breakRem = dc->breakRem;
2014 if (quietfixme == 0 && flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN))
2016 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN unimplemented\n");
2021 physdev = GET_DC_PHYSDEV( dc, pExtTextOut );
2022 type = GetObjectType(hdc);
2023 if(type == OBJ_METADC || type == OBJ_ENHMETADC)
2025 ret = physdev->funcs->pExtTextOut( physdev, x, y, flags, lprect, str, count, lpDx );
2026 release_dc_ptr( dc );
2031 flags &= ~ETO_CLIPPED;
2033 if (flags & ETO_RTLREADING) align |= TA_RTLREADING;
2034 if (layout & LAYOUT_RTL)
2036 if ((align & TA_CENTER) != TA_CENTER) align ^= TA_RIGHT;
2037 align ^= TA_RTLREADING;
2040 if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && count > 0 )
2043 reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
2045 BIDI_Reorder( hdc, str, count, GCP_REORDER,
2046 (align & TA_RTLREADING) ? WINE_GCPW_FORCE_RTL : WINE_GCPW_FORCE_LTR,
2047 reordered_str, count, NULL, &glyphs, &cGlyphs);
2049 flags |= ETO_IGNORELANGUAGE;
2052 flags |= ETO_GLYPH_INDEX;
2053 if (cGlyphs != count)
2057 else if(flags & ETO_GLYPH_INDEX)
2058 glyphs = reordered_str;
2060 TRACE("%p, %d, %d, %08x, %s, %s, %d, %p)\n", hdc, x, y, flags,
2061 wine_dbgstr_rect(lprect), debugstr_wn(str, count), count, lpDx);
2062 TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
2064 if(align & TA_UPDATECP)
2066 GetCurrentPositionEx( hdc, &pt );
2071 GetTextMetricsW(hdc, &tm);
2072 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
2074 if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
2075 lf.lfEscapement = 0;
2077 if(lf.lfEscapement != 0)
2079 cosEsc = cos(lf.lfEscapement * M_PI / 1800);
2080 sinEsc = sin(lf.lfEscapement * M_PI / 1800);
2088 if(flags & (ETO_CLIPPED | ETO_OPAQUE))
2092 if(flags & ETO_GLYPH_INDEX)
2093 GetTextExtentPointI(hdc, glyphs, count, &sz);
2095 GetTextExtentPointW(hdc, reordered_str, count, &sz);
2097 done_extents = TRUE;
2100 rc.right = x + sz.cx;
2101 rc.bottom = y + sz.cy;
2108 LPtoDP(hdc, (POINT*)&rc, 2);
2110 if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
2111 if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
2114 if (flags & ETO_OPAQUE)
2115 physdev->funcs->pExtTextOut( physdev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL );
2125 LPtoDP(hdc, &pt, 1);
2129 char_extra = GetTextCharacterExtra(hdc);
2130 if(char_extra || dc->breakExtra || breakRem || lpDx || lf.lfEscapement != 0)
2134 POINT total = {0, 0}, desired[2];
2136 deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
2137 for(i = 0; i < count; i++)
2143 deltas[i].x = lpDx[i * 2] + char_extra;
2144 deltas[i].y = -lpDx[i * 2 + 1];
2148 deltas[i].x = lpDx[i] + char_extra;
2155 if(flags & ETO_GLYPH_INDEX)
2156 GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
2158 GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
2160 deltas[i].x = tmpsz.cx;
2164 if (!(flags & ETO_GLYPH_INDEX) && (dc->breakExtra || breakRem) && reordered_str[i] == tm.tmBreakChar)
2166 deltas[i].x = deltas[i].x + dc->breakExtra;
2173 total.x += deltas[i].x;
2174 total.y += deltas[i].y;
2176 desired[0].x = desired[0].y = 0;
2178 desired[1].x = cosEsc * total.x + sinEsc * total.y;
2179 desired[1].y = -sinEsc * total.x + cosEsc * total.y;
2181 LPtoDP(hdc, desired, 2);
2182 desired[1].x -= desired[0].x;
2183 desired[1].y -= desired[0].y;
2184 if (layout & LAYOUT_RTL) desired[1].x = -desired[1].x;
2186 deltas[i].x = desired[1].x - width.x;
2187 deltas[i].y = desired[1].y - width.y;
2197 if(flags & ETO_GLYPH_INDEX)
2198 GetTextExtentPointI(hdc, glyphs, count, &sz);
2200 GetTextExtentPointW(hdc, reordered_str, count, &sz);
2201 done_extents = TRUE;
2203 width.x = abs(INTERNAL_XWSTODS(dc, sz.cx));
2207 tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
2208 tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
2209 switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
2212 if (align & TA_UPDATECP)
2216 DPtoLP(hdc, &pt, 1);
2217 MoveToEx(hdc, pt.x, pt.y, NULL);
2229 if (align & TA_UPDATECP)
2233 DPtoLP(hdc, &pt, 1);
2234 MoveToEx(hdc, pt.x, pt.y, NULL);
2239 switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
2242 y += tm.tmAscent * cosEsc;
2243 x += tm.tmAscent * sinEsc;
2247 y -= tm.tmDescent * cosEsc;
2248 x -= tm.tmDescent * sinEsc;
2255 if (GetBkMode(hdc) != TRANSPARENT)
2257 if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
2259 if(!(flags & ETO_OPAQUE) || x < rc.left || x + width.x >= rc.right ||
2260 y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
2264 rc.right = x + width.x;
2265 rc.top = y - tm.tmAscent;
2266 rc.bottom = y + tm.tmDescent;
2268 if(flags & ETO_CLIPPED)
2270 rc.left = max(lprect->left, rc.left);
2271 rc.right = min(lprect->right, rc.right);
2272 rc.top = max(lprect->top, rc.top);
2273 rc.bottom = min(lprect->bottom, rc.bottom);
2275 if(rc.left < rc.right && rc.top < rc.bottom)
2276 physdev->funcs->pExtTextOut( physdev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL );
2281 if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
2283 HFONT orig_font = dc->hFont, cur_font;
2286 POINT *offsets = NULL;
2289 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2290 for(i = 0; i < count; i++)
2292 WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
2293 if(cur_font != dc->hFont)
2298 offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
2299 offsets[0].x = offsets[0].y = 0;
2304 for(j = 1; j < count; j++)
2306 GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
2307 offsets[j].x = offsets[j - 1].x + abs(INTERNAL_XWSTODS(dc, tmpsz.cx));
2313 for(j = 1; j < count; j++)
2315 offsets[j].x = offsets[j - 1].x + deltas[j].x;
2316 offsets[j].y = offsets[j - 1].y + deltas[j].y;
2322 physdev->funcs->pExtTextOut( physdev, x + offsets[i - span].x,
2323 y + offsets[i - span].y,
2324 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc, glyphs,
2325 span, deltas ? (INT*)(deltas + (i - span)) : NULL);
2328 SelectObject(hdc, cur_font);
2330 glyphs[span++] = glyph;
2334 ret = physdev->funcs->pExtTextOut(physdev, x + (offsets ? offsets[count - span].x : 0),
2335 y + (offsets ? offsets[count - span].y : 0),
2336 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc, glyphs,
2337 span, deltas ? (INT*)(deltas + (count - span)) : NULL);
2338 SelectObject(hdc, orig_font);
2339 HeapFree(GetProcessHeap(), 0, offsets);
2345 if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
2347 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2348 GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
2349 flags |= ETO_GLYPH_INDEX;
2351 ret = physdev->funcs->pExtTextOut( physdev, x, y, (flags & ~ETO_OPAQUE), &rc,
2352 glyphs ? glyphs : reordered_str, count, (INT*)deltas );
2356 HeapFree(GetProcessHeap(), 0, deltas);
2357 if(glyphs != reordered_str)
2358 HeapFree(GetProcessHeap(), 0, glyphs);
2359 if(reordered_str != str)
2360 HeapFree(GetProcessHeap(), 0, reordered_str);
2362 release_dc_ptr( dc );
2364 if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2366 int underlinePos, strikeoutPos;
2367 int underlineWidth, strikeoutWidth;
2368 UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2369 OUTLINETEXTMETRICW* otm = NULL;
2371 HPEN hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2372 HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2374 hbrush = SelectObject(hdc, hbrush);
2379 underlineWidth = tm.tmAscent / 20 + 1;
2380 strikeoutPos = tm.tmAscent / 2;
2381 strikeoutWidth = underlineWidth;
2385 otm = HeapAlloc(GetProcessHeap(), 0, size);
2386 GetOutlineTextMetricsW(hdc, size, otm);
2387 underlinePos = abs( INTERNAL_YWSTODS( dc, otm->otmsUnderscorePosition ));
2388 if (otm->otmsUnderscorePosition < 0) underlinePos = -underlinePos;
2389 underlineWidth = abs( INTERNAL_YWSTODS( dc, otm->otmsUnderscoreSize ));
2390 if (otm->otmsUnderscoreSize < 0) underlineWidth = -underlineWidth;
2391 strikeoutPos = abs( INTERNAL_YWSTODS( dc, otm->otmsStrikeoutPosition ));
2392 if (otm->otmsStrikeoutPosition < 0) strikeoutPos = -strikeoutPos;
2393 strikeoutWidth = abs( INTERNAL_YWSTODS( dc, otm->otmsStrikeoutSize ));
2394 HeapFree(GetProcessHeap(), 0, otm);
2400 pts[0].x = x - (underlinePos + underlineWidth / 2) * sinEsc;
2401 pts[0].y = y - (underlinePos + underlineWidth / 2) * cosEsc;
2402 pts[1].x = x + width.x - (underlinePos + underlineWidth / 2) * sinEsc;
2403 pts[1].y = y + width.y - (underlinePos + underlineWidth / 2) * cosEsc;
2404 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2405 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2406 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2407 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2408 pts[4].x = pts[0].x;
2409 pts[4].y = pts[0].y;
2410 DPtoLP(hdc, pts, 5);
2411 Polygon(hdc, pts, 5);
2416 pts[0].x = x - (strikeoutPos + strikeoutWidth / 2) * sinEsc;
2417 pts[0].y = y - (strikeoutPos + strikeoutWidth / 2) * cosEsc;
2418 pts[1].x = x + width.x - (strikeoutPos + strikeoutWidth / 2) * sinEsc;
2419 pts[1].y = y + width.y - (strikeoutPos + strikeoutWidth / 2) * cosEsc;
2420 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2421 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2422 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2423 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2424 pts[4].x = pts[0].x;
2425 pts[4].y = pts[0].y;
2426 DPtoLP(hdc, pts, 5);
2427 Polygon(hdc, pts, 5);
2430 SelectObject(hdc, hpen);
2431 hbrush = SelectObject(hdc, hbrush);
2432 DeleteObject(hbrush);
2439 /***********************************************************************
2440 * TextOutA (GDI32.@)
2442 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2444 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2448 /***********************************************************************
2449 * TextOutW (GDI32.@)
2451 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2453 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2457 /***********************************************************************
2458 * PolyTextOutA (GDI32.@)
2462 BOOL WINAPI PolyTextOutA( HDC hdc, const POLYTEXTA *pptxt, INT cStrings )
2464 for (; cStrings>0; cStrings--, pptxt++)
2465 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2472 /***********************************************************************
2473 * PolyTextOutW (GDI32.@)
2475 * Draw several Strings
2481 BOOL WINAPI PolyTextOutW( HDC hdc, const POLYTEXTW *pptxt, INT cStrings )
2483 for (; cStrings>0; cStrings--, pptxt++)
2484 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2490 /***********************************************************************
2491 * SetMapperFlags (GDI32.@)
2493 DWORD WINAPI SetMapperFlags( HDC hdc, DWORD flags )
2495 DC *dc = get_dc_ptr( hdc );
2496 DWORD ret = GDI_ERROR;
2500 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetMapperFlags );
2501 flags = physdev->funcs->pSetMapperFlags( physdev, flags );
2502 if (flags != GDI_ERROR)
2504 ret = dc->mapperFlags;
2505 dc->mapperFlags = flags;
2507 release_dc_ptr( dc );
2512 /***********************************************************************
2513 * GetAspectRatioFilterEx (GDI32.@)
2515 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2517 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2522 /***********************************************************************
2523 * GetCharABCWidthsA (GDI32.@)
2525 * See GetCharABCWidthsW.
2527 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2535 str = FONT_GetCharsByRangeA(hdc, firstChar, lastChar, &i);
2539 wstr = FONT_mbtowc(hdc, str, i, &wlen, NULL);
2542 HeapFree(GetProcessHeap(), 0, str);
2546 for(i = 0; i < wlen; i++)
2548 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2556 HeapFree(GetProcessHeap(), 0, str);
2557 HeapFree(GetProcessHeap(), 0, wstr);
2563 /******************************************************************************
2564 * GetCharABCWidthsW [GDI32.@]
2566 * Retrieves widths of characters in range.
2569 * hdc [I] Handle of device context
2570 * firstChar [I] First character in range to query
2571 * lastChar [I] Last character in range to query
2572 * abc [O] Address of character-width structure
2575 * Only works with TrueType fonts
2581 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2584 DC *dc = get_dc_ptr(hdc);
2589 if (!dc) return FALSE;
2593 release_dc_ptr( dc );
2597 dev = GET_DC_PHYSDEV( dc, pGetCharABCWidths );
2598 ret = dev->funcs->pGetCharABCWidths( dev, firstChar, lastChar, abc );
2601 /* convert device units to logical */
2602 for( i = firstChar; i <= lastChar; i++, abc++ ) {
2603 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2604 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2605 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2609 release_dc_ptr( dc );
2614 /******************************************************************************
2615 * GetCharABCWidthsI [GDI32.@]
2617 * Retrieves widths of characters in range.
2620 * hdc [I] Handle of device context
2621 * firstChar [I] First glyphs in range to query
2622 * count [I] Last glyphs in range to query
2623 * pgi [i] Array of glyphs to query
2624 * abc [O] Address of character-width structure
2627 * Only works with TrueType fonts
2633 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2634 LPWORD pgi, LPABC abc)
2636 DC *dc = get_dc_ptr(hdc);
2641 if (!dc) return FALSE;
2645 release_dc_ptr( dc );
2649 dev = GET_DC_PHYSDEV( dc, pGetCharABCWidthsI );
2650 ret = dev->funcs->pGetCharABCWidthsI( dev, firstChar, count, pgi, abc );
2653 /* convert device units to logical */
2654 for( i = 0; i < count; i++, abc++ ) {
2655 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2656 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2657 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2661 release_dc_ptr( dc );
2666 /***********************************************************************
2667 * GetGlyphOutlineA (GDI32.@)
2669 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2670 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2671 LPVOID lpBuffer, const MAT2 *lpmat2 )
2673 if (!lpmat2) return GDI_ERROR;
2675 if(!(fuFormat & GGO_GLYPH_INDEX)) {
2680 cp = GdiGetCodePage(hdc);
2681 if (IsDBCSLeadByteEx(cp, uChar >> 8)) {
2683 mbchs[0] = (uChar & 0xff00) >> 8;
2684 mbchs[1] = (uChar & 0xff);
2687 mbchs[0] = (uChar & 0xff);
2690 MultiByteToWideChar(cp, 0, mbchs, len, (LPWSTR)&uChar, 1);
2693 return GetGlyphOutlineW(hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer,
2697 /***********************************************************************
2698 * GetGlyphOutlineW (GDI32.@)
2700 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2701 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2702 LPVOID lpBuffer, const MAT2 *lpmat2 )
2708 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2709 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2711 if (!lpmat2) return GDI_ERROR;
2713 dc = get_dc_ptr(hdc);
2714 if(!dc) return GDI_ERROR;
2716 dev = GET_DC_PHYSDEV( dc, pGetGlyphOutline );
2717 ret = dev->funcs->pGetGlyphOutline( dev, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2718 release_dc_ptr( dc );
2723 /***********************************************************************
2724 * CreateScalableFontResourceA (GDI32.@)
2726 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2727 LPCSTR lpszResourceFile,
2728 LPCSTR lpszFontFile,
2729 LPCSTR lpszCurrentPath )
2731 LPWSTR lpszResourceFileW = NULL;
2732 LPWSTR lpszFontFileW = NULL;
2733 LPWSTR lpszCurrentPathW = NULL;
2737 if (lpszResourceFile)
2739 len = MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, NULL, 0);
2740 lpszResourceFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2741 MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, lpszResourceFileW, len);
2746 len = MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, NULL, 0);
2747 lpszFontFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2748 MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, lpszFontFileW, len);
2751 if (lpszCurrentPath)
2753 len = MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, NULL, 0);
2754 lpszCurrentPathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2755 MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, lpszCurrentPathW, len);
2758 ret = CreateScalableFontResourceW(fHidden, lpszResourceFileW,
2759 lpszFontFileW, lpszCurrentPathW);
2761 HeapFree(GetProcessHeap(), 0, lpszResourceFileW);
2762 HeapFree(GetProcessHeap(), 0, lpszFontFileW);
2763 HeapFree(GetProcessHeap(), 0, lpszCurrentPathW);
2768 /***********************************************************************
2769 * CreateScalableFontResourceW (GDI32.@)
2771 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2772 LPCWSTR lpszResourceFile,
2773 LPCWSTR lpszFontFile,
2774 LPCWSTR lpszCurrentPath )
2777 FIXME("(%d,%s,%s,%s): stub\n",
2778 fHidden, debugstr_w(lpszResourceFile), debugstr_w(lpszFontFile),
2779 debugstr_w(lpszCurrentPath) );
2781 /* fHidden=1 - only visible for the calling app, read-only, not
2782 * enumerated with EnumFonts/EnumFontFamilies
2783 * lpszCurrentPath can be NULL
2786 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2787 if ((f = CreateFileW(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2789 SetLastError(ERROR_FILE_EXISTS);
2792 return FALSE; /* create failed */
2795 /*************************************************************************
2796 * GetKerningPairsA (GDI32.@)
2798 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2799 LPKERNINGPAIR kern_pairA )
2803 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2804 KERNINGPAIR *kern_pairW;
2806 if (!cPairs && kern_pairA)
2808 SetLastError(ERROR_INVALID_PARAMETER);
2812 cp = GdiGetCodePage(hDC);
2814 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2815 * to fail on an invalid character for CP_SYMBOL.
2817 cpi.DefaultChar[0] = 0;
2818 if (cp != CP_SYMBOL && !GetCPInfo(cp, &cpi))
2820 FIXME("Can't find codepage %u info\n", cp);
2824 total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2825 if (!total_kern_pairs) return 0;
2827 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2828 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2830 for (i = 0; i < total_kern_pairs; i++)
2834 if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2837 if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2840 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2845 if (kern_pairs_copied >= cPairs) break;
2847 kern_pairA->wFirst = (BYTE)first;
2848 kern_pairA->wSecond = (BYTE)second;
2849 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2852 kern_pairs_copied++;
2855 HeapFree(GetProcessHeap(), 0, kern_pairW);
2857 return kern_pairs_copied;
2860 /*************************************************************************
2861 * GetKerningPairsW (GDI32.@)
2863 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2864 LPKERNINGPAIR lpKerningPairs )
2870 TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2872 if (!cPairs && lpKerningPairs)
2874 SetLastError(ERROR_INVALID_PARAMETER);
2878 dc = get_dc_ptr(hDC);
2881 dev = GET_DC_PHYSDEV( dc, pGetKerningPairs );
2882 ret = dev->funcs->pGetKerningPairs( dev, cPairs, lpKerningPairs );
2883 release_dc_ptr( dc );
2887 /*************************************************************************
2888 * TranslateCharsetInfo [GDI32.@]
2890 * Fills a CHARSETINFO structure for a character set, code page, or
2891 * font. This allows making the correspondence between different labels
2892 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2893 * of the same encoding.
2895 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2896 * only one codepage should be set in *lpSrc.
2899 * TRUE on success, FALSE on failure.
2902 BOOL WINAPI TranslateCharsetInfo(
2903 LPDWORD lpSrc, /* [in]
2904 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2905 if flags == TCI_SRCCHARSET: a character set value
2906 if flags == TCI_SRCCODEPAGE: a code page value
2908 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2909 DWORD flags /* [in] determines interpretation of lpSrc */)
2913 case TCI_SRCFONTSIG:
2914 while (index < MAXTCIINDEX && !(*lpSrc>>index & 0x0001)) index++;
2916 case TCI_SRCCODEPAGE:
2917 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciACP) index++;
2919 case TCI_SRCCHARSET:
2920 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciCharset) index++;
2925 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2926 *lpCs = FONT_tci[index];
2930 /*************************************************************************
2931 * GetFontLanguageInfo (GDI32.@)
2933 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2935 FONTSIGNATURE fontsig;
2936 static const DWORD GCP_DBCS_MASK=0x003F0000,
2937 GCP_DIACRITIC_MASK=0x00000000,
2938 FLI_GLYPHS_MASK=0x00000000,
2939 GCP_GLYPHSHAPE_MASK=0x00000040,
2940 GCP_KASHIDA_MASK=0x00000000,
2941 GCP_LIGATE_MASK=0x00000000,
2942 GCP_USEKERNING_MASK=0x00000000,
2943 GCP_REORDER_MASK=0x00000060;
2947 GetTextCharsetInfo( hdc, &fontsig, 0 );
2948 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2950 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2953 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2954 result|=GCP_DIACRITIC;
2956 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2959 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2960 result|=GCP_GLYPHSHAPE;
2962 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2963 result|=GCP_KASHIDA;
2965 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2968 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2969 result|=GCP_USEKERNING;
2971 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2972 if( GetTextAlign( hdc) & TA_RTLREADING )
2973 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2974 result|=GCP_REORDER;
2980 /*************************************************************************
2981 * GetFontData [GDI32.@]
2983 * Retrieve data for TrueType font.
2987 * success: Number of bytes returned
2988 * failure: GDI_ERROR
2992 * Calls SetLastError()
2995 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2996 LPVOID buffer, DWORD length)
2998 DC *dc = get_dc_ptr(hdc);
3002 if(!dc) return GDI_ERROR;
3004 dev = GET_DC_PHYSDEV( dc, pGetFontData );
3005 ret = dev->funcs->pGetFontData( dev, table, offset, buffer, length );
3006 release_dc_ptr( dc );
3010 /*************************************************************************
3011 * GetGlyphIndicesA [GDI32.@]
3013 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
3014 LPWORD pgi, DWORD flags)
3020 TRACE("(%p, %s, %d, %p, 0x%x)\n",
3021 hdc, debugstr_an(lpstr, count), count, pgi, flags);
3023 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
3024 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
3025 HeapFree(GetProcessHeap(), 0, lpstrW);
3030 /*************************************************************************
3031 * GetGlyphIndicesW [GDI32.@]
3033 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
3034 LPWORD pgi, DWORD flags)
3036 DC *dc = get_dc_ptr(hdc);
3040 TRACE("(%p, %s, %d, %p, 0x%x)\n",
3041 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
3043 if(!dc) return GDI_ERROR;
3045 dev = GET_DC_PHYSDEV( dc, pGetGlyphIndices );
3046 ret = dev->funcs->pGetGlyphIndices( dev, lpstr, count, pgi, flags );
3047 release_dc_ptr( dc );
3051 /*************************************************************************
3052 * GetCharacterPlacementA [GDI32.@]
3054 * See GetCharacterPlacementW.
3057 * the web browser control of ie4 calls this with dwFlags=0
3060 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
3061 INT nMaxExtent, GCP_RESULTSA *lpResults,
3066 GCP_RESULTSW resultsW;
3070 TRACE("%s, %d, %d, 0x%08x\n",
3071 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
3073 /* both structs are equal in size */
3074 memcpy(&resultsW, lpResults, sizeof(resultsW));
3076 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
3077 if(lpResults->lpOutString)
3078 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
3080 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
3082 lpResults->nGlyphs = resultsW.nGlyphs;
3083 lpResults->nMaxFit = resultsW.nMaxFit;
3085 if(lpResults->lpOutString) {
3086 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
3087 lpResults->lpOutString, uCount, NULL, NULL );
3090 HeapFree(GetProcessHeap(), 0, lpStringW);
3091 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
3096 /*************************************************************************
3097 * GetCharacterPlacementW [GDI32.@]
3099 * Retrieve information about a string. This includes the width, reordering,
3100 * Glyphing and so on.
3104 * The width and height of the string if successful, 0 if failed.
3108 * All flags except GCP_REORDER are not yet implemented.
3109 * Reordering is not 100% compliant to the Windows BiDi method.
3110 * Caret positioning is not yet implemented for BiDi.
3111 * Classes are not yet implemented.
3115 GetCharacterPlacementW(
3116 HDC hdc, /* [in] Device context for which the rendering is to be done */
3117 LPCWSTR lpString, /* [in] The string for which information is to be returned */
3118 INT uCount, /* [in] Number of WORDS in string. */
3119 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
3120 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
3121 DWORD dwFlags /* [in] Flags specifying how to process the string */
3128 TRACE("%s, %d, %d, 0x%08x\n",
3129 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
3131 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
3132 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
3133 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
3134 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
3135 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
3137 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08x ignored\n", dwFlags);
3138 if(lpResults->lpClass) FIXME("classes not implemented\n");
3139 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
3140 FIXME("Caret positions for complex scripts not implemented\n");
3142 nSet = (UINT)uCount;
3143 if(nSet > lpResults->nGlyphs)
3144 nSet = lpResults->nGlyphs;
3146 /* return number of initialized fields */
3147 lpResults->nGlyphs = nSet;
3149 if((dwFlags&GCP_REORDER)==0 )
3151 /* Treat the case where no special handling was requested in a fastpath way */
3152 /* copy will do if the GCP_REORDER flag is not set */
3153 if(lpResults->lpOutString)
3154 memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
3156 if(lpResults->lpOrder)
3158 for(i = 0; i < nSet; i++)
3159 lpResults->lpOrder[i] = i;
3163 BIDI_Reorder(NULL, lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
3164 nSet, lpResults->lpOrder, NULL, NULL );
3167 /* FIXME: Will use the placement chars */
3168 if (lpResults->lpDx)
3171 for (i = 0; i < nSet; i++)
3173 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
3174 lpResults->lpDx[i]= c;
3178 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
3182 lpResults->lpCaretPos[0] = 0;
3183 for (i = 1; i < nSet; i++)
3184 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
3185 lpResults->lpCaretPos[i] = (pos += size.cx);
3188 if(lpResults->lpGlyphs)
3189 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
3191 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
3192 ret = MAKELONG(size.cx, size.cy);
3197 /*************************************************************************
3198 * GetCharABCWidthsFloatA [GDI32.@]
3200 * See GetCharABCWidthsFloatW.
3202 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3209 str = FONT_GetCharsByRangeA(hdc, first, last, &i);
3213 wstr = FONT_mbtowc( hdc, str, i, &wlen, NULL );
3215 for (i = 0; i < wlen; i++)
3217 if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
3225 HeapFree( GetProcessHeap(), 0, str );
3226 HeapFree( GetProcessHeap(), 0, wstr );
3231 /*************************************************************************
3232 * GetCharABCWidthsFloatW [GDI32.@]
3234 * Retrieves widths of a range of characters.
3237 * hdc [I] Handle to device context.
3238 * first [I] First character in range to query.
3239 * last [I] Last character in range to query.
3240 * abcf [O] Array of LPABCFLOAT structures.
3246 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3252 DC *dc = get_dc_ptr( hdc );
3254 TRACE("%p, %d, %d, %p\n", hdc, first, last, abcf);
3256 if (!dc) return FALSE;
3258 if (!abcf) goto done;
3259 if (!(abc = HeapAlloc( GetProcessHeap(), 0, (last - first + 1) * sizeof(*abc) ))) goto done;
3261 dev = GET_DC_PHYSDEV( dc, pGetCharABCWidths );
3262 ret = dev->funcs->pGetCharABCWidths( dev, first, last, abc );
3265 /* convert device units to logical */
3266 for (i = first; i <= last; i++, abcf++)
3268 abcf->abcfA = abc->abcA * dc->xformVport2World.eM11;
3269 abcf->abcfB = abc->abcB * dc->xformVport2World.eM11;
3270 abcf->abcfC = abc->abcC * dc->xformVport2World.eM11;
3273 HeapFree( GetProcessHeap(), 0, abc );
3276 release_dc_ptr( dc );
3280 /*************************************************************************
3281 * GetCharWidthFloatA [GDI32.@]
3283 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
3284 UINT iLastChar, PFLOAT pxBuffer)
3286 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3290 /*************************************************************************
3291 * GetCharWidthFloatW [GDI32.@]
3293 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
3294 UINT iLastChar, PFLOAT pxBuffer)
3296 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3301 /***********************************************************************
3303 * Font Resource API *
3305 ***********************************************************************/
3307 /***********************************************************************
3308 * AddFontResourceA (GDI32.@)
3310 INT WINAPI AddFontResourceA( LPCSTR str )
3312 return AddFontResourceExA( str, 0, NULL);
3315 /***********************************************************************
3316 * AddFontResourceW (GDI32.@)
3318 INT WINAPI AddFontResourceW( LPCWSTR str )
3320 return AddFontResourceExW(str, 0, NULL);
3324 /***********************************************************************
3325 * AddFontResourceExA (GDI32.@)
3327 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3329 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3330 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3333 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3334 ret = AddFontResourceExW(strW, fl, pdv);
3335 HeapFree(GetProcessHeap(), 0, strW);
3339 static BOOL CALLBACK load_enumed_resource(HMODULE hModule, LPCWSTR type, LPWSTR name, LONG_PTR lParam)
3341 HRSRC rsrc = FindResourceW(hModule, name, type);
3342 HGLOBAL hMem = LoadResource(hModule, rsrc);
3343 LPVOID *pMem = LockResource(hMem);
3344 int *num_total = (int *)lParam;
3347 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type));
3348 if (!AddFontMemResourceEx(pMem, SizeofResource(hModule, rsrc), NULL, &num_in_res))
3350 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule, hMem);
3354 *num_total += num_in_res;
3358 /***********************************************************************
3359 * AddFontResourceExW (GDI32.@)
3361 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3363 int ret = WineEngAddFontResourceEx(str, fl, pdv);
3366 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3367 HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
3368 if (hModule != NULL)
3370 int num_resources = 0;
3371 LPWSTR rt_font = (LPWSTR)((ULONG_PTR)8); /* we don't want to include winuser.h */
3373 TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3374 wine_dbgstr_w(str));
3375 if (EnumResourceNamesW(hModule, rt_font, load_enumed_resource, (LONG_PTR)&num_resources))
3376 ret = num_resources;
3377 FreeLibrary(hModule);
3383 /***********************************************************************
3384 * RemoveFontResourceA (GDI32.@)
3386 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3388 return RemoveFontResourceExA(str, 0, 0);
3391 /***********************************************************************
3392 * RemoveFontResourceW (GDI32.@)
3394 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3396 return RemoveFontResourceExW(str, 0, 0);
3399 /***********************************************************************
3400 * AddFontMemResourceEx (GDI32.@)
3402 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3407 if (!pbFont || !cbFont || !pcFonts)
3409 SetLastError(ERROR_INVALID_PARAMETER);
3413 ret = WineEngAddFontMemResourceEx(pbFont, cbFont, pdv, &num_fonts);
3418 *pcFonts = num_fonts;
3422 WARN("page fault while writing to *pcFonts (%p)\n", pcFonts);
3423 RemoveFontMemResourceEx(ret);
3431 /***********************************************************************
3432 * RemoveFontMemResourceEx (GDI32.@)
3434 BOOL WINAPI RemoveFontMemResourceEx( HANDLE fh )
3436 FIXME("(%p) stub\n", fh);
3440 /***********************************************************************
3441 * RemoveFontResourceExA (GDI32.@)
3443 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3445 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3446 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3449 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3450 ret = RemoveFontResourceExW(strW, fl, pdv);
3451 HeapFree(GetProcessHeap(), 0, strW);
3455 /***********************************************************************
3456 * RemoveFontResourceExW (GDI32.@)
3458 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3460 return WineEngRemoveFontResourceEx(str, fl, pdv);
3463 /***********************************************************************
3464 * GetTextCharset (GDI32.@)
3466 UINT WINAPI GetTextCharset(HDC hdc)
3468 /* MSDN docs say this is equivalent */
3469 return GetTextCharsetInfo(hdc, NULL, 0);
3472 /***********************************************************************
3473 * GetTextCharsetInfo (GDI32.@)
3475 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3477 UINT ret = DEFAULT_CHARSET;
3478 DC *dc = get_dc_ptr(hdc);
3483 dev = GET_DC_PHYSDEV( dc, pGetTextCharsetInfo );
3484 ret = dev->funcs->pGetTextCharsetInfo( dev, fs, flags );
3485 release_dc_ptr( dc );
3488 if (ret == DEFAULT_CHARSET && fs)
3489 memset(fs, 0, sizeof(FONTSIGNATURE));
3493 /***********************************************************************
3494 * GdiGetCharDimensions (GDI32.@)
3496 * Gets the average width of the characters in the English alphabet.
3499 * hdc [I] Handle to the device context to measure on.
3500 * lptm [O] Pointer to memory to store the text metrics into.
3501 * height [O] On exit, the maximum height of characters in the English alphabet.
3504 * The average width of characters in the English alphabet.
3507 * This function is used by the dialog manager to get the size of a dialog
3508 * unit. It should also be used by other pieces of code that need to know
3509 * the size of a dialog unit in logical units without having access to the
3510 * window handle of the dialog.
3511 * Windows caches the font metrics from this function, but we don't and
3512 * there doesn't appear to be an immediate advantage to do so.
3515 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3517 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3520 static const WCHAR alphabet[] = {
3521 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3522 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3523 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3525 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3527 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3529 if (height) *height = sz.cy;
3530 return (sz.cx / 26 + 1) / 2;
3533 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3535 FIXME("(%d): stub\n", fEnableEUDC);
3539 /***********************************************************************
3540 * GetCharWidthI (GDI32.@)
3542 * Retrieve widths of characters.
3545 * hdc [I] Handle to a device context.
3546 * first [I] First glyph in range to query.
3547 * count [I] Number of glyph indices to query.
3548 * glyphs [I] Array of glyphs to query.
3549 * buffer [O] Buffer to receive character widths.
3552 * Only works with TrueType fonts.
3558 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3563 TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3565 if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3568 if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3570 HeapFree(GetProcessHeap(), 0, abc);
3574 for (i = 0; i < count; i++)
3575 buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3577 HeapFree(GetProcessHeap(), 0, abc);
3581 /***********************************************************************
3582 * GetFontUnicodeRanges (GDI32.@)
3584 * Retrieve a list of supported Unicode characters in a font.
3587 * hdc [I] Handle to a device context.
3588 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3591 * Success: Number of bytes written to the buffer pointed to by lpgs.
3595 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3599 DC *dc = get_dc_ptr(hdc);
3601 TRACE("(%p, %p)\n", hdc, lpgs);
3605 dev = GET_DC_PHYSDEV( dc, pGetFontUnicodeRanges );
3606 ret = dev->funcs->pGetFontUnicodeRanges( dev, lpgs );
3612 /*************************************************************
3613 * FontIsLinked (GDI32.@)
3615 BOOL WINAPI FontIsLinked(HDC hdc)
3617 DC *dc = get_dc_ptr(hdc);
3621 if (!dc) return FALSE;
3622 dev = GET_DC_PHYSDEV( dc, pFontIsLinked );
3623 ret = dev->funcs->pFontIsLinked( dev );
3625 TRACE("returning %d\n", ret);
3629 /*************************************************************
3630 * GdiRealizationInfo (GDI32.@)
3632 * Returns a structure that contains some font information.
3634 BOOL WINAPI GdiRealizationInfo(HDC hdc, realization_info_t *info)
3636 DC *dc = get_dc_ptr(hdc);
3640 if (!dc) return FALSE;
3641 dev = GET_DC_PHYSDEV( dc, pGdiRealizationInfo );
3642 ret = dev->funcs->pGdiRealizationInfo( dev, info );