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"
36 #include "gdi_private.h"
37 #include "wine/exception.h"
38 #include "wine/unicode.h"
39 #include "wine/debug.h"
41 #ifdef WORDS_BIGENDIAN
42 #define get_be_word(x) (x)
44 #define get_be_word(x) RtlUshortByteSwap(x)
47 WINE_DEFAULT_DEBUG_CHANNEL(font);
49 /* Device -> World size conversion */
51 /* Performs a device to world transformation on the specified width (which
52 * is in integer format).
54 static inline INT INTERNAL_XDSTOWS(DC *dc, INT width)
58 /* Perform operation with floating point */
59 floatWidth = (double)width * dc->xformVport2World.eM11;
60 /* Round to integers */
61 return GDI_ROUND(floatWidth);
64 /* Performs a device to world transformation on the specified size (which
65 * is in integer format).
67 static inline INT INTERNAL_YDSTOWS(DC *dc, INT height)
71 /* Perform operation with floating point */
72 floatHeight = (double)height * dc->xformVport2World.eM22;
73 /* Round to integers */
74 return GDI_ROUND(floatHeight);
77 static inline INT INTERNAL_XWSTODS(DC *dc, INT width)
80 pt[0].x = pt[0].y = 0;
83 LPtoDP(dc->hSelf, pt, 2);
84 return pt[1].x - pt[0].x;
87 static inline INT INTERNAL_YWSTODS(DC *dc, INT height)
90 pt[0].x = pt[0].y = 0;
93 LPtoDP(dc->hSelf, pt, 2);
94 return pt[1].y - pt[0].y;
97 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc );
98 static INT FONT_GetObjectA( HGDIOBJ handle, INT count, LPVOID buffer );
99 static INT FONT_GetObjectW( HGDIOBJ handle, INT count, LPVOID buffer );
100 static BOOL FONT_DeleteObject( HGDIOBJ handle );
102 static const struct gdi_obj_funcs font_funcs =
104 FONT_SelectObject, /* pSelectObject */
105 FONT_GetObjectA, /* pGetObjectA */
106 FONT_GetObjectW, /* pGetObjectW */
107 NULL, /* pUnrealizeObject */
108 FONT_DeleteObject /* pDeleteObject */
118 LPLOGFONTW lpLogFontParam;
119 FONTENUMPROCW lpEnumFunc;
127 * For TranslateCharsetInfo
129 #define MAXTCIINDEX 32
130 static const CHARSETINFO FONT_tci[MAXTCIINDEX] = {
132 { ANSI_CHARSET, 1252, {{0,0,0,0},{FS_LATIN1,0}} },
133 { EASTEUROPE_CHARSET, 1250, {{0,0,0,0},{FS_LATIN2,0}} },
134 { RUSSIAN_CHARSET, 1251, {{0,0,0,0},{FS_CYRILLIC,0}} },
135 { GREEK_CHARSET, 1253, {{0,0,0,0},{FS_GREEK,0}} },
136 { TURKISH_CHARSET, 1254, {{0,0,0,0},{FS_TURKISH,0}} },
137 { HEBREW_CHARSET, 1255, {{0,0,0,0},{FS_HEBREW,0}} },
138 { ARABIC_CHARSET, 1256, {{0,0,0,0},{FS_ARABIC,0}} },
139 { BALTIC_CHARSET, 1257, {{0,0,0,0},{FS_BALTIC,0}} },
140 { VIETNAMESE_CHARSET, 1258, {{0,0,0,0},{FS_VIETNAMESE,0}} },
141 /* reserved by ANSI */
142 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
143 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
144 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
145 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
146 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
147 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
148 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
150 { THAI_CHARSET, 874, {{0,0,0,0},{FS_THAI,0}} },
151 { SHIFTJIS_CHARSET, 932, {{0,0,0,0},{FS_JISJAPAN,0}} },
152 { GB2312_CHARSET, 936, {{0,0,0,0},{FS_CHINESESIMP,0}} },
153 { HANGEUL_CHARSET, 949, {{0,0,0,0},{FS_WANSUNG,0}} },
154 { CHINESEBIG5_CHARSET, 950, {{0,0,0,0},{FS_CHINESETRAD,0}} },
155 { JOHAB_CHARSET, 1361, {{0,0,0,0},{FS_JOHAB,0}} },
156 /* reserved for alternate ANSI and OEM */
157 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
158 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
159 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
160 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
161 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
162 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
163 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
164 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
165 /* reserved for system */
166 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
167 { SYMBOL_CHARSET, CP_SYMBOL, {{0,0,0,0},{FS_SYMBOL,0}} }
170 static void FONT_LogFontAToW( const LOGFONTA *fontA, LPLOGFONTW fontW )
172 memcpy(fontW, fontA, sizeof(LOGFONTA) - LF_FACESIZE);
173 MultiByteToWideChar(CP_ACP, 0, fontA->lfFaceName, -1, fontW->lfFaceName,
175 fontW->lfFaceName[LF_FACESIZE-1] = 0;
178 static void FONT_LogFontWToA( const LOGFONTW *fontW, LPLOGFONTA fontA )
180 memcpy(fontA, fontW, sizeof(LOGFONTA) - LF_FACESIZE);
181 WideCharToMultiByte(CP_ACP, 0, fontW->lfFaceName, -1, fontA->lfFaceName,
182 LF_FACESIZE, NULL, NULL);
183 fontA->lfFaceName[LF_FACESIZE-1] = 0;
186 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEXA fontA )
188 FONT_LogFontWToA( &fontW->elfLogFont, &fontA->elfLogFont );
190 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
191 (LPSTR) fontA->elfFullName, LF_FULLFACESIZE, NULL, NULL );
192 fontA->elfFullName[LF_FULLFACESIZE-1] = '\0';
193 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
194 (LPSTR) fontA->elfStyle, LF_FACESIZE, NULL, NULL );
195 fontA->elfStyle[LF_FACESIZE-1] = '\0';
196 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
197 (LPSTR) fontA->elfScript, LF_FACESIZE, NULL, NULL );
198 fontA->elfScript[LF_FACESIZE-1] = '\0';
201 static void FONT_EnumLogFontExAToW( const ENUMLOGFONTEXA *fontA, LPENUMLOGFONTEXW fontW )
203 FONT_LogFontAToW( &fontA->elfLogFont, &fontW->elfLogFont );
205 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfFullName, -1,
206 fontW->elfFullName, LF_FULLFACESIZE );
207 fontW->elfFullName[LF_FULLFACESIZE-1] = '\0';
208 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfStyle, -1,
209 fontW->elfStyle, LF_FACESIZE );
210 fontW->elfStyle[LF_FACESIZE-1] = '\0';
211 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfScript, -1,
212 fontW->elfScript, LF_FACESIZE );
213 fontW->elfScript[LF_FACESIZE-1] = '\0';
216 /***********************************************************************
217 * TEXTMETRIC conversion functions.
219 static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
221 ptmA->tmHeight = ptmW->tmHeight;
222 ptmA->tmAscent = ptmW->tmAscent;
223 ptmA->tmDescent = ptmW->tmDescent;
224 ptmA->tmInternalLeading = ptmW->tmInternalLeading;
225 ptmA->tmExternalLeading = ptmW->tmExternalLeading;
226 ptmA->tmAveCharWidth = ptmW->tmAveCharWidth;
227 ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth;
228 ptmA->tmWeight = ptmW->tmWeight;
229 ptmA->tmOverhang = ptmW->tmOverhang;
230 ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX;
231 ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
232 ptmA->tmFirstChar = min(ptmW->tmFirstChar, 255);
233 if (ptmW->tmCharSet == SYMBOL_CHARSET)
235 ptmA->tmFirstChar = 0x1e;
236 ptmA->tmLastChar = 0xff; /* win9x behaviour - we need the OS2 table data to calculate correctly */
238 else if (ptmW->tmPitchAndFamily & TMPF_TRUETYPE)
240 ptmA->tmFirstChar = ptmW->tmDefaultChar - 1;
241 ptmA->tmLastChar = min(ptmW->tmLastChar, 0xff);
245 ptmA->tmFirstChar = min(ptmW->tmFirstChar, 0xff);
246 ptmA->tmLastChar = min(ptmW->tmLastChar, 0xff);
248 ptmA->tmDefaultChar = ptmW->tmDefaultChar;
249 ptmA->tmBreakChar = ptmW->tmBreakChar;
250 ptmA->tmItalic = ptmW->tmItalic;
251 ptmA->tmUnderlined = ptmW->tmUnderlined;
252 ptmA->tmStruckOut = ptmW->tmStruckOut;
253 ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
254 ptmA->tmCharSet = ptmW->tmCharSet;
258 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW *ptmW, NEWTEXTMETRICEXA *ptmA )
260 FONT_TextMetricWToA((const TEXTMETRICW *)ptmW, (LPTEXTMETRICA)ptmA);
261 ptmA->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
262 ptmA->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
263 ptmA->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
264 ptmA->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
265 memcpy(&ptmA->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
268 static DWORD get_font_ppem( HDC hdc )
272 DC *dc = get_dc_ptr( hdc );
274 if (!dc) return GDI_ERROR;
276 GetTextMetricsW( hdc, &tm );
277 ppem = abs( INTERNAL_YWSTODS( dc, tm.tmAscent + tm.tmDescent - tm.tmInternalLeading ) );
278 release_dc_ptr( dc );
282 #define GASP_GRIDFIT 0x01
283 #define GASP_DOGRAY 0x02
285 static BOOL get_gasp_flags( HDC hdc, WORD *flags )
287 DWORD size, gasp_tag = 0x70736167;
288 WORD buf[16]; /* Enough for seven ranges before we need to alloc */
289 WORD *alloced = NULL, *ptr = buf;
290 WORD num_recs, version;
291 DWORD ppem = get_font_ppem( hdc );
295 if (ppem == GDI_ERROR) return FALSE;
297 size = GetFontData( hdc, gasp_tag, 0, NULL, 0 );
298 if (size == GDI_ERROR) return FALSE;
299 if (size < 4 * sizeof(WORD)) return FALSE;
300 if (size > sizeof(buf))
302 ptr = alloced = HeapAlloc( GetProcessHeap(), 0, size );
303 if (!ptr) return FALSE;
306 GetFontData( hdc, gasp_tag, 0, ptr, size );
308 version = get_be_word( *ptr++ );
309 num_recs = get_be_word( *ptr++ );
311 if (version > 1 || size < (num_recs * 2 + 2) * sizeof(WORD))
313 FIXME( "Unsupported gasp table: ver %d size %d recs %d\n", version, size, num_recs );
319 *flags = get_be_word( *(ptr + 1) );
320 if (ppem <= get_be_word( *ptr )) break;
323 TRACE( "got flags %04x for ppem %d\n", *flags, ppem );
327 HeapFree( GetProcessHeap(), 0, alloced );
331 UINT get_font_aa_flags( HDC hdc )
336 if (GetObjectType( hdc ) == OBJ_MEMDC)
339 GetObjectW( GetCurrentObject( hdc, OBJ_BITMAP ), sizeof(bm), &bm );
340 if (bm.bmBitsPixel <= 8) return GGO_BITMAP;
342 else if (GetDeviceCaps( hdc, BITSPIXEL ) <= 8) return GGO_BITMAP;
344 GetObjectW( GetCurrentObject( hdc, OBJ_FONT ), sizeof(lf), &lf );
345 if (lf.lfQuality == NONANTIALIASED_QUALITY) return GGO_BITMAP;
347 if (get_gasp_flags( hdc, &gasp_flags ) && !(gasp_flags & GASP_DOGRAY))
350 /* FIXME, check user prefs */
351 return GGO_GRAY4_BITMAP;
354 /***********************************************************************
355 * GdiGetCodePage (GDI32.@)
357 DWORD WINAPI GdiGetCodePage( HDC hdc )
360 DC *dc = get_dc_ptr( hdc );
364 cp = dc->font_code_page;
365 release_dc_ptr( dc );
370 /***********************************************************************
373 * Returns a Unicode translation of str using the charset of the
374 * currently selected font in hdc. If count is -1 then str is assumed
375 * to be '\0' terminated, otherwise it contains the number of bytes to
376 * convert. If plenW is non-NULL, on return it will point to the
377 * number of WCHARs that have been written. If pCP is non-NULL, on
378 * return it will point to the codepage used in the conversion. The
379 * caller should free the returned LPWSTR from the process heap
382 static LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
388 cp = GdiGetCodePage( hdc );
390 if(count == -1) count = strlen(str);
391 lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
392 strW = HeapAlloc(GetProcessHeap(), 0, lenW*sizeof(WCHAR));
393 MultiByteToWideChar(cp, 0, str, count, strW, lenW);
394 TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW));
395 if(plenW) *plenW = lenW;
400 /***********************************************************************
401 * CreateFontIndirectExA (GDI32.@)
403 HFONT WINAPI CreateFontIndirectExA( const ENUMLOGFONTEXDVA *penumexA )
405 ENUMLOGFONTEXDVW enumexW;
407 if (!penumexA) return 0;
409 FONT_EnumLogFontExAToW( &penumexA->elfEnumLogfontEx, &enumexW.elfEnumLogfontEx );
410 enumexW.elfDesignVector = penumexA->elfDesignVector;
411 return CreateFontIndirectExW( &enumexW );
414 /***********************************************************************
415 * CreateFontIndirectExW (GDI32.@)
417 HFONT WINAPI CreateFontIndirectExW( const ENUMLOGFONTEXDVW *penumex )
423 if (!penumex) return 0;
425 if (penumex->elfEnumLogfontEx.elfFullName[0] ||
426 penumex->elfEnumLogfontEx.elfStyle[0] ||
427 penumex->elfEnumLogfontEx.elfScript[0])
429 FIXME("some fields ignored. fullname=%s, style=%s, script=%s\n",
430 debugstr_w(penumex->elfEnumLogfontEx.elfFullName),
431 debugstr_w(penumex->elfEnumLogfontEx.elfStyle),
432 debugstr_w(penumex->elfEnumLogfontEx.elfScript));
435 plf = &penumex->elfEnumLogfontEx.elfLogFont;
436 if (!(fontPtr = HeapAlloc( GetProcessHeap(), 0, sizeof(*fontPtr) ))) return 0;
438 fontPtr->logfont = *plf;
440 if (plf->lfEscapement != plf->lfOrientation)
442 /* this should really depend on whether GM_ADVANCED is set */
443 fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
444 WARN("orientation angle %f set to "
445 "escapement angle %f for new font %p\n",
446 plf->lfOrientation/10., plf->lfEscapement/10., fontPtr);
449 if (!(hFont = alloc_gdi_handle( fontPtr, OBJ_FONT, &font_funcs )))
451 HeapFree( GetProcessHeap(), 0, fontPtr );
455 TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
456 plf->lfHeight, plf->lfWidth,
457 plf->lfEscapement, plf->lfOrientation,
458 plf->lfPitchAndFamily,
459 plf->lfOutPrecision, plf->lfClipPrecision,
460 plf->lfQuality, plf->lfCharSet,
461 debugstr_w(plf->lfFaceName),
462 plf->lfWeight > 400 ? "Bold" : "",
463 plf->lfItalic ? "Italic" : "",
464 plf->lfUnderline ? "Underline" : "", hFont);
469 /***********************************************************************
470 * CreateFontIndirectA (GDI32.@)
472 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *plfA )
478 FONT_LogFontAToW( plfA, &lfW );
479 return CreateFontIndirectW( &lfW );
482 /***********************************************************************
483 * CreateFontIndirectW (GDI32.@)
485 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
487 ENUMLOGFONTEXDVW exdv;
491 exdv.elfEnumLogfontEx.elfLogFont = *plf;
492 exdv.elfEnumLogfontEx.elfFullName[0] = 0;
493 exdv.elfEnumLogfontEx.elfStyle[0] = 0;
494 exdv.elfEnumLogfontEx.elfScript[0] = 0;
495 return CreateFontIndirectExW( &exdv );
498 /*************************************************************************
499 * CreateFontA (GDI32.@)
501 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
502 INT orient, INT weight, DWORD italic,
503 DWORD underline, DWORD strikeout, DWORD charset,
504 DWORD outpres, DWORD clippres, DWORD quality,
505 DWORD pitch, LPCSTR name )
509 logfont.lfHeight = height;
510 logfont.lfWidth = width;
511 logfont.lfEscapement = esc;
512 logfont.lfOrientation = orient;
513 logfont.lfWeight = weight;
514 logfont.lfItalic = italic;
515 logfont.lfUnderline = underline;
516 logfont.lfStrikeOut = strikeout;
517 logfont.lfCharSet = charset;
518 logfont.lfOutPrecision = outpres;
519 logfont.lfClipPrecision = clippres;
520 logfont.lfQuality = quality;
521 logfont.lfPitchAndFamily = pitch;
524 lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
526 logfont.lfFaceName[0] = '\0';
528 return CreateFontIndirectA( &logfont );
531 /*************************************************************************
532 * CreateFontW (GDI32.@)
534 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
535 INT orient, INT weight, DWORD italic,
536 DWORD underline, DWORD strikeout, DWORD charset,
537 DWORD outpres, DWORD clippres, DWORD quality,
538 DWORD pitch, LPCWSTR name )
542 logfont.lfHeight = height;
543 logfont.lfWidth = width;
544 logfont.lfEscapement = esc;
545 logfont.lfOrientation = orient;
546 logfont.lfWeight = weight;
547 logfont.lfItalic = italic;
548 logfont.lfUnderline = underline;
549 logfont.lfStrikeOut = strikeout;
550 logfont.lfCharSet = charset;
551 logfont.lfOutPrecision = outpres;
552 logfont.lfClipPrecision = clippres;
553 logfont.lfQuality = quality;
554 logfont.lfPitchAndFamily = pitch;
557 lstrcpynW(logfont.lfFaceName, name,
558 sizeof(logfont.lfFaceName) / sizeof(WCHAR));
560 logfont.lfFaceName[0] = '\0';
562 return CreateFontIndirectW( &logfont );
565 static void update_font_code_page( DC *dc )
568 int charset = GetTextCharsetInfo( dc->hSelf, NULL, 0 );
570 /* Hmm, nicely designed api this one! */
571 if (TranslateCharsetInfo( ULongToPtr(charset), &csi, TCI_SRCCHARSET) )
572 dc->font_code_page = csi.ciACP;
576 dc->font_code_page = GetOEMCP();
578 case DEFAULT_CHARSET:
579 dc->font_code_page = GetACP();
589 /* FIXME: These have no place here, but because x11drv
590 enumerates fonts with these (made up) charsets some apps
591 might use them and then the FIXME below would become
592 annoying. Now we could pick the intended codepage for
593 each of these, but since it's broken anyway we'll just
594 use CP_ACP and hope it'll go away...
596 dc->font_code_page = CP_ACP;
600 FIXME("Can't find codepage for charset %d\n", charset);
601 dc->font_code_page = CP_ACP;
606 TRACE("charset %d => cp %d\n", charset, dc->font_code_page);
609 /***********************************************************************
612 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc )
615 DC *dc = get_dc_ptr( hdc );
620 if (!GDI_inc_ref_count( handle ))
622 release_dc_ptr( dc );
626 physdev = GET_DC_PHYSDEV( dc, pSelectFont );
627 if (physdev->funcs->pSelectFont( physdev, handle ))
631 update_font_code_page( dc );
632 GDI_dec_ref_count( ret );
634 else GDI_dec_ref_count( handle );
636 release_dc_ptr( dc );
641 /***********************************************************************
644 static INT FONT_GetObjectA( HGDIOBJ handle, INT count, LPVOID buffer )
646 FONTOBJ *font = GDI_GetObjPtr( handle, OBJ_FONT );
652 FONT_LogFontWToA( &font->logfont, &lfA );
653 if (count > sizeof(lfA)) count = sizeof(lfA);
654 memcpy( buffer, &lfA, count );
656 else count = sizeof(lfA);
657 GDI_ReleaseObj( handle );
661 /***********************************************************************
664 static INT FONT_GetObjectW( HGDIOBJ handle, INT count, LPVOID buffer )
666 FONTOBJ *font = GDI_GetObjPtr( handle, OBJ_FONT );
671 if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
672 memcpy( buffer, &font->logfont, count );
674 else count = sizeof(LOGFONTW);
675 GDI_ReleaseObj( handle );
680 /***********************************************************************
683 static BOOL FONT_DeleteObject( HGDIOBJ handle )
687 WineEngDestroyFontInstance( handle );
689 if (!(obj = free_gdi_handle( handle ))) return FALSE;
690 return HeapFree( GetProcessHeap(), 0, obj );
694 /***********************************************************************
697 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
698 * We have to use other types because of the FONTENUMPROCW definition.
700 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
701 DWORD fType, LPARAM lp )
703 struct font_enum *pfe = (struct font_enum *)lp;
706 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
707 if ((!pfe->lpLogFontParam ||
708 pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
709 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
710 (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
712 /* convert font metrics */
713 ENUMLOGFONTEXA logfont;
714 NEWTEXTMETRICEXA tmA;
718 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
719 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
720 plf = (LOGFONTW *)&logfont.elfLogFont;
721 ptm = (TEXTMETRICW *)&tmA;
723 ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
729 /***********************************************************************
730 * FONT_EnumFontFamiliesEx
732 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf, FONTENUMPROCW efproc,
733 LPARAM lParam, BOOL unicode )
736 DC *dc = get_dc_ptr( hDC );
741 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pEnumFonts );
743 if (plf) TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName), plf->lfCharSet);
744 fe.lpLogFontParam = plf;
745 fe.lpEnumFunc = efproc;
747 fe.unicode = unicode;
750 ret = physdev->funcs->pEnumFonts( physdev, plf, FONT_EnumInstance, (LPARAM)&fe );
751 release_dc_ptr( dc );
753 return ret ? fe.retval : 0;
756 /***********************************************************************
757 * EnumFontFamiliesExW (GDI32.@)
759 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
760 FONTENUMPROCW efproc,
761 LPARAM lParam, DWORD dwFlags )
763 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, TRUE );
766 /***********************************************************************
767 * EnumFontFamiliesExA (GDI32.@)
769 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
770 FONTENUMPROCA efproc,
771 LPARAM lParam, DWORD dwFlags)
777 FONT_LogFontAToW( plf, &lfW );
782 return FONT_EnumFontFamiliesEx( hDC, plfW, (FONTENUMPROCW)efproc, lParam, FALSE );
785 /***********************************************************************
786 * EnumFontFamiliesA (GDI32.@)
788 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
789 FONTENUMPROCA efproc, LPARAM lpData )
795 if (!*lpFamily) return 1;
796 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
797 lf.lfCharSet = DEFAULT_CHARSET;
798 lf.lfPitchAndFamily = 0;
803 return EnumFontFamiliesExA( hDC, plf, efproc, lpData, 0 );
806 /***********************************************************************
807 * EnumFontFamiliesW (GDI32.@)
809 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
810 FONTENUMPROCW efproc, LPARAM lpData )
816 if (!*lpFamily) return 1;
817 lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
818 lf.lfCharSet = DEFAULT_CHARSET;
819 lf.lfPitchAndFamily = 0;
824 return EnumFontFamiliesExW( hDC, plf, efproc, lpData, 0 );
827 /***********************************************************************
828 * EnumFontsA (GDI32.@)
830 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
833 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
836 /***********************************************************************
837 * EnumFontsW (GDI32.@)
839 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
842 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
846 /***********************************************************************
847 * GetTextCharacterExtra (GDI32.@)
849 INT WINAPI GetTextCharacterExtra( HDC hdc )
852 DC *dc = get_dc_ptr( hdc );
853 if (!dc) return 0x80000000;
855 release_dc_ptr( dc );
860 /***********************************************************************
861 * SetTextCharacterExtra (GDI32.@)
863 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
865 INT ret = 0x80000000;
866 DC * dc = get_dc_ptr( hdc );
870 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetTextCharacterExtra );
871 extra = physdev->funcs->pSetTextCharacterExtra( physdev, extra );
872 if (extra != 0x80000000)
875 dc->charExtra = extra;
877 release_dc_ptr( dc );
883 /***********************************************************************
884 * SetTextJustification (GDI32.@)
886 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
890 DC * dc = get_dc_ptr( hdc );
892 if (!dc) return FALSE;
894 physdev = GET_DC_PHYSDEV( dc, pSetTextJustification );
895 ret = physdev->funcs->pSetTextJustification( physdev, extra, breaks );
898 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
899 if (!extra) breaks = 0;
902 dc->breakExtra = extra / breaks;
903 dc->breakRem = extra - (breaks * dc->breakExtra);
911 release_dc_ptr( dc );
916 /***********************************************************************
917 * GetTextFaceA (GDI32.@)
919 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
921 INT res = GetTextFaceW(hdc, 0, NULL);
922 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
923 GetTextFaceW( hdc, res, nameW );
929 res = WideCharToMultiByte(CP_ACP, 0, nameW, -1, name, count, NULL, NULL);
933 /* GetTextFaceA does NOT include the nul byte in the return count. */
940 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
941 HeapFree( GetProcessHeap(), 0, nameW );
945 /***********************************************************************
946 * GetTextFaceW (GDI32.@)
948 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
953 DC * dc = get_dc_ptr( hdc );
956 dev = GET_DC_PHYSDEV( dc, pGetTextFace );
957 ret = dev->funcs->pGetTextFace( dev, count, name );
958 release_dc_ptr( dc );
963 /***********************************************************************
964 * GetTextExtentPoint32A (GDI32.@)
966 * See GetTextExtentPoint32W.
968 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
975 if (count < 0) return FALSE;
977 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
981 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
982 HeapFree( GetProcessHeap(), 0, p );
985 TRACE("(%p %s %d %p): returning %d x %d\n",
986 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
991 /***********************************************************************
992 * GetTextExtentPoint32W [GDI32.@]
994 * Computes width/height for a string.
996 * Computes width and height of the specified string.
1002 BOOL WINAPI GetTextExtentPoint32W(
1003 HDC hdc, /* [in] Handle of device context */
1004 LPCWSTR str, /* [in] Address of text string */
1005 INT count, /* [in] Number of characters in string */
1006 LPSIZE size) /* [out] Address of structure for string size */
1008 return GetTextExtentExPointW(hdc, str, count, 0, NULL, NULL, size);
1011 /***********************************************************************
1012 * GetTextExtentExPointI [GDI32.@]
1014 * Computes width and height of the array of glyph indices.
1017 * hdc [I] Handle of device context.
1018 * indices [I] Glyph index array.
1019 * count [I] Number of glyphs in array.
1020 * max_ext [I] Maximum width in glyphs.
1021 * nfit [O] Maximum number of characters.
1022 * dxs [O] Partial string widths.
1023 * size [O] Returned string size.
1029 BOOL WINAPI GetTextExtentExPointI( HDC hdc, const WORD *indices, INT count, INT max_ext,
1030 LPINT nfit, LPINT dxs, LPSIZE size )
1036 if (count < 0) return FALSE;
1038 dc = get_dc_ptr( hdc );
1039 if (!dc) return FALSE;
1041 dev = GET_DC_PHYSDEV( dc, pGetTextExtentExPointI );
1042 ret = dev->funcs->pGetTextExtentExPointI( dev, indices, count, max_ext, nfit, dxs, size );
1043 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1044 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1045 size->cx += count * dc->charExtra;
1046 release_dc_ptr( dc );
1048 TRACE("(%p %p %d %p): returning %d x %d\n",
1049 hdc, indices, count, size, size->cx, size->cy );
1053 /***********************************************************************
1054 * GetTextExtentPointI [GDI32.@]
1056 * Computes width and height of the array of glyph indices.
1059 * hdc [I] Handle of device context.
1060 * indices [I] Glyph index array.
1061 * count [I] Number of glyphs in array.
1062 * size [O] Returned string size.
1068 BOOL WINAPI GetTextExtentPointI( HDC hdc, const WORD *indices, INT count, LPSIZE size )
1070 return GetTextExtentExPointI( hdc, indices, count, 0, NULL, NULL, size );
1074 /***********************************************************************
1075 * GetTextExtentPointA (GDI32.@)
1077 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
1080 TRACE("not bug compatible.\n");
1081 return GetTextExtentPoint32A( hdc, str, count, size );
1084 /***********************************************************************
1085 * GetTextExtentPointW (GDI32.@)
1087 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1090 TRACE("not bug compatible.\n");
1091 return GetTextExtentPoint32W( hdc, str, count, size );
1095 /***********************************************************************
1096 * GetTextExtentExPointA (GDI32.@)
1098 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1099 INT maxExt, LPINT lpnFit,
1100 LPINT alpDx, LPSIZE size )
1107 if (count < 0) return FALSE;
1111 walpDx = HeapAlloc( GetProcessHeap(), 0, count * sizeof(INT) );
1112 if (!walpDx) return FALSE;
1115 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1116 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
1119 INT n = lpnFit ? *lpnFit : wlen;
1121 for(i = 0, j = 0; i < n; i++, j++)
1123 alpDx[j] = walpDx[i];
1124 if (IsDBCSLeadByte(str[j])) alpDx[++j] = walpDx[i];
1127 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1128 HeapFree( GetProcessHeap(), 0, p );
1129 HeapFree( GetProcessHeap(), 0, walpDx );
1134 /***********************************************************************
1135 * GetTextExtentExPointW (GDI32.@)
1137 * Return the size of the string as it would be if it was output properly by
1140 * This should include
1141 * - Intercharacter spacing
1142 * - justification spacing (not yet done)
1143 * - kerning? see below
1145 * Kerning. Since kerning would be carried out by the rendering code it should
1146 * be done by the driver. However they don't support it yet. Also I am not
1147 * yet persuaded that (certainly under Win95) any kerning is actually done.
1149 * str: According to MSDN this should be null-terminated. That is not true; a
1150 * null will not terminate it early.
1151 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1152 * than count. I have seen it be either the size of the full string or
1153 * 1 less than the size of the full string. I have not seen it bear any
1154 * resemblance to the portion that would fit.
1155 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1156 * trailing intercharacter spacing and any trailing justification.
1159 * Currently we do this by measuring each character etc. We should do it by
1160 * passing the request to the driver, perhaps by extending the
1161 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1162 * thinking about kerning issues and rounding issues in the justification.
1165 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1166 INT maxExt, LPINT lpnFit,
1167 LPINT alpDx, LPSIZE size )
1176 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1178 if (count < 0) return FALSE;
1180 dc = get_dc_ptr(hdc);
1181 if (!dc) return FALSE;
1183 GetTextMetricsW(hdc, &tm);
1185 /* If we need to calculate nFit, then we need the partial extents even if
1186 the user hasn't provided us with an array. */
1189 dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]);
1193 SetLastError(ERROR_OUTOFMEMORY);
1200 dev = GET_DC_PHYSDEV( dc, pGetTextExtentExPoint );
1201 ret = dev->funcs->pGetTextExtentExPoint(dev, str, count, 0, NULL, dxs, size);
1203 /* Perform device size to world size transformations. */
1206 INT extra = dc->charExtra,
1207 breakExtra = dc->breakExtra,
1208 breakRem = dc->breakRem,
1213 for (i = 0; i < count; ++i)
1215 dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
1216 dxs[i] += (i+1) * extra;
1217 if (count > 1 && (breakExtra || breakRem) && str[i] == tm.tmBreakChar)
1219 dxs[i] += breakExtra;
1226 if (dxs[i] <= maxExt)
1229 breakRem = dc->breakRem;
1231 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1232 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1234 if (!dxs && count > 1 && (breakExtra || breakRem))
1236 for (i = 0; i < count; i++)
1238 if (str[i] == tm.tmBreakChar)
1240 size->cx += breakExtra;
1255 HeapFree(GetProcessHeap(), 0, dxs);
1257 release_dc_ptr( dc );
1259 TRACE("returning %d %d x %d\n",nFit,size->cx,size->cy);
1263 /***********************************************************************
1264 * GetTextMetricsA (GDI32.@)
1266 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1270 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1271 FONT_TextMetricWToA( &tm32, metrics );
1275 /***********************************************************************
1276 * GetTextMetricsW (GDI32.@)
1278 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1282 DC * dc = get_dc_ptr( hdc );
1283 if (!dc) return FALSE;
1285 physdev = GET_DC_PHYSDEV( dc, pGetTextMetrics );
1286 ret = physdev->funcs->pGetTextMetrics( physdev, metrics );
1290 /* device layer returns values in device units
1291 * therefore we have to convert them to logical */
1293 metrics->tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1294 metrics->tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1296 #define WDPTOLP(x) ((x<0)? \
1297 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1298 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1299 #define HDPTOLP(y) ((y<0)? \
1300 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1301 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1303 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1304 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1305 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1306 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1307 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1308 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1309 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1310 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1314 TRACE("text metrics:\n"
1315 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1316 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1317 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1318 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1319 " PitchAndFamily = %02x\n"
1320 " --------------------\n"
1321 " InternalLeading = %i\n"
1325 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1326 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1327 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1328 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1329 metrics->tmPitchAndFamily,
1330 metrics->tmInternalLeading,
1333 metrics->tmHeight );
1335 release_dc_ptr( dc );
1340 /***********************************************************************
1341 * GetOutlineTextMetricsA (GDI32.@)
1342 * Gets metrics for TrueType fonts.
1345 * If the supplied buffer isn't big enough Windows partially fills it up to
1346 * its given length and returns that length.
1349 * Success: Non-zero or size of required buffer
1352 UINT WINAPI GetOutlineTextMetricsA(
1353 HDC hdc, /* [in] Handle of device context */
1354 UINT cbData, /* [in] Size of metric data array */
1355 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1357 char buf[512], *ptr;
1359 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1360 OUTLINETEXTMETRICA *output = lpOTM;
1363 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1365 if(ret > sizeof(buf))
1366 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1367 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1369 needed = sizeof(OUTLINETEXTMETRICA);
1370 if(lpOTMW->otmpFamilyName)
1371 needed += WideCharToMultiByte(CP_ACP, 0,
1372 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1373 NULL, 0, NULL, NULL);
1374 if(lpOTMW->otmpFaceName)
1375 needed += WideCharToMultiByte(CP_ACP, 0,
1376 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1377 NULL, 0, NULL, NULL);
1378 if(lpOTMW->otmpStyleName)
1379 needed += WideCharToMultiByte(CP_ACP, 0,
1380 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1381 NULL, 0, NULL, NULL);
1382 if(lpOTMW->otmpFullName)
1383 needed += WideCharToMultiByte(CP_ACP, 0,
1384 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1385 NULL, 0, NULL, NULL);
1392 TRACE("needed = %d\n", needed);
1394 /* Since the supplied buffer isn't big enough, we'll alloc one
1395 that is and memcpy the first cbData bytes into the lpOTM at
1397 output = HeapAlloc(GetProcessHeap(), 0, needed);
1399 ret = output->otmSize = min(needed, cbData);
1400 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1401 output->otmFiller = 0;
1402 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1403 output->otmfsSelection = lpOTMW->otmfsSelection;
1404 output->otmfsType = lpOTMW->otmfsType;
1405 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1406 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1407 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1408 output->otmEMSquare = lpOTMW->otmEMSquare;
1409 output->otmAscent = lpOTMW->otmAscent;
1410 output->otmDescent = lpOTMW->otmDescent;
1411 output->otmLineGap = lpOTMW->otmLineGap;
1412 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1413 output->otmsXHeight = lpOTMW->otmsXHeight;
1414 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1415 output->otmMacAscent = lpOTMW->otmMacAscent;
1416 output->otmMacDescent = lpOTMW->otmMacDescent;
1417 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1418 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1419 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1420 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1421 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1422 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1423 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1424 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1425 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1426 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1429 ptr = (char*)(output + 1);
1430 left = needed - sizeof(*output);
1432 if(lpOTMW->otmpFamilyName) {
1433 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1434 len = WideCharToMultiByte(CP_ACP, 0,
1435 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1436 ptr, left, NULL, NULL);
1440 output->otmpFamilyName = 0;
1442 if(lpOTMW->otmpFaceName) {
1443 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1444 len = WideCharToMultiByte(CP_ACP, 0,
1445 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1446 ptr, left, NULL, NULL);
1450 output->otmpFaceName = 0;
1452 if(lpOTMW->otmpStyleName) {
1453 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1454 len = WideCharToMultiByte(CP_ACP, 0,
1455 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1456 ptr, left, NULL, NULL);
1460 output->otmpStyleName = 0;
1462 if(lpOTMW->otmpFullName) {
1463 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1464 len = WideCharToMultiByte(CP_ACP, 0,
1465 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1466 ptr, left, NULL, NULL);
1469 output->otmpFullName = 0;
1473 if(output != lpOTM) {
1474 memcpy(lpOTM, output, cbData);
1475 HeapFree(GetProcessHeap(), 0, output);
1477 /* check if the string offsets really fit into the provided size */
1478 /* FIXME: should we check string length as well? */
1479 /* make sure that we don't read/write beyond the provided buffer */
1480 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(LPSTR))
1482 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1483 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1486 /* make sure that we don't read/write beyond the provided buffer */
1487 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(LPSTR))
1489 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1490 lpOTM->otmpFaceName = 0; /* doesn't fit */
1493 /* make sure that we don't read/write beyond the provided buffer */
1494 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(LPSTR))
1496 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1497 lpOTM->otmpStyleName = 0; /* doesn't fit */
1500 /* make sure that we don't read/write beyond the provided buffer */
1501 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(LPSTR))
1503 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1504 lpOTM->otmpFullName = 0; /* doesn't fit */
1509 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1510 HeapFree(GetProcessHeap(), 0, lpOTMW);
1516 /***********************************************************************
1517 * GetOutlineTextMetricsW [GDI32.@]
1519 UINT WINAPI GetOutlineTextMetricsW(
1520 HDC hdc, /* [in] Handle of device context */
1521 UINT cbData, /* [in] Size of metric data array */
1522 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1524 DC *dc = get_dc_ptr( hdc );
1525 OUTLINETEXTMETRICW *output = lpOTM;
1529 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1532 dev = GET_DC_PHYSDEV( dc, pGetOutlineTextMetrics );
1533 ret = dev->funcs->pGetOutlineTextMetrics( dev, cbData, output );
1535 if (lpOTM && ret > cbData)
1537 output = HeapAlloc(GetProcessHeap(), 0, ret);
1538 ret = dev->funcs->pGetOutlineTextMetrics( dev, ret, output );
1543 output->otmTextMetrics.tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1544 output->otmTextMetrics.tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1546 #define WDPTOLP(x) ((x<0)? \
1547 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1548 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1549 #define HDPTOLP(y) ((y<0)? \
1550 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1551 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1553 output->otmTextMetrics.tmHeight = HDPTOLP(output->otmTextMetrics.tmHeight);
1554 output->otmTextMetrics.tmAscent = HDPTOLP(output->otmTextMetrics.tmAscent);
1555 output->otmTextMetrics.tmDescent = HDPTOLP(output->otmTextMetrics.tmDescent);
1556 output->otmTextMetrics.tmInternalLeading = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1557 output->otmTextMetrics.tmExternalLeading = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1558 output->otmTextMetrics.tmAveCharWidth = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1559 output->otmTextMetrics.tmMaxCharWidth = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1560 output->otmTextMetrics.tmOverhang = WDPTOLP(output->otmTextMetrics.tmOverhang);
1561 output->otmAscent = HDPTOLP(output->otmAscent);
1562 output->otmDescent = HDPTOLP(output->otmDescent);
1563 output->otmLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmLineGap));
1564 output->otmsCapEmHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsCapEmHeight));
1565 output->otmsXHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsXHeight));
1566 output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1567 output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1568 output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1569 output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1570 output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1571 output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1572 output->otmMacLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmMacLineGap));
1573 output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1574 output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1575 output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1576 output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1577 output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1578 output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1579 output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1580 output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1581 output->otmsStrikeoutSize = abs(INTERNAL_YDSTOWS(dc,output->otmsStrikeoutSize));
1582 output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1583 output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1584 output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1589 memcpy(lpOTM, output, cbData);
1590 HeapFree(GetProcessHeap(), 0, output);
1598 static LPSTR FONT_GetCharsByRangeA(HDC hdc, UINT firstChar, UINT lastChar, PINT pByteLen)
1600 INT i, count = lastChar - firstChar + 1;
1608 mbcp = GdiGetCodePage(hdc);
1616 if (lastChar > 0xffff)
1618 if ((firstChar ^ lastChar) > 0xff)
1622 if (lastChar > 0xff)
1628 str = HeapAlloc(GetProcessHeap(), 0, count * 2 + 1);
1632 for(i = 0, c = firstChar; c <= lastChar; i++, c++)
1636 str[i++] = (BYTE)(c >> 8);
1637 if (c <= 0xff && IsDBCSLeadByteEx(mbcp, c))
1638 str[i] = 0x1f; /* FIXME: use default character */
1652 /***********************************************************************
1653 * GetCharWidthW (GDI32.@)
1654 * GetCharWidth32W (GDI32.@)
1656 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1662 DC * dc = get_dc_ptr( hdc );
1664 if (!dc) return FALSE;
1666 dev = GET_DC_PHYSDEV( dc, pGetCharWidth );
1667 ret = dev->funcs->pGetCharWidth( dev, firstChar, lastChar, buffer );
1671 /* convert device units to logical */
1672 for( i = firstChar; i <= lastChar; i++, buffer++ )
1673 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1675 release_dc_ptr( dc );
1680 /***********************************************************************
1681 * GetCharWidthA (GDI32.@)
1682 * GetCharWidth32A (GDI32.@)
1684 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1692 str = FONT_GetCharsByRangeA(hdc, firstChar, lastChar, &i);
1696 wstr = FONT_mbtowc(hdc, str, i, &wlen, NULL);
1698 for(i = 0; i < wlen; i++)
1700 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1708 HeapFree(GetProcessHeap(), 0, str);
1709 HeapFree(GetProcessHeap(), 0, wstr);
1715 /* helper for nulldrv_ExtTextOut */
1716 static DWORD get_glyph_bitmap( HDC hdc, UINT index, UINT aa_flags,
1717 GLYPHMETRICS *metrics, struct gdi_image_bits *image )
1719 UINT ggo_flags = aa_flags | GGO_GLYPH_INDEX;
1720 static const MAT2 identity = { {0,1}, {0,0}, {0,0}, {0,1} };
1721 UINT indices[3] = {0, 0, 0x20};
1728 for (i = 0; i < sizeof(indices) / sizeof(indices[0]); i++)
1731 ret = GetGlyphOutlineW( hdc, index, ggo_flags, metrics, 0, NULL, &identity );
1732 if (ret != GDI_ERROR) break;
1735 if (ret == GDI_ERROR) return ERROR_NOT_FOUND;
1736 if (!image) return ERROR_SUCCESS;
1740 if (!ret) return ERROR_SUCCESS; /* empty glyph */
1742 stride = get_dib_stride( metrics->gmBlackBoxX, 1 );
1743 size = metrics->gmBlackBoxY * stride;
1745 if (!(image->ptr = HeapAlloc( GetProcessHeap(), 0, size ))) return ERROR_OUTOFMEMORY;
1746 image->is_copy = TRUE;
1747 image->free = free_heap_bits;
1749 ret = GetGlyphOutlineW( hdc, index, ggo_flags, metrics, size, image->ptr, &identity );
1750 if (ret == GDI_ERROR)
1752 HeapFree( GetProcessHeap(), 0, image->ptr );
1753 return ERROR_NOT_FOUND;
1755 return ERROR_SUCCESS;
1758 /* helper for nulldrv_ExtTextOut */
1759 static RECT get_total_extents( HDC hdc, INT x, INT y, UINT flags, UINT aa_flags,
1760 LPCWSTR str, UINT count, const INT *dx )
1765 reset_bounds( &bounds );
1766 for (i = 0; i < count; i++)
1768 GLYPHMETRICS metrics;
1770 if (get_glyph_bitmap( hdc, (UINT)str[i], aa_flags, &metrics, NULL )) continue;
1772 rect.left = x + metrics.gmptGlyphOrigin.x;
1773 rect.top = y - metrics.gmptGlyphOrigin.y;
1774 rect.right = rect.left + metrics.gmBlackBoxX;
1775 rect.bottom = rect.top + metrics.gmBlackBoxY;
1776 add_bounds_rect( &bounds, &rect );
1780 if (flags & ETO_PDY)
1783 y += dx[ i * 2 + 1];
1789 x += metrics.gmCellIncX;
1790 y += metrics.gmCellIncY;
1796 /* helper for nulldrv_ExtTextOut */
1797 static void draw_glyph( HDC hdc, INT origin_x, INT origin_y, const GLYPHMETRICS *metrics,
1798 const struct gdi_image_bits *image, const RECT *clip )
1800 static const BYTE masks[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
1801 UINT x, y, i, count, max_count;
1802 BYTE *ptr = image->ptr;
1803 int stride = get_dib_stride( metrics->gmBlackBoxX, 1 );
1805 RECT rect, clipped_rect;
1807 rect.left = origin_x + metrics->gmptGlyphOrigin.x;
1808 rect.top = origin_y - metrics->gmptGlyphOrigin.y;
1809 rect.right = rect.left + metrics->gmBlackBoxX;
1810 rect.bottom = rect.top + metrics->gmBlackBoxY;
1811 if (!clip) clipped_rect = rect;
1812 else if (!intersect_rect( &clipped_rect, &rect, clip )) return;
1814 max_count = (metrics->gmBlackBoxX + 1) * metrics->gmBlackBoxY;
1815 pts = HeapAlloc( GetProcessHeap(), 0, max_count * sizeof(*pts) );
1819 ptr += (clipped_rect.top - rect.top) * stride;
1820 for (y = clipped_rect.top; y < clipped_rect.bottom; y++, ptr += stride)
1822 for (x = clipped_rect.left - rect.left; x < clipped_rect.right - rect.left; x++)
1824 while (x < clipped_rect.right - rect.left && !(ptr[x / 8] & masks[x % 8])) x++;
1825 pts[count].x = rect.left + x;
1826 while (x < clipped_rect.right - rect.left && (ptr[x / 8] & masks[x % 8])) x++;
1827 pts[count + 1].x = rect.left + x;
1828 if (pts[count + 1].x > pts[count].x)
1830 pts[count].y = pts[count + 1].y = y;
1835 assert( count <= max_count );
1836 DPtoLP( hdc, pts, count );
1837 for (i = 0; i < count; i += 2) Polyline( hdc, pts + i, 2 );
1838 HeapFree( GetProcessHeap(), 0, pts );
1841 /***********************************************************************
1842 * nulldrv_ExtTextOut
1844 BOOL nulldrv_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags, const RECT *rect,
1845 LPCWSTR str, UINT count, const INT *dx )
1847 DC *dc = get_nulldrv_dc( dev );
1853 if (flags & ETO_OPAQUE)
1856 HBRUSH brush = CreateSolidBrush( GetNearestColor( dev->hdc, GetBkColor(dev->hdc) ));
1860 orig = SelectObject( dev->hdc, brush );
1861 DPtoLP( dev->hdc, (POINT *)&rc, 2 );
1862 PatBlt( dev->hdc, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, PATCOPY );
1863 SelectObject( dev->hdc, orig );
1864 DeleteObject( brush );
1868 if (!count) return TRUE;
1870 aa_flags = get_font_aa_flags( dev->hdc );
1872 if (aa_flags != GGO_BITMAP)
1874 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1875 BITMAPINFO *info = (BITMAPINFO *)buffer;
1876 struct gdi_image_bits bits;
1877 struct bitblt_coords src, dst;
1880 dst_dev = GET_DC_PHYSDEV( dc, pPutImage );
1881 src.visrect = get_total_extents( dev->hdc, x, y, flags, aa_flags, str, count, dx );
1882 if (flags & ETO_CLIPPED) intersect_rect( &src.visrect, &src.visrect, rect );
1883 if (!clip_visrect( dc, &src.visrect, &src.visrect )) return TRUE;
1885 /* FIXME: check for ETO_OPAQUE and avoid GetImage */
1886 src.x = src.visrect.left;
1887 src.y = src.visrect.top;
1888 src.width = src.visrect.right - src.visrect.left;
1889 src.height = src.visrect.bottom - src.visrect.top;
1891 if ((flags & ETO_OPAQUE) && (src.visrect.left >= rect->left) && (src.visrect.top >= rect->top) &&
1892 (src.visrect.right <= rect->right) && (src.visrect.bottom <= rect->bottom))
1894 /* we can avoid the GetImage, just query the needed format */
1895 memset( &info->bmiHeader, 0, sizeof(info->bmiHeader) );
1896 info->bmiHeader.biSize = sizeof(info->bmiHeader);
1897 info->bmiHeader.biWidth = src.width;
1898 info->bmiHeader.biHeight = -src.height;
1899 err = dst_dev->funcs->pPutImage( dst_dev, 0, info, NULL, NULL, NULL, 0 );
1900 if (!err || err == ERROR_BAD_FORMAT)
1902 /* make the source rectangle relative to the source bits */
1904 src.visrect.left = src.visrect.top = 0;
1905 src.visrect.right = src.width;
1906 src.visrect.bottom = src.height;
1908 bits.ptr = HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( info ));
1909 if (!bits.ptr) return ERROR_OUTOFMEMORY;
1910 bits.is_copy = TRUE;
1911 bits.free = free_heap_bits;
1912 err = ERROR_SUCCESS;
1917 PHYSDEV src_dev = GET_DC_PHYSDEV( dc, pGetImage );
1918 err = src_dev->funcs->pGetImage( src_dev, info, &bits, &src );
1919 if (!err && !bits.is_copy)
1921 void *ptr = HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( info ));
1924 if (bits.free) bits.free( &bits );
1925 return ERROR_OUTOFMEMORY;
1927 memcpy( ptr, bits.ptr, get_dib_image_size( info ));
1928 if (bits.free) bits.free( &bits );
1930 bits.is_copy = TRUE;
1931 bits.free = free_heap_bits;
1936 /* make x,y relative to the image bits */
1937 x += src.visrect.left - dst.visrect.left;
1938 y += src.visrect.top - dst.visrect.top;
1939 render_aa_text_bitmapinfo( dev->hdc, info, &bits, &src, x, y, flags,
1940 aa_flags, str, count, dx );
1941 err = dst_dev->funcs->pPutImage( dst_dev, 0, info, &bits, &src, &dst, SRCCOPY );
1942 if (bits.free) bits.free( &bits );
1947 pen = CreatePen( PS_SOLID, 1, GetTextColor(dev->hdc) );
1948 orig = SelectObject( dev->hdc, pen );
1950 for (i = 0; i < count; i++)
1952 GLYPHMETRICS metrics;
1953 struct gdi_image_bits image;
1955 err = get_glyph_bitmap( dev->hdc, (UINT)str[i], GGO_BITMAP, &metrics, &image );
1958 if (image.ptr) draw_glyph( dev->hdc, x, y, &metrics, &image, (flags & ETO_CLIPPED) ? rect : NULL );
1959 if (image.free) image.free( &image );
1963 if (flags & ETO_PDY)
1966 y += dx[ i * 2 + 1];
1972 x += metrics.gmCellIncX;
1973 y += metrics.gmCellIncY;
1977 SelectObject( dev->hdc, orig );
1978 DeleteObject( pen );
1983 /***********************************************************************
1984 * ExtTextOutA (GDI32.@)
1988 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1989 const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1997 if (flags & ETO_GLYPH_INDEX)
1998 return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
2000 p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
2003 unsigned int i = 0, j = 0;
2005 /* allocate enough for a ETO_PDY */
2006 lpDxW = HeapAlloc( GetProcessHeap(), 0, 2*wlen*sizeof(INT));
2008 if(IsDBCSLeadByteEx(codepage, str[i]))
2012 lpDxW[j++] = lpDx[i * 2] + lpDx[(i + 1) * 2];
2013 lpDxW[j++] = lpDx[i * 2 + 1] + lpDx[(i + 1) * 2 + 1];
2016 lpDxW[j++] = lpDx[i] + lpDx[i + 1];
2023 lpDxW[j++] = lpDx[i * 2];
2024 lpDxW[j++] = lpDx[i * 2 + 1];
2027 lpDxW[j++] = lpDx[i];
2033 ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
2035 HeapFree( GetProcessHeap(), 0, p );
2036 HeapFree( GetProcessHeap(), 0, lpDxW );
2041 /***********************************************************************
2042 * ExtTextOutW (GDI32.@)
2044 * Draws text using the currently selected font, background color, and text color.
2048 * x,y [I] coordinates of string
2050 * ETO_GRAYED - undocumented on MSDN
2051 * ETO_OPAQUE - use background color for fill the rectangle
2052 * ETO_CLIPPED - clipping text to the rectangle
2053 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
2054 * than encoded characters. Implies ETO_IGNORELANGUAGE
2055 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
2056 * Affects BiDi ordering
2057 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
2058 * ETO_PDY - unimplemented
2059 * ETO_NUMERICSLATIN - unimplemented always assumed -
2060 * do not translate numbers into locale representations
2061 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
2062 * lprect [I] dimensions for clipping or/and opaquing
2063 * str [I] text string
2064 * count [I] number of symbols in string
2065 * lpDx [I] optional parameter with distance between drawing characters
2071 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
2072 const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
2075 LPWSTR reordered_str = (LPWSTR)str;
2076 WORD *glyphs = NULL;
2077 UINT align = GetTextAlign( hdc );
2078 DWORD layout = GetLayout( hdc );
2082 double cosEsc, sinEsc;
2086 BOOL done_extents = FALSE;
2087 POINT *deltas = NULL, width = {0, 0};
2089 DC * dc = get_dc_ptr( hdc );
2092 static int quietfixme = 0;
2094 if (!dc) return FALSE;
2096 breakRem = dc->breakRem;
2098 if (quietfixme == 0 && flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN))
2100 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN unimplemented\n");
2105 physdev = GET_DC_PHYSDEV( dc, pExtTextOut );
2106 type = GetObjectType(hdc);
2107 if(type == OBJ_METADC || type == OBJ_ENHMETADC)
2109 ret = physdev->funcs->pExtTextOut( physdev, x, y, flags, lprect, str, count, lpDx );
2110 release_dc_ptr( dc );
2115 flags &= ~ETO_CLIPPED;
2117 if (flags & ETO_RTLREADING) align |= TA_RTLREADING;
2118 if (layout & LAYOUT_RTL)
2120 if ((align & TA_CENTER) != TA_CENTER) align ^= TA_RIGHT;
2121 align ^= TA_RTLREADING;
2124 if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && count > 0 )
2127 reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
2129 BIDI_Reorder( hdc, str, count, GCP_REORDER,
2130 (align & TA_RTLREADING) ? WINE_GCPW_FORCE_RTL : WINE_GCPW_FORCE_LTR,
2131 reordered_str, count, NULL, &glyphs, &cGlyphs);
2133 flags |= ETO_IGNORELANGUAGE;
2136 flags |= ETO_GLYPH_INDEX;
2137 if (cGlyphs != count)
2141 else if(flags & ETO_GLYPH_INDEX)
2142 glyphs = reordered_str;
2144 TRACE("%p, %d, %d, %08x, %s, %s, %d, %p)\n", hdc, x, y, flags,
2145 wine_dbgstr_rect(lprect), debugstr_wn(str, count), count, lpDx);
2146 TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
2148 if(align & TA_UPDATECP)
2150 GetCurrentPositionEx( hdc, &pt );
2155 GetTextMetricsW(hdc, &tm);
2156 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
2158 if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
2159 lf.lfEscapement = 0;
2161 if ((dc->GraphicsMode == GM_COMPATIBLE) &&
2162 (dc->vport2WorldValid && dc->xformWorld2Vport.eM11 * dc->xformWorld2Vport.eM22 < 0))
2164 lf.lfEscapement = -lf.lfEscapement;
2167 if(lf.lfEscapement != 0)
2169 cosEsc = cos(lf.lfEscapement * M_PI / 1800);
2170 sinEsc = sin(lf.lfEscapement * M_PI / 1800);
2178 if(flags & (ETO_CLIPPED | ETO_OPAQUE))
2182 if(flags & ETO_GLYPH_INDEX)
2183 GetTextExtentPointI(hdc, glyphs, count, &sz);
2185 GetTextExtentPointW(hdc, reordered_str, count, &sz);
2187 done_extents = TRUE;
2190 rc.right = x + sz.cx;
2191 rc.bottom = y + sz.cy;
2198 LPtoDP(hdc, (POINT*)&rc, 2);
2200 if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
2201 if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
2204 if (lprect && (flags & ETO_OPAQUE))
2205 physdev->funcs->pExtTextOut( physdev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL );
2215 LPtoDP(hdc, &pt, 1);
2219 char_extra = GetTextCharacterExtra(hdc);
2220 if(char_extra || dc->breakExtra || breakRem || lpDx || lf.lfEscapement != 0)
2224 POINT total = {0, 0}, desired[2];
2226 deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
2227 for(i = 0; i < count; i++)
2233 deltas[i].x = lpDx[i * 2] + char_extra;
2234 deltas[i].y = -lpDx[i * 2 + 1];
2238 deltas[i].x = lpDx[i] + char_extra;
2245 if(flags & ETO_GLYPH_INDEX)
2246 GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
2248 GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
2250 deltas[i].x = tmpsz.cx;
2254 if (!(flags & ETO_GLYPH_INDEX) && (dc->breakExtra || breakRem) && reordered_str[i] == tm.tmBreakChar)
2256 deltas[i].x = deltas[i].x + dc->breakExtra;
2263 total.x += deltas[i].x;
2264 total.y += deltas[i].y;
2266 desired[0].x = desired[0].y = 0;
2268 desired[1].x = cosEsc * total.x + sinEsc * total.y;
2269 desired[1].y = -sinEsc * total.x + cosEsc * total.y;
2271 LPtoDP(hdc, desired, 2);
2272 desired[1].x -= desired[0].x;
2273 desired[1].y -= desired[0].y;
2275 if (dc->GraphicsMode == GM_COMPATIBLE)
2277 if (dc->vport2WorldValid && dc->xformWorld2Vport.eM11 < 0)
2278 desired[1].x = -desired[1].x;
2279 if (dc->vport2WorldValid && dc->xformWorld2Vport.eM22 < 0)
2280 desired[1].y = -desired[1].y;
2284 if (layout & LAYOUT_RTL) desired[1].x = -desired[1].x;
2287 deltas[i].x = desired[1].x - width.x;
2288 deltas[i].y = desired[1].y - width.y;
2298 if(flags & ETO_GLYPH_INDEX)
2299 GetTextExtentPointI(hdc, glyphs, count, &sz);
2301 GetTextExtentPointW(hdc, reordered_str, count, &sz);
2302 done_extents = TRUE;
2304 width.x = abs(INTERNAL_XWSTODS(dc, sz.cx));
2308 tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
2309 tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
2310 switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
2313 if (align & TA_UPDATECP)
2317 DPtoLP(hdc, &pt, 1);
2318 MoveToEx(hdc, pt.x, pt.y, NULL);
2330 if (align & TA_UPDATECP)
2334 DPtoLP(hdc, &pt, 1);
2335 MoveToEx(hdc, pt.x, pt.y, NULL);
2340 switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
2343 y += tm.tmAscent * cosEsc;
2344 x += tm.tmAscent * sinEsc;
2348 y -= tm.tmDescent * cosEsc;
2349 x -= tm.tmDescent * sinEsc;
2356 if (GetBkMode(hdc) != TRANSPARENT)
2358 if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
2360 if(!(flags & ETO_OPAQUE) || !lprect ||
2361 x < rc.left || x + width.x >= rc.right ||
2362 y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
2366 text_box.right = x + width.x;
2367 text_box.top = y - tm.tmAscent;
2368 text_box.bottom = y + tm.tmDescent;
2370 if (flags & ETO_CLIPPED) intersect_rect( &text_box, &text_box, &rc );
2371 if (!is_rect_empty( &text_box ))
2372 physdev->funcs->pExtTextOut( physdev, 0, 0, ETO_OPAQUE, &text_box, NULL, 0, NULL );
2377 if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
2379 HFONT orig_font = dc->hFont, cur_font;
2382 POINT *offsets = NULL;
2385 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2386 for(i = 0; i < count; i++)
2388 WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
2389 if(cur_font != dc->hFont)
2394 offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
2395 offsets[0].x = offsets[0].y = 0;
2400 for(j = 1; j < count; j++)
2402 GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
2403 offsets[j].x = offsets[j - 1].x + abs(INTERNAL_XWSTODS(dc, tmpsz.cx));
2409 for(j = 1; j < count; j++)
2411 offsets[j].x = offsets[j - 1].x + deltas[j].x;
2412 offsets[j].y = offsets[j - 1].y + deltas[j].y;
2418 physdev->funcs->pExtTextOut( physdev, x + offsets[i - span].x,
2419 y + offsets[i - span].y,
2420 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc, glyphs,
2421 span, deltas ? (INT*)(deltas + (i - span)) : NULL);
2424 SelectObject(hdc, cur_font);
2426 glyphs[span++] = glyph;
2430 ret = physdev->funcs->pExtTextOut(physdev, x + (offsets ? offsets[count - span].x : 0),
2431 y + (offsets ? offsets[count - span].y : 0),
2432 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc, glyphs,
2433 span, deltas ? (INT*)(deltas + (count - span)) : NULL);
2434 SelectObject(hdc, orig_font);
2435 HeapFree(GetProcessHeap(), 0, offsets);
2441 if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
2443 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2444 GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
2445 flags |= ETO_GLYPH_INDEX;
2447 ret = physdev->funcs->pExtTextOut( physdev, x, y, (flags & ~ETO_OPAQUE), &rc,
2448 glyphs ? glyphs : reordered_str, count, (INT*)deltas );
2452 HeapFree(GetProcessHeap(), 0, deltas);
2453 if(glyphs != reordered_str)
2454 HeapFree(GetProcessHeap(), 0, glyphs);
2455 if(reordered_str != str)
2456 HeapFree(GetProcessHeap(), 0, reordered_str);
2458 release_dc_ptr( dc );
2460 if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2462 int underlinePos, strikeoutPos;
2463 int underlineWidth, strikeoutWidth;
2464 UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2465 OUTLINETEXTMETRICW* otm = NULL;
2467 HPEN hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2468 HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2470 hbrush = SelectObject(hdc, hbrush);
2475 underlineWidth = tm.tmAscent / 20 + 1;
2476 strikeoutPos = tm.tmAscent / 2;
2477 strikeoutWidth = underlineWidth;
2481 otm = HeapAlloc(GetProcessHeap(), 0, size);
2482 GetOutlineTextMetricsW(hdc, size, otm);
2483 underlinePos = abs( INTERNAL_YWSTODS( dc, otm->otmsUnderscorePosition ));
2484 if (otm->otmsUnderscorePosition < 0) underlinePos = -underlinePos;
2485 underlineWidth = abs( INTERNAL_YWSTODS( dc, otm->otmsUnderscoreSize ));
2486 if (otm->otmsUnderscoreSize < 0) underlineWidth = -underlineWidth;
2487 strikeoutPos = abs( INTERNAL_YWSTODS( dc, otm->otmsStrikeoutPosition ));
2488 if (otm->otmsStrikeoutPosition < 0) strikeoutPos = -strikeoutPos;
2489 strikeoutWidth = abs( INTERNAL_YWSTODS( dc, otm->otmsStrikeoutSize ));
2490 HeapFree(GetProcessHeap(), 0, otm);
2496 pts[0].x = x - (underlinePos + underlineWidth / 2) * sinEsc;
2497 pts[0].y = y - (underlinePos + underlineWidth / 2) * cosEsc;
2498 pts[1].x = x + width.x - (underlinePos + underlineWidth / 2) * sinEsc;
2499 pts[1].y = y + width.y - (underlinePos + underlineWidth / 2) * cosEsc;
2500 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2501 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2502 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2503 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2504 pts[4].x = pts[0].x;
2505 pts[4].y = pts[0].y;
2506 DPtoLP(hdc, pts, 5);
2507 Polygon(hdc, pts, 5);
2512 pts[0].x = x - (strikeoutPos + strikeoutWidth / 2) * sinEsc;
2513 pts[0].y = y - (strikeoutPos + strikeoutWidth / 2) * cosEsc;
2514 pts[1].x = x + width.x - (strikeoutPos + strikeoutWidth / 2) * sinEsc;
2515 pts[1].y = y + width.y - (strikeoutPos + strikeoutWidth / 2) * cosEsc;
2516 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2517 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2518 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2519 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2520 pts[4].x = pts[0].x;
2521 pts[4].y = pts[0].y;
2522 DPtoLP(hdc, pts, 5);
2523 Polygon(hdc, pts, 5);
2526 SelectObject(hdc, hpen);
2527 hbrush = SelectObject(hdc, hbrush);
2528 DeleteObject(hbrush);
2535 /***********************************************************************
2536 * TextOutA (GDI32.@)
2538 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2540 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2544 /***********************************************************************
2545 * TextOutW (GDI32.@)
2547 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2549 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2553 /***********************************************************************
2554 * PolyTextOutA (GDI32.@)
2558 BOOL WINAPI PolyTextOutA( HDC hdc, const POLYTEXTA *pptxt, INT cStrings )
2560 for (; cStrings>0; cStrings--, pptxt++)
2561 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2568 /***********************************************************************
2569 * PolyTextOutW (GDI32.@)
2571 * Draw several Strings
2577 BOOL WINAPI PolyTextOutW( HDC hdc, const POLYTEXTW *pptxt, INT cStrings )
2579 for (; cStrings>0; cStrings--, pptxt++)
2580 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2586 /***********************************************************************
2587 * SetMapperFlags (GDI32.@)
2589 DWORD WINAPI SetMapperFlags( HDC hdc, DWORD flags )
2591 DC *dc = get_dc_ptr( hdc );
2592 DWORD ret = GDI_ERROR;
2596 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetMapperFlags );
2597 flags = physdev->funcs->pSetMapperFlags( physdev, flags );
2598 if (flags != GDI_ERROR)
2600 ret = dc->mapperFlags;
2601 dc->mapperFlags = flags;
2603 release_dc_ptr( dc );
2608 /***********************************************************************
2609 * GetAspectRatioFilterEx (GDI32.@)
2611 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2613 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2618 /***********************************************************************
2619 * GetCharABCWidthsA (GDI32.@)
2621 * See GetCharABCWidthsW.
2623 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2631 str = FONT_GetCharsByRangeA(hdc, firstChar, lastChar, &i);
2635 wstr = FONT_mbtowc(hdc, str, i, &wlen, NULL);
2638 HeapFree(GetProcessHeap(), 0, str);
2642 for(i = 0; i < wlen; i++)
2644 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2652 HeapFree(GetProcessHeap(), 0, str);
2653 HeapFree(GetProcessHeap(), 0, wstr);
2659 /******************************************************************************
2660 * GetCharABCWidthsW [GDI32.@]
2662 * Retrieves widths of characters in range.
2665 * hdc [I] Handle of device context
2666 * firstChar [I] First character in range to query
2667 * lastChar [I] Last character in range to query
2668 * abc [O] Address of character-width structure
2671 * Only works with TrueType fonts
2677 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2680 DC *dc = get_dc_ptr(hdc);
2686 if (!dc) return FALSE;
2690 release_dc_ptr( dc );
2694 /* unlike GetCharABCWidthsFloatW, this one is supposed to fail on non-scalable fonts */
2695 dev = GET_DC_PHYSDEV( dc, pGetTextMetrics );
2696 if (!dev->funcs->pGetTextMetrics( dev, &tm ) || !(tm.tmPitchAndFamily & TMPF_VECTOR))
2698 release_dc_ptr( dc );
2702 dev = GET_DC_PHYSDEV( dc, pGetCharABCWidths );
2703 ret = dev->funcs->pGetCharABCWidths( dev, firstChar, lastChar, abc );
2706 /* convert device units to logical */
2707 for( i = firstChar; i <= lastChar; i++, abc++ ) {
2708 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2709 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2710 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2714 release_dc_ptr( dc );
2719 /******************************************************************************
2720 * GetCharABCWidthsI [GDI32.@]
2722 * Retrieves widths of characters in range.
2725 * hdc [I] Handle of device context
2726 * firstChar [I] First glyphs in range to query
2727 * count [I] Last glyphs in range to query
2728 * pgi [i] Array of glyphs to query
2729 * abc [O] Address of character-width structure
2732 * Only works with TrueType fonts
2738 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2739 LPWORD pgi, LPABC abc)
2741 DC *dc = get_dc_ptr(hdc);
2746 if (!dc) return FALSE;
2750 release_dc_ptr( dc );
2754 dev = GET_DC_PHYSDEV( dc, pGetCharABCWidthsI );
2755 ret = dev->funcs->pGetCharABCWidthsI( dev, firstChar, count, pgi, abc );
2758 /* convert device units to logical */
2759 for( i = 0; i < count; i++, abc++ ) {
2760 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2761 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2762 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2766 release_dc_ptr( dc );
2771 /***********************************************************************
2772 * GetGlyphOutlineA (GDI32.@)
2774 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2775 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2776 LPVOID lpBuffer, const MAT2 *lpmat2 )
2778 if (!lpmat2) return GDI_ERROR;
2780 if(!(fuFormat & GGO_GLYPH_INDEX)) {
2785 cp = GdiGetCodePage(hdc);
2786 if (IsDBCSLeadByteEx(cp, uChar >> 8)) {
2788 mbchs[0] = (uChar & 0xff00) >> 8;
2789 mbchs[1] = (uChar & 0xff);
2792 mbchs[0] = (uChar & 0xff);
2795 MultiByteToWideChar(cp, 0, mbchs, len, (LPWSTR)&uChar, 1);
2798 return GetGlyphOutlineW(hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer,
2802 /***********************************************************************
2803 * GetGlyphOutlineW (GDI32.@)
2805 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2806 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2807 LPVOID lpBuffer, const MAT2 *lpmat2 )
2813 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2814 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2816 if (!lpmat2) return GDI_ERROR;
2818 dc = get_dc_ptr(hdc);
2819 if(!dc) return GDI_ERROR;
2821 dev = GET_DC_PHYSDEV( dc, pGetGlyphOutline );
2822 ret = dev->funcs->pGetGlyphOutline( dev, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2823 release_dc_ptr( dc );
2828 /***********************************************************************
2829 * CreateScalableFontResourceA (GDI32.@)
2831 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2832 LPCSTR lpszResourceFile,
2833 LPCSTR lpszFontFile,
2834 LPCSTR lpszCurrentPath )
2836 LPWSTR lpszResourceFileW = NULL;
2837 LPWSTR lpszFontFileW = NULL;
2838 LPWSTR lpszCurrentPathW = NULL;
2842 if (lpszResourceFile)
2844 len = MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, NULL, 0);
2845 lpszResourceFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2846 MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, lpszResourceFileW, len);
2851 len = MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, NULL, 0);
2852 lpszFontFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2853 MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, lpszFontFileW, len);
2856 if (lpszCurrentPath)
2858 len = MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, NULL, 0);
2859 lpszCurrentPathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2860 MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, lpszCurrentPathW, len);
2863 ret = CreateScalableFontResourceW(fHidden, lpszResourceFileW,
2864 lpszFontFileW, lpszCurrentPathW);
2866 HeapFree(GetProcessHeap(), 0, lpszResourceFileW);
2867 HeapFree(GetProcessHeap(), 0, lpszFontFileW);
2868 HeapFree(GetProcessHeap(), 0, lpszCurrentPathW);
2873 /***********************************************************************
2874 * CreateScalableFontResourceW (GDI32.@)
2876 BOOL WINAPI CreateScalableFontResourceW( DWORD hidden, LPCWSTR resource_file,
2877 LPCWSTR font_file, LPCWSTR font_path )
2879 TRACE("(%d, %s, %s, %s)\n", hidden, debugstr_w(resource_file),
2880 debugstr_w(font_file), debugstr_w(font_path) );
2882 return WineEngCreateScalableFontResource( hidden, resource_file,
2883 font_file, font_path );
2886 /*************************************************************************
2887 * GetKerningPairsA (GDI32.@)
2889 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2890 LPKERNINGPAIR kern_pairA )
2894 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2895 KERNINGPAIR *kern_pairW;
2897 if (!cPairs && kern_pairA)
2899 SetLastError(ERROR_INVALID_PARAMETER);
2903 cp = GdiGetCodePage(hDC);
2905 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2906 * to fail on an invalid character for CP_SYMBOL.
2908 cpi.DefaultChar[0] = 0;
2909 if (cp != CP_SYMBOL && !GetCPInfo(cp, &cpi))
2911 FIXME("Can't find codepage %u info\n", cp);
2915 total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2916 if (!total_kern_pairs) return 0;
2918 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2919 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2921 for (i = 0; i < total_kern_pairs; i++)
2925 if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2928 if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2931 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2936 if (kern_pairs_copied >= cPairs) break;
2938 kern_pairA->wFirst = (BYTE)first;
2939 kern_pairA->wSecond = (BYTE)second;
2940 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2943 kern_pairs_copied++;
2946 HeapFree(GetProcessHeap(), 0, kern_pairW);
2948 return kern_pairs_copied;
2951 /*************************************************************************
2952 * GetKerningPairsW (GDI32.@)
2954 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2955 LPKERNINGPAIR lpKerningPairs )
2961 TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2963 if (!cPairs && lpKerningPairs)
2965 SetLastError(ERROR_INVALID_PARAMETER);
2969 dc = get_dc_ptr(hDC);
2972 dev = GET_DC_PHYSDEV( dc, pGetKerningPairs );
2973 ret = dev->funcs->pGetKerningPairs( dev, cPairs, lpKerningPairs );
2974 release_dc_ptr( dc );
2978 /*************************************************************************
2979 * TranslateCharsetInfo [GDI32.@]
2981 * Fills a CHARSETINFO structure for a character set, code page, or
2982 * font. This allows making the correspondence between different labels
2983 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2984 * of the same encoding.
2986 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2987 * only one codepage should be set in *lpSrc.
2990 * TRUE on success, FALSE on failure.
2993 BOOL WINAPI TranslateCharsetInfo(
2994 LPDWORD lpSrc, /* [in]
2995 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2996 if flags == TCI_SRCCHARSET: a character set value
2997 if flags == TCI_SRCCODEPAGE: a code page value
2999 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
3000 DWORD flags /* [in] determines interpretation of lpSrc */)
3004 case TCI_SRCFONTSIG:
3005 while (index < MAXTCIINDEX && !(*lpSrc>>index & 0x0001)) index++;
3007 case TCI_SRCCODEPAGE:
3008 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciACP) index++;
3010 case TCI_SRCCHARSET:
3011 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciCharset) index++;
3016 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
3017 *lpCs = FONT_tci[index];
3021 /*************************************************************************
3022 * GetFontLanguageInfo (GDI32.@)
3024 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
3026 FONTSIGNATURE fontsig;
3027 static const DWORD GCP_DBCS_MASK=0x003F0000,
3028 GCP_DIACRITIC_MASK=0x00000000,
3029 FLI_GLYPHS_MASK=0x00000000,
3030 GCP_GLYPHSHAPE_MASK=0x00000040,
3031 GCP_KASHIDA_MASK=0x00000000,
3032 GCP_LIGATE_MASK=0x00000000,
3033 GCP_USEKERNING_MASK=0x00000000,
3034 GCP_REORDER_MASK=0x00000060;
3038 GetTextCharsetInfo( hdc, &fontsig, 0 );
3039 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
3041 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
3044 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
3045 result|=GCP_DIACRITIC;
3047 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
3050 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
3051 result|=GCP_GLYPHSHAPE;
3053 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
3054 result|=GCP_KASHIDA;
3056 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
3059 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
3060 result|=GCP_USEKERNING;
3062 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
3063 if( GetTextAlign( hdc) & TA_RTLREADING )
3064 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
3065 result|=GCP_REORDER;
3071 /*************************************************************************
3072 * GetFontData [GDI32.@]
3074 * Retrieve data for TrueType font.
3078 * success: Number of bytes returned
3079 * failure: GDI_ERROR
3083 * Calls SetLastError()
3086 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
3087 LPVOID buffer, DWORD length)
3089 DC *dc = get_dc_ptr(hdc);
3093 if(!dc) return GDI_ERROR;
3095 dev = GET_DC_PHYSDEV( dc, pGetFontData );
3096 ret = dev->funcs->pGetFontData( dev, table, offset, buffer, length );
3097 release_dc_ptr( dc );
3101 /*************************************************************************
3102 * GetGlyphIndicesA [GDI32.@]
3104 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
3105 LPWORD pgi, DWORD flags)
3111 TRACE("(%p, %s, %d, %p, 0x%x)\n",
3112 hdc, debugstr_an(lpstr, count), count, pgi, flags);
3114 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
3115 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
3116 HeapFree(GetProcessHeap(), 0, lpstrW);
3121 /*************************************************************************
3122 * GetGlyphIndicesW [GDI32.@]
3124 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
3125 LPWORD pgi, DWORD flags)
3127 DC *dc = get_dc_ptr(hdc);
3131 TRACE("(%p, %s, %d, %p, 0x%x)\n",
3132 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
3134 if(!dc) return GDI_ERROR;
3136 dev = GET_DC_PHYSDEV( dc, pGetGlyphIndices );
3137 ret = dev->funcs->pGetGlyphIndices( dev, lpstr, count, pgi, flags );
3138 release_dc_ptr( dc );
3142 /*************************************************************************
3143 * GetCharacterPlacementA [GDI32.@]
3145 * See GetCharacterPlacementW.
3148 * the web browser control of ie4 calls this with dwFlags=0
3151 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
3152 INT nMaxExtent, GCP_RESULTSA *lpResults,
3157 GCP_RESULTSW resultsW;
3161 TRACE("%s, %d, %d, 0x%08x\n",
3162 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
3164 /* both structs are equal in size */
3165 memcpy(&resultsW, lpResults, sizeof(resultsW));
3167 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
3168 if(lpResults->lpOutString)
3169 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
3171 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
3173 lpResults->nGlyphs = resultsW.nGlyphs;
3174 lpResults->nMaxFit = resultsW.nMaxFit;
3176 if(lpResults->lpOutString) {
3177 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
3178 lpResults->lpOutString, uCount, NULL, NULL );
3181 HeapFree(GetProcessHeap(), 0, lpStringW);
3182 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
3187 /*************************************************************************
3188 * GetCharacterPlacementW [GDI32.@]
3190 * Retrieve information about a string. This includes the width, reordering,
3191 * Glyphing and so on.
3195 * The width and height of the string if successful, 0 if failed.
3199 * All flags except GCP_REORDER are not yet implemented.
3200 * Reordering is not 100% compliant to the Windows BiDi method.
3201 * Caret positioning is not yet implemented for BiDi.
3202 * Classes are not yet implemented.
3206 GetCharacterPlacementW(
3207 HDC hdc, /* [in] Device context for which the rendering is to be done */
3208 LPCWSTR lpString, /* [in] The string for which information is to be returned */
3209 INT uCount, /* [in] Number of WORDS in string. */
3210 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
3211 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
3212 DWORD dwFlags /* [in] Flags specifying how to process the string */
3219 TRACE("%s, %d, %d, 0x%08x\n",
3220 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
3222 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
3223 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
3224 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
3225 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
3226 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
3228 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08x ignored\n", dwFlags);
3229 if(lpResults->lpClass) FIXME("classes not implemented\n");
3230 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
3231 FIXME("Caret positions for complex scripts not implemented\n");
3233 nSet = (UINT)uCount;
3234 if(nSet > lpResults->nGlyphs)
3235 nSet = lpResults->nGlyphs;
3237 /* return number of initialized fields */
3238 lpResults->nGlyphs = nSet;
3240 if((dwFlags&GCP_REORDER)==0 )
3242 /* Treat the case where no special handling was requested in a fastpath way */
3243 /* copy will do if the GCP_REORDER flag is not set */
3244 if(lpResults->lpOutString)
3245 memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
3247 if(lpResults->lpOrder)
3249 for(i = 0; i < nSet; i++)
3250 lpResults->lpOrder[i] = i;
3254 BIDI_Reorder(NULL, lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
3255 nSet, lpResults->lpOrder, NULL, NULL );
3258 /* FIXME: Will use the placement chars */
3259 if (lpResults->lpDx)
3262 for (i = 0; i < nSet; i++)
3264 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
3265 lpResults->lpDx[i]= c;
3269 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
3273 lpResults->lpCaretPos[0] = 0;
3274 for (i = 1; i < nSet; i++)
3275 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
3276 lpResults->lpCaretPos[i] = (pos += size.cx);
3279 if(lpResults->lpGlyphs)
3280 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
3282 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
3283 ret = MAKELONG(size.cx, size.cy);
3288 /*************************************************************************
3289 * GetCharABCWidthsFloatA [GDI32.@]
3291 * See GetCharABCWidthsFloatW.
3293 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3300 str = FONT_GetCharsByRangeA(hdc, first, last, &i);
3304 wstr = FONT_mbtowc( hdc, str, i, &wlen, NULL );
3306 for (i = 0; i < wlen; i++)
3308 if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
3316 HeapFree( GetProcessHeap(), 0, str );
3317 HeapFree( GetProcessHeap(), 0, wstr );
3322 /*************************************************************************
3323 * GetCharABCWidthsFloatW [GDI32.@]
3325 * Retrieves widths of a range of characters.
3328 * hdc [I] Handle to device context.
3329 * first [I] First character in range to query.
3330 * last [I] Last character in range to query.
3331 * abcf [O] Array of LPABCFLOAT structures.
3337 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3343 DC *dc = get_dc_ptr( hdc );
3345 TRACE("%p, %d, %d, %p\n", hdc, first, last, abcf);
3347 if (!dc) return FALSE;
3349 if (!abcf) goto done;
3350 if (!(abc = HeapAlloc( GetProcessHeap(), 0, (last - first + 1) * sizeof(*abc) ))) goto done;
3352 dev = GET_DC_PHYSDEV( dc, pGetCharABCWidths );
3353 ret = dev->funcs->pGetCharABCWidths( dev, first, last, abc );
3356 /* convert device units to logical */
3357 for (i = first; i <= last; i++, abcf++)
3359 abcf->abcfA = abc[i - first].abcA * dc->xformVport2World.eM11;
3360 abcf->abcfB = abc[i - first].abcB * dc->xformVport2World.eM11;
3361 abcf->abcfC = abc[i - first].abcC * dc->xformVport2World.eM11;
3364 HeapFree( GetProcessHeap(), 0, abc );
3367 release_dc_ptr( dc );
3371 /*************************************************************************
3372 * GetCharWidthFloatA [GDI32.@]
3374 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
3375 UINT iLastChar, PFLOAT pxBuffer)
3377 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3381 /*************************************************************************
3382 * GetCharWidthFloatW [GDI32.@]
3384 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
3385 UINT iLastChar, PFLOAT pxBuffer)
3387 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3392 /***********************************************************************
3394 * Font Resource API *
3396 ***********************************************************************/
3398 /***********************************************************************
3399 * AddFontResourceA (GDI32.@)
3401 INT WINAPI AddFontResourceA( LPCSTR str )
3403 return AddFontResourceExA( str, 0, NULL);
3406 /***********************************************************************
3407 * AddFontResourceW (GDI32.@)
3409 INT WINAPI AddFontResourceW( LPCWSTR str )
3411 return AddFontResourceExW(str, 0, NULL);
3415 /***********************************************************************
3416 * AddFontResourceExA (GDI32.@)
3418 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3420 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3421 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3424 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3425 ret = AddFontResourceExW(strW, fl, pdv);
3426 HeapFree(GetProcessHeap(), 0, strW);
3430 static BOOL CALLBACK load_enumed_resource(HMODULE hModule, LPCWSTR type, LPWSTR name, LONG_PTR lParam)
3432 HRSRC rsrc = FindResourceW(hModule, name, type);
3433 HGLOBAL hMem = LoadResource(hModule, rsrc);
3434 LPVOID *pMem = LockResource(hMem);
3435 int *num_total = (int *)lParam;
3438 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type));
3439 if (!AddFontMemResourceEx(pMem, SizeofResource(hModule, rsrc), NULL, &num_in_res))
3441 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule, hMem);
3445 *num_total += num_in_res;
3449 static void *map_file( const WCHAR *filename, LARGE_INTEGER *size )
3451 HANDLE file, mapping;
3454 file = CreateFileW( filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
3455 if (file == INVALID_HANDLE_VALUE) return NULL;
3457 if (!GetFileSizeEx( file, size ) || size->u.HighPart)
3459 CloseHandle( file );
3463 mapping = CreateFileMappingW( file, NULL, PAGE_READONLY, 0, 0, NULL );
3464 CloseHandle( file );
3465 if (!mapping) return NULL;
3467 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 );
3468 CloseHandle( mapping );
3473 static WCHAR *get_scalable_filename( const WCHAR *res )
3476 BYTE *ptr = map_file( res, &size );
3477 const IMAGE_DOS_HEADER *dos;
3478 const IMAGE_OS2_HEADER *ne;
3480 WORD rsrc_off, align, type_id, count;
3481 DWORD res_off, res_len, i;
3484 if (!ptr) return NULL;
3486 if (size.u.LowPart < sizeof( *dos )) goto fail;
3487 dos = (const IMAGE_DOS_HEADER *)ptr;
3488 if (dos->e_magic != IMAGE_DOS_SIGNATURE) goto fail;
3489 if (size.u.LowPart < dos->e_lfanew + sizeof( *ne )) goto fail;
3490 ne = (const IMAGE_OS2_HEADER *)(ptr + dos->e_lfanew);
3491 rsrc_off = dos->e_lfanew + ne->ne_rsrctab;
3492 if (size.u.LowPart < rsrc_off + 10) goto fail;
3493 align = *(WORD *)(ptr + rsrc_off);
3495 type_id = *(WORD *)(ptr + rsrc_off);
3496 while (type_id && type_id != 0x80cc)
3498 count = *(WORD *)(ptr + rsrc_off + 2);
3499 rsrc_off += 8 + count * 12;
3500 if (size.u.LowPart < rsrc_off + 8) goto fail;
3501 type_id = *(WORD *)(ptr + rsrc_off);
3503 if (!type_id) goto fail;
3504 count = *(WORD *)(ptr + rsrc_off + 2);
3505 if (size.u.LowPart < rsrc_off + 8 + count * 12) goto fail;
3507 res_off = *(WORD *)(ptr + rsrc_off + 8) << align;
3508 res_len = *(WORD *)(ptr + rsrc_off + 10) << align;
3509 if (size.u.LowPart < res_off + res_len) goto fail;
3511 for (i = 0; i < res_len; i++)
3512 if (ptr[ res_off + i ] == 0) break;
3513 if (i == res_len) goto fail;
3515 len = MultiByteToWideChar( CP_ACP, 0, (char *)ptr + res_off, -1, NULL, 0 );
3516 name = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
3517 if (name) MultiByteToWideChar( CP_ACP, 0, (char *)ptr + res_off, -1, name, len );
3520 UnmapViewOfFile( ptr );
3524 /***********************************************************************
3525 * AddFontResourceExW (GDI32.@)
3527 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3529 int ret = WineEngAddFontResourceEx(str, fl, pdv);
3534 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3535 HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
3536 if (hModule != NULL)
3538 int num_resources = 0;
3539 LPWSTR rt_font = (LPWSTR)((ULONG_PTR)8); /* we don't want to include winuser.h */
3541 TRACE("WineEngAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3542 wine_dbgstr_w(str));
3543 if (EnumResourceNamesW(hModule, rt_font, load_enumed_resource, (LONG_PTR)&num_resources))
3544 ret = num_resources;
3545 FreeLibrary(hModule);
3547 else if ((filename = get_scalable_filename( str )) != NULL)
3549 ret = WineEngAddFontResourceEx( filename, fl, pdv );
3550 HeapFree( GetProcessHeap(), 0, filename );
3556 /***********************************************************************
3557 * RemoveFontResourceA (GDI32.@)
3559 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3561 return RemoveFontResourceExA(str, 0, 0);
3564 /***********************************************************************
3565 * RemoveFontResourceW (GDI32.@)
3567 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3569 return RemoveFontResourceExW(str, 0, 0);
3572 /***********************************************************************
3573 * AddFontMemResourceEx (GDI32.@)
3575 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3580 if (!pbFont || !cbFont || !pcFonts)
3582 SetLastError(ERROR_INVALID_PARAMETER);
3586 ret = WineEngAddFontMemResourceEx(pbFont, cbFont, pdv, &num_fonts);
3591 *pcFonts = num_fonts;
3595 WARN("page fault while writing to *pcFonts (%p)\n", pcFonts);
3596 RemoveFontMemResourceEx(ret);
3604 /***********************************************************************
3605 * RemoveFontMemResourceEx (GDI32.@)
3607 BOOL WINAPI RemoveFontMemResourceEx( HANDLE fh )
3609 FIXME("(%p) stub\n", fh);
3613 /***********************************************************************
3614 * RemoveFontResourceExA (GDI32.@)
3616 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3618 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3619 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3622 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3623 ret = RemoveFontResourceExW(strW, fl, pdv);
3624 HeapFree(GetProcessHeap(), 0, strW);
3628 /***********************************************************************
3629 * RemoveFontResourceExW (GDI32.@)
3631 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3633 return WineEngRemoveFontResourceEx(str, fl, pdv);
3636 /***********************************************************************
3637 * GetTextCharset (GDI32.@)
3639 UINT WINAPI GetTextCharset(HDC hdc)
3641 /* MSDN docs say this is equivalent */
3642 return GetTextCharsetInfo(hdc, NULL, 0);
3645 /***********************************************************************
3646 * GetTextCharsetInfo (GDI32.@)
3648 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3650 UINT ret = DEFAULT_CHARSET;
3651 DC *dc = get_dc_ptr(hdc);
3656 dev = GET_DC_PHYSDEV( dc, pGetTextCharsetInfo );
3657 ret = dev->funcs->pGetTextCharsetInfo( dev, fs, flags );
3658 release_dc_ptr( dc );
3661 if (ret == DEFAULT_CHARSET && fs)
3662 memset(fs, 0, sizeof(FONTSIGNATURE));
3666 /***********************************************************************
3667 * GdiGetCharDimensions (GDI32.@)
3669 * Gets the average width of the characters in the English alphabet.
3672 * hdc [I] Handle to the device context to measure on.
3673 * lptm [O] Pointer to memory to store the text metrics into.
3674 * height [O] On exit, the maximum height of characters in the English alphabet.
3677 * The average width of characters in the English alphabet.
3680 * This function is used by the dialog manager to get the size of a dialog
3681 * unit. It should also be used by other pieces of code that need to know
3682 * the size of a dialog unit in logical units without having access to the
3683 * window handle of the dialog.
3684 * Windows caches the font metrics from this function, but we don't and
3685 * there doesn't appear to be an immediate advantage to do so.
3688 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3690 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3693 static const WCHAR alphabet[] = {
3694 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3695 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3696 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3698 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3700 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3702 if (height) *height = sz.cy;
3703 return (sz.cx / 26 + 1) / 2;
3706 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3708 FIXME("(%d): stub\n", fEnableEUDC);
3712 /***********************************************************************
3713 * GetCharWidthI (GDI32.@)
3715 * Retrieve widths of characters.
3718 * hdc [I] Handle to a device context.
3719 * first [I] First glyph in range to query.
3720 * count [I] Number of glyph indices to query.
3721 * glyphs [I] Array of glyphs to query.
3722 * buffer [O] Buffer to receive character widths.
3725 * Only works with TrueType fonts.
3731 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3736 TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3738 if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3741 if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3743 HeapFree(GetProcessHeap(), 0, abc);
3747 for (i = 0; i < count; i++)
3748 buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3750 HeapFree(GetProcessHeap(), 0, abc);
3754 /***********************************************************************
3755 * GetFontUnicodeRanges (GDI32.@)
3757 * Retrieve a list of supported Unicode characters in a font.
3760 * hdc [I] Handle to a device context.
3761 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3764 * Success: Number of bytes written to the buffer pointed to by lpgs.
3768 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3772 DC *dc = get_dc_ptr(hdc);
3774 TRACE("(%p, %p)\n", hdc, lpgs);
3778 dev = GET_DC_PHYSDEV( dc, pGetFontUnicodeRanges );
3779 ret = dev->funcs->pGetFontUnicodeRanges( dev, lpgs );
3785 /*************************************************************
3786 * FontIsLinked (GDI32.@)
3788 BOOL WINAPI FontIsLinked(HDC hdc)
3790 DC *dc = get_dc_ptr(hdc);
3794 if (!dc) return FALSE;
3795 dev = GET_DC_PHYSDEV( dc, pFontIsLinked );
3796 ret = dev->funcs->pFontIsLinked( dev );
3798 TRACE("returning %d\n", ret);
3802 /*************************************************************
3803 * GdiRealizationInfo (GDI32.@)
3805 * Returns a structure that contains some font information.
3807 BOOL WINAPI GdiRealizationInfo(HDC hdc, realization_info_t *info)
3809 DC *dc = get_dc_ptr(hdc);
3813 if (!dc) return FALSE;
3814 dev = GET_DC_PHYSDEV( dc, pGdiRealizationInfo );
3815 ret = dev->funcs->pGdiRealizationInfo( dev, info );