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"
34 #include "gdi_private.h"
35 #include "wine/exception.h"
36 #include "wine/unicode.h"
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(font);
41 /* Device -> World size conversion */
43 /* Performs a device to world transformation on the specified width (which
44 * is in integer format).
46 static inline INT INTERNAL_XDSTOWS(DC *dc, INT width)
50 /* Perform operation with floating point */
51 floatWidth = (double)width * dc->xformVport2World.eM11;
52 /* Round to integers */
53 return GDI_ROUND(floatWidth);
56 /* Performs a device to world transformation on the specified size (which
57 * is in integer format).
59 static inline INT INTERNAL_YDSTOWS(DC *dc, INT height)
63 /* Perform operation with floating point */
64 floatHeight = (double)height * dc->xformVport2World.eM22;
65 /* Round to integers */
66 return GDI_ROUND(floatHeight);
69 static inline INT INTERNAL_XWSTODS(DC *dc, INT width)
72 pt[0].x = pt[0].y = 0;
75 LPtoDP(dc->hSelf, pt, 2);
76 return pt[1].x - pt[0].x;
79 static inline INT INTERNAL_YWSTODS(DC *dc, INT height)
82 pt[0].x = pt[0].y = 0;
85 LPtoDP(dc->hSelf, pt, 2);
86 return pt[1].y - pt[0].y;
89 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc );
90 static INT FONT_GetObjectA( HGDIOBJ handle, INT count, LPVOID buffer );
91 static INT FONT_GetObjectW( HGDIOBJ handle, INT count, LPVOID buffer );
92 static BOOL FONT_DeleteObject( HGDIOBJ handle );
94 static const struct gdi_obj_funcs font_funcs =
96 FONT_SelectObject, /* pSelectObject */
97 FONT_GetObjectA, /* pGetObjectA */
98 FONT_GetObjectW, /* pGetObjectW */
99 NULL, /* pUnrealizeObject */
100 FONT_DeleteObject /* pDeleteObject */
103 #define ENUM_UNICODE 0x00000001
104 #define ENUM_CALLED 0x00000002
114 LPLOGFONTW lpLogFontParam;
115 FONTENUMPROCW lpEnumFunc;
122 * For TranslateCharsetInfo
124 #define MAXTCIINDEX 32
125 static const CHARSETINFO FONT_tci[MAXTCIINDEX] = {
127 { ANSI_CHARSET, 1252, {{0,0,0,0},{FS_LATIN1,0}} },
128 { EASTEUROPE_CHARSET, 1250, {{0,0,0,0},{FS_LATIN2,0}} },
129 { RUSSIAN_CHARSET, 1251, {{0,0,0,0},{FS_CYRILLIC,0}} },
130 { GREEK_CHARSET, 1253, {{0,0,0,0},{FS_GREEK,0}} },
131 { TURKISH_CHARSET, 1254, {{0,0,0,0},{FS_TURKISH,0}} },
132 { HEBREW_CHARSET, 1255, {{0,0,0,0},{FS_HEBREW,0}} },
133 { ARABIC_CHARSET, 1256, {{0,0,0,0},{FS_ARABIC,0}} },
134 { BALTIC_CHARSET, 1257, {{0,0,0,0},{FS_BALTIC,0}} },
135 { VIETNAMESE_CHARSET, 1258, {{0,0,0,0},{FS_VIETNAMESE,0}} },
136 /* reserved by ANSI */
137 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
138 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
139 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
140 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
141 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
142 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
143 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
145 { THAI_CHARSET, 874, {{0,0,0,0},{FS_THAI,0}} },
146 { SHIFTJIS_CHARSET, 932, {{0,0,0,0},{FS_JISJAPAN,0}} },
147 { GB2312_CHARSET, 936, {{0,0,0,0},{FS_CHINESESIMP,0}} },
148 { HANGEUL_CHARSET, 949, {{0,0,0,0},{FS_WANSUNG,0}} },
149 { CHINESEBIG5_CHARSET, 950, {{0,0,0,0},{FS_CHINESETRAD,0}} },
150 { JOHAB_CHARSET, 1361, {{0,0,0,0},{FS_JOHAB,0}} },
151 /* reserved for alternate ANSI and OEM */
152 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
153 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
154 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
155 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
156 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
157 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
158 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
159 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
160 /* reserved for system */
161 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
162 { SYMBOL_CHARSET, CP_SYMBOL, {{0,0,0,0},{FS_SYMBOL,0}} }
165 static void FONT_LogFontAToW( const LOGFONTA *fontA, LPLOGFONTW fontW )
167 memcpy(fontW, fontA, sizeof(LOGFONTA) - LF_FACESIZE);
168 MultiByteToWideChar(CP_ACP, 0, fontA->lfFaceName, -1, fontW->lfFaceName,
170 fontW->lfFaceName[LF_FACESIZE-1] = 0;
173 static void FONT_LogFontWToA( const LOGFONTW *fontW, LPLOGFONTA fontA )
175 memcpy(fontA, fontW, sizeof(LOGFONTA) - LF_FACESIZE);
176 WideCharToMultiByte(CP_ACP, 0, fontW->lfFaceName, -1, fontA->lfFaceName,
177 LF_FACESIZE, NULL, NULL);
178 fontA->lfFaceName[LF_FACESIZE-1] = 0;
181 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEXA fontA )
183 FONT_LogFontWToA( &fontW->elfLogFont, &fontA->elfLogFont );
185 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
186 (LPSTR) fontA->elfFullName, LF_FULLFACESIZE, NULL, NULL );
187 fontA->elfFullName[LF_FULLFACESIZE-1] = '\0';
188 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
189 (LPSTR) fontA->elfStyle, LF_FACESIZE, NULL, NULL );
190 fontA->elfStyle[LF_FACESIZE-1] = '\0';
191 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
192 (LPSTR) fontA->elfScript, LF_FACESIZE, NULL, NULL );
193 fontA->elfScript[LF_FACESIZE-1] = '\0';
196 static void FONT_EnumLogFontExAToW( const ENUMLOGFONTEXA *fontA, LPENUMLOGFONTEXW fontW )
198 FONT_LogFontAToW( &fontA->elfLogFont, &fontW->elfLogFont );
200 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfFullName, -1,
201 fontW->elfFullName, LF_FULLFACESIZE );
202 fontW->elfFullName[LF_FULLFACESIZE-1] = '\0';
203 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfStyle, -1,
204 fontW->elfStyle, LF_FACESIZE );
205 fontW->elfStyle[LF_FACESIZE-1] = '\0';
206 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfScript, -1,
207 fontW->elfScript, LF_FACESIZE );
208 fontW->elfScript[LF_FACESIZE-1] = '\0';
211 /***********************************************************************
212 * TEXTMETRIC conversion functions.
214 static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
216 ptmA->tmHeight = ptmW->tmHeight;
217 ptmA->tmAscent = ptmW->tmAscent;
218 ptmA->tmDescent = ptmW->tmDescent;
219 ptmA->tmInternalLeading = ptmW->tmInternalLeading;
220 ptmA->tmExternalLeading = ptmW->tmExternalLeading;
221 ptmA->tmAveCharWidth = ptmW->tmAveCharWidth;
222 ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth;
223 ptmA->tmWeight = ptmW->tmWeight;
224 ptmA->tmOverhang = ptmW->tmOverhang;
225 ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX;
226 ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
227 ptmA->tmFirstChar = min(ptmW->tmFirstChar, 255);
228 if (ptmW->tmCharSet == SYMBOL_CHARSET)
230 ptmA->tmFirstChar = 0x1e;
231 ptmA->tmLastChar = 0xff; /* win9x behaviour - we need the OS2 table data to calculate correctly */
233 else if (ptmW->tmPitchAndFamily & TMPF_TRUETYPE)
235 ptmA->tmFirstChar = ptmW->tmDefaultChar - 1;
236 ptmA->tmLastChar = min(ptmW->tmLastChar, 0xff);
240 ptmA->tmFirstChar = min(ptmW->tmFirstChar, 0xff);
241 ptmA->tmLastChar = min(ptmW->tmLastChar, 0xff);
243 ptmA->tmDefaultChar = ptmW->tmDefaultChar;
244 ptmA->tmBreakChar = ptmW->tmBreakChar;
245 ptmA->tmItalic = ptmW->tmItalic;
246 ptmA->tmUnderlined = ptmW->tmUnderlined;
247 ptmA->tmStruckOut = ptmW->tmStruckOut;
248 ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
249 ptmA->tmCharSet = ptmW->tmCharSet;
253 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW *ptmW, NEWTEXTMETRICEXA *ptmA )
255 FONT_TextMetricWToA((const TEXTMETRICW *)ptmW, (LPTEXTMETRICA)ptmA);
256 ptmA->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
257 ptmA->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
258 ptmA->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
259 ptmA->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
260 memcpy(&ptmA->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
264 /***********************************************************************
265 * GdiGetCodePage (GDI32.@)
267 DWORD WINAPI GdiGetCodePage( HDC hdc )
270 DC *dc = get_dc_ptr( hdc );
274 cp = dc->font_code_page;
275 release_dc_ptr( dc );
280 /***********************************************************************
283 * Returns a Unicode translation of str using the charset of the
284 * currently selected font in hdc. If count is -1 then str is assumed
285 * to be '\0' terminated, otherwise it contains the number of bytes to
286 * convert. If plenW is non-NULL, on return it will point to the
287 * number of WCHARs that have been written. If pCP is non-NULL, on
288 * return it will point to the codepage used in the conversion. The
289 * caller should free the returned LPWSTR from the process heap
292 static LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
298 cp = GdiGetCodePage( hdc );
300 if(count == -1) count = strlen(str);
301 lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
302 strW = HeapAlloc(GetProcessHeap(), 0, lenW*sizeof(WCHAR));
303 MultiByteToWideChar(cp, 0, str, count, strW, lenW);
304 TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW));
305 if(plenW) *plenW = lenW;
310 /***********************************************************************
311 * CreateFontIndirectExA (GDI32.@)
313 HFONT WINAPI CreateFontIndirectExA( const ENUMLOGFONTEXDVA *penumexA )
315 ENUMLOGFONTEXDVW enumexW;
317 if (!penumexA) return 0;
319 FONT_EnumLogFontExAToW( &penumexA->elfEnumLogfontEx, &enumexW.elfEnumLogfontEx );
320 enumexW.elfDesignVector = penumexA->elfDesignVector;
321 return CreateFontIndirectExW( &enumexW );
324 /***********************************************************************
325 * CreateFontIndirectExW (GDI32.@)
327 HFONT WINAPI CreateFontIndirectExW( const ENUMLOGFONTEXDVW *penumex )
333 if (!penumex) return 0;
335 if (penumex->elfEnumLogfontEx.elfFullName[0] ||
336 penumex->elfEnumLogfontEx.elfStyle[0] ||
337 penumex->elfEnumLogfontEx.elfScript[0])
339 FIXME("some fields ignored. fullname=%s, style=%s, script=%s\n",
340 debugstr_w(penumex->elfEnumLogfontEx.elfFullName),
341 debugstr_w(penumex->elfEnumLogfontEx.elfStyle),
342 debugstr_w(penumex->elfEnumLogfontEx.elfScript));
345 plf = &penumex->elfEnumLogfontEx.elfLogFont;
346 if (!(fontPtr = HeapAlloc( GetProcessHeap(), 0, sizeof(*fontPtr) ))) return 0;
348 fontPtr->logfont = *plf;
350 if (plf->lfEscapement != plf->lfOrientation)
352 /* this should really depend on whether GM_ADVANCED is set */
353 fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
354 WARN("orientation angle %f set to "
355 "escapement angle %f for new font %p\n",
356 plf->lfOrientation/10., plf->lfEscapement/10., fontPtr);
359 if (!(hFont = alloc_gdi_handle( &fontPtr->header, OBJ_FONT, &font_funcs )))
361 HeapFree( GetProcessHeap(), 0, fontPtr );
365 TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
366 plf->lfHeight, plf->lfWidth,
367 plf->lfEscapement, plf->lfOrientation,
368 plf->lfPitchAndFamily,
369 plf->lfOutPrecision, plf->lfClipPrecision,
370 plf->lfQuality, plf->lfCharSet,
371 debugstr_w(plf->lfFaceName),
372 plf->lfWeight > 400 ? "Bold" : "",
373 plf->lfItalic ? "Italic" : "",
374 plf->lfUnderline ? "Underline" : "", hFont);
379 /***********************************************************************
380 * CreateFontIndirectA (GDI32.@)
382 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *plfA )
388 FONT_LogFontAToW( plfA, &lfW );
389 return CreateFontIndirectW( &lfW );
392 /***********************************************************************
393 * CreateFontIndirectW (GDI32.@)
395 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
397 ENUMLOGFONTEXDVW exdv;
401 exdv.elfEnumLogfontEx.elfLogFont = *plf;
402 exdv.elfEnumLogfontEx.elfFullName[0] = 0;
403 exdv.elfEnumLogfontEx.elfStyle[0] = 0;
404 exdv.elfEnumLogfontEx.elfScript[0] = 0;
405 return CreateFontIndirectExW( &exdv );
408 /*************************************************************************
409 * CreateFontA (GDI32.@)
411 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
412 INT orient, INT weight, DWORD italic,
413 DWORD underline, DWORD strikeout, DWORD charset,
414 DWORD outpres, DWORD clippres, DWORD quality,
415 DWORD pitch, LPCSTR name )
419 logfont.lfHeight = height;
420 logfont.lfWidth = width;
421 logfont.lfEscapement = esc;
422 logfont.lfOrientation = orient;
423 logfont.lfWeight = weight;
424 logfont.lfItalic = italic;
425 logfont.lfUnderline = underline;
426 logfont.lfStrikeOut = strikeout;
427 logfont.lfCharSet = charset;
428 logfont.lfOutPrecision = outpres;
429 logfont.lfClipPrecision = clippres;
430 logfont.lfQuality = quality;
431 logfont.lfPitchAndFamily = pitch;
434 lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
436 logfont.lfFaceName[0] = '\0';
438 return CreateFontIndirectA( &logfont );
441 /*************************************************************************
442 * CreateFontW (GDI32.@)
444 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
445 INT orient, INT weight, DWORD italic,
446 DWORD underline, DWORD strikeout, DWORD charset,
447 DWORD outpres, DWORD clippres, DWORD quality,
448 DWORD pitch, LPCWSTR name )
452 logfont.lfHeight = height;
453 logfont.lfWidth = width;
454 logfont.lfEscapement = esc;
455 logfont.lfOrientation = orient;
456 logfont.lfWeight = weight;
457 logfont.lfItalic = italic;
458 logfont.lfUnderline = underline;
459 logfont.lfStrikeOut = strikeout;
460 logfont.lfCharSet = charset;
461 logfont.lfOutPrecision = outpres;
462 logfont.lfClipPrecision = clippres;
463 logfont.lfQuality = quality;
464 logfont.lfPitchAndFamily = pitch;
467 lstrcpynW(logfont.lfFaceName, name,
468 sizeof(logfont.lfFaceName) / sizeof(WCHAR));
470 logfont.lfFaceName[0] = '\0';
472 return CreateFontIndirectW( &logfont );
475 static void update_font_code_page( DC *dc )
478 int charset = DEFAULT_CHARSET;
481 charset = WineEngGetTextCharsetInfo( dc->gdiFont, NULL, 0 );
483 /* Hmm, nicely designed api this one! */
484 if (TranslateCharsetInfo( ULongToPtr(charset), &csi, TCI_SRCCHARSET) )
485 dc->font_code_page = csi.ciACP;
489 dc->font_code_page = GetOEMCP();
491 case DEFAULT_CHARSET:
492 dc->font_code_page = GetACP();
502 /* FIXME: These have no place here, but because x11drv
503 enumerates fonts with these (made up) charsets some apps
504 might use them and then the FIXME below would become
505 annoying. Now we could pick the intended codepage for
506 each of these, but since it's broken anyway we'll just
507 use CP_ACP and hope it'll go away...
509 dc->font_code_page = CP_ACP;
513 FIXME("Can't find codepage for charset %d\n", charset);
514 dc->font_code_page = CP_ACP;
519 TRACE("charset %d => cp %d\n", charset, dc->font_code_page);
522 /***********************************************************************
525 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc )
528 DC *dc = get_dc_ptr( hdc );
533 if (!GDI_inc_ref_count( handle ))
535 release_dc_ptr( dc );
539 physdev = GET_DC_PHYSDEV( dc, pSelectFont );
540 if (physdev->funcs->pSelectFont( physdev, handle ))
544 update_font_code_page( dc );
545 GDI_dec_ref_count( ret );
547 else GDI_dec_ref_count( handle );
549 release_dc_ptr( dc );
554 /***********************************************************************
557 static INT FONT_GetObjectA( HGDIOBJ handle, INT count, LPVOID buffer )
559 FONTOBJ *font = GDI_GetObjPtr( handle, OBJ_FONT );
565 FONT_LogFontWToA( &font->logfont, &lfA );
566 if (count > sizeof(lfA)) count = sizeof(lfA);
567 memcpy( buffer, &lfA, count );
569 else count = sizeof(lfA);
570 GDI_ReleaseObj( handle );
574 /***********************************************************************
577 static INT FONT_GetObjectW( HGDIOBJ handle, INT count, LPVOID buffer )
579 FONTOBJ *font = GDI_GetObjPtr( handle, OBJ_FONT );
584 if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
585 memcpy( buffer, &font->logfont, count );
587 else count = sizeof(LOGFONTW);
588 GDI_ReleaseObj( handle );
593 /***********************************************************************
596 static BOOL FONT_DeleteObject( HGDIOBJ handle )
600 WineEngDestroyFontInstance( handle );
602 if (!(obj = free_gdi_handle( handle ))) return FALSE;
603 return HeapFree( GetProcessHeap(), 0, obj );
607 /***********************************************************************
610 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
611 * We have to use other types because of the FONTENUMPROCW definition.
613 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
614 DWORD fType, LPARAM lp )
616 fontEnum32 *pfe = (fontEnum32*)lp;
619 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
620 if ((!pfe->lpLogFontParam ||
621 pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
622 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
623 (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
625 /* convert font metrics */
626 ENUMLOGFONTEXA logfont;
627 NEWTEXTMETRICEXA tmA;
629 pfe->dwFlags |= ENUM_CALLED;
630 if (!(pfe->dwFlags & ENUM_UNICODE))
632 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
633 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
634 plf = (LOGFONTW *)&logfont.elfLogFont;
635 ptm = (TEXTMETRICW *)&tmA;
638 ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
643 /***********************************************************************
644 * FONT_EnumFontFamiliesEx
646 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf,
647 FONTENUMPROCW efproc,
648 LPARAM lParam, DWORD dwUnicode)
651 DC *dc = get_dc_ptr( hDC );
658 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName),
660 fe32.lpLogFontParam = plf;
661 fe32.lpEnumFunc = efproc;
662 fe32.lpData = lParam;
663 fe32.dwFlags = dwUnicode;
666 enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE;
669 ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
670 fe32.dwFlags &= ~ENUM_CALLED;
673 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pEnumDeviceFonts );
674 ret2 = physdev->funcs->pEnumDeviceFonts( physdev, plf, FONT_EnumInstance, (LPARAM)&fe32 );
675 if(fe32.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
678 release_dc_ptr( dc );
682 /***********************************************************************
683 * EnumFontFamiliesExW (GDI32.@)
685 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
686 FONTENUMPROCW efproc,
687 LPARAM lParam, DWORD dwFlags )
689 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, ENUM_UNICODE );
692 /***********************************************************************
693 * EnumFontFamiliesExA (GDI32.@)
695 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
696 FONTENUMPROCA efproc,
697 LPARAM lParam, DWORD dwFlags)
703 FONT_LogFontAToW( plf, &lfW );
708 return FONT_EnumFontFamiliesEx( hDC, plfW, (FONTENUMPROCW)efproc, lParam, 0);
711 /***********************************************************************
712 * EnumFontFamiliesA (GDI32.@)
714 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
715 FONTENUMPROCA efproc, LPARAM lpData )
721 if (!*lpFamily) return 1;
722 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
723 lf.lfCharSet = DEFAULT_CHARSET;
724 lf.lfPitchAndFamily = 0;
729 return EnumFontFamiliesExA( hDC, plf, efproc, lpData, 0 );
732 /***********************************************************************
733 * EnumFontFamiliesW (GDI32.@)
735 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
736 FONTENUMPROCW efproc, LPARAM lpData )
742 if (!*lpFamily) return 1;
743 lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
744 lf.lfCharSet = DEFAULT_CHARSET;
745 lf.lfPitchAndFamily = 0;
750 return EnumFontFamiliesExW( hDC, plf, efproc, lpData, 0 );
753 /***********************************************************************
754 * EnumFontsA (GDI32.@)
756 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
759 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
762 /***********************************************************************
763 * EnumFontsW (GDI32.@)
765 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
768 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
772 /***********************************************************************
773 * GetTextCharacterExtra (GDI32.@)
775 INT WINAPI GetTextCharacterExtra( HDC hdc )
778 DC *dc = get_dc_ptr( hdc );
779 if (!dc) return 0x80000000;
781 release_dc_ptr( dc );
786 /***********************************************************************
787 * SetTextCharacterExtra (GDI32.@)
789 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
791 INT ret = 0x80000000;
792 DC * dc = get_dc_ptr( hdc );
796 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetTextCharacterExtra );
797 extra = physdev->funcs->pSetTextCharacterExtra( physdev, extra );
798 if (extra != 0x80000000)
801 dc->charExtra = extra;
803 release_dc_ptr( dc );
809 /***********************************************************************
810 * SetTextJustification (GDI32.@)
812 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
816 DC * dc = get_dc_ptr( hdc );
818 if (!dc) return FALSE;
820 physdev = GET_DC_PHYSDEV( dc, pSetTextJustification );
821 ret = physdev->funcs->pSetTextJustification( physdev, extra, breaks );
824 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
825 if (!extra) breaks = 0;
828 dc->breakExtra = extra / breaks;
829 dc->breakRem = extra - (breaks * dc->breakExtra);
837 release_dc_ptr( dc );
842 /***********************************************************************
843 * GetTextFaceA (GDI32.@)
845 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
847 INT res = GetTextFaceW(hdc, 0, NULL);
848 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
849 GetTextFaceW( hdc, res, nameW );
855 res = WideCharToMultiByte(CP_ACP, 0, nameW, -1, name, count, NULL, NULL);
859 /* GetTextFaceA does NOT include the nul byte in the return count. */
866 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
867 HeapFree( GetProcessHeap(), 0, nameW );
871 /***********************************************************************
872 * GetTextFaceW (GDI32.@)
874 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
879 DC * dc = get_dc_ptr( hdc );
883 ret = WineEngGetTextFace(dc->gdiFont, count, name);
884 else if ((font = GDI_GetObjPtr( dc->hFont, OBJ_FONT )))
886 INT n = strlenW(font->logfont.lfFaceName) + 1;
889 lstrcpynW( name, font->logfont.lfFaceName, count );
893 GDI_ReleaseObj( dc->hFont );
895 release_dc_ptr( dc );
900 /***********************************************************************
901 * GetTextExtentPoint32A (GDI32.@)
903 * See GetTextExtentPoint32W.
905 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
912 if (count < 0) return FALSE;
914 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
918 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
919 HeapFree( GetProcessHeap(), 0, p );
922 TRACE("(%p %s %d %p): returning %d x %d\n",
923 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
928 /***********************************************************************
929 * GetTextExtentPoint32W [GDI32.@]
931 * Computes width/height for a string.
933 * Computes width and height of the specified string.
939 BOOL WINAPI GetTextExtentPoint32W(
940 HDC hdc, /* [in] Handle of device context */
941 LPCWSTR str, /* [in] Address of text string */
942 INT count, /* [in] Number of characters in string */
943 LPSIZE size) /* [out] Address of structure for string size */
945 return GetTextExtentExPointW(hdc, str, count, 0, NULL, NULL, size);
948 /***********************************************************************
949 * GetTextExtentExPointI [GDI32.@]
951 * Computes width and height of the array of glyph indices.
954 * hdc [I] Handle of device context.
955 * indices [I] Glyph index array.
956 * count [I] Number of glyphs in array.
957 * max_ext [I] Maximum width in glyphs.
958 * nfit [O] Maximum number of characters.
959 * dxs [O] Partial string widths.
960 * size [O] Returned string size.
966 BOOL WINAPI GetTextExtentExPointI( HDC hdc, const WORD *indices, INT count, INT max_ext,
967 LPINT nfit, LPINT dxs, LPSIZE size )
972 if (count < 0) return FALSE;
974 dc = get_dc_ptr( hdc );
975 if (!dc) return FALSE;
979 ret = WineEngGetTextExtentExPointI(dc->gdiFont, indices, count, max_ext, nfit, dxs, size);
980 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
981 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
982 size->cx += count * dc->charExtra;
986 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pGetTextExtentExPoint );
987 FIXME("calling GetTextExtentExPoint\n");
988 ret = physdev->funcs->pGetTextExtentExPoint( physdev, indices, count, max_ext, nfit, dxs, size );
991 release_dc_ptr( dc );
993 TRACE("(%p %p %d %p): returning %d x %d\n",
994 hdc, indices, count, size, size->cx, size->cy );
998 /***********************************************************************
999 * GetTextExtentPointI [GDI32.@]
1001 * Computes width and height of the array of glyph indices.
1004 * hdc [I] Handle of device context.
1005 * indices [I] Glyph index array.
1006 * count [I] Number of glyphs in array.
1007 * size [O] Returned string size.
1013 BOOL WINAPI GetTextExtentPointI( HDC hdc, const WORD *indices, INT count, LPSIZE size )
1015 return GetTextExtentExPointI( hdc, indices, count, 0, NULL, NULL, size );
1019 /***********************************************************************
1020 * GetTextExtentPointA (GDI32.@)
1022 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
1025 TRACE("not bug compatible.\n");
1026 return GetTextExtentPoint32A( hdc, str, count, size );
1029 /***********************************************************************
1030 * GetTextExtentPointW (GDI32.@)
1032 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1035 TRACE("not bug compatible.\n");
1036 return GetTextExtentPoint32W( hdc, str, count, size );
1040 /***********************************************************************
1041 * GetTextExtentExPointA (GDI32.@)
1043 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1044 INT maxExt, LPINT lpnFit,
1045 LPINT alpDx, LPSIZE size )
1052 if (count < 0) return FALSE;
1056 walpDx = HeapAlloc( GetProcessHeap(), 0, count * sizeof(INT) );
1057 if (!walpDx) return FALSE;
1060 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1061 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
1064 INT n = lpnFit ? *lpnFit : wlen;
1066 for(i = 0, j = 0; i < n; i++, j++)
1068 alpDx[j] = walpDx[i];
1069 if (IsDBCSLeadByte(str[j])) alpDx[++j] = walpDx[i];
1072 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1073 HeapFree( GetProcessHeap(), 0, p );
1074 HeapFree( GetProcessHeap(), 0, walpDx );
1079 /***********************************************************************
1080 * GetTextExtentExPointW (GDI32.@)
1082 * Return the size of the string as it would be if it was output properly by
1085 * This should include
1086 * - Intercharacter spacing
1087 * - justification spacing (not yet done)
1088 * - kerning? see below
1090 * Kerning. Since kerning would be carried out by the rendering code it should
1091 * be done by the driver. However they don't support it yet. Also I am not
1092 * yet persuaded that (certainly under Win95) any kerning is actually done.
1094 * str: According to MSDN this should be null-terminated. That is not true; a
1095 * null will not terminate it early.
1096 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1097 * than count. I have seen it be either the size of the full string or
1098 * 1 less than the size of the full string. I have not seen it bear any
1099 * resemblance to the portion that would fit.
1100 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1101 * trailing intercharacter spacing and any trailing justification.
1104 * Currently we do this by measuring each character etc. We should do it by
1105 * passing the request to the driver, perhaps by extending the
1106 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1107 * thinking about kerning issues and rounding issues in the justification.
1110 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1111 INT maxExt, LPINT lpnFit,
1112 LPINT alpDx, LPSIZE size )
1121 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1123 if (count < 0) return FALSE;
1125 dc = get_dc_ptr(hdc);
1126 if (!dc) return FALSE;
1128 GetTextMetricsW(hdc, &tm);
1130 /* If we need to calculate nFit, then we need the partial extents even if
1131 the user hasn't provided us with an array. */
1134 dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]);
1138 SetLastError(ERROR_OUTOFMEMORY);
1145 dev = GET_DC_PHYSDEV( dc, pGetTextExtentExPoint );
1146 ret = dev->funcs->pGetTextExtentExPoint(dev, str, count, 0, NULL, dxs, size);
1148 /* Perform device size to world size transformations. */
1151 INT extra = dc->charExtra,
1152 breakExtra = dc->breakExtra,
1153 breakRem = dc->breakRem,
1158 for (i = 0; i < count; ++i)
1160 dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
1161 dxs[i] += (i+1) * extra;
1162 if (count > 1 && (breakExtra || breakRem) && str[i] == tm.tmBreakChar)
1164 dxs[i] += breakExtra;
1171 if (dxs[i] <= maxExt)
1174 breakRem = dc->breakRem;
1176 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1177 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1179 if (!dxs && count > 1 && (breakExtra || breakRem))
1181 for (i = 0; i < count; i++)
1183 if (str[i] == tm.tmBreakChar)
1185 size->cx += breakExtra;
1200 HeapFree(GetProcessHeap(), 0, dxs);
1202 release_dc_ptr( dc );
1204 TRACE("returning %d %d x %d\n",nFit,size->cx,size->cy);
1208 /***********************************************************************
1209 * GetTextMetricsA (GDI32.@)
1211 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1215 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1216 FONT_TextMetricWToA( &tm32, metrics );
1220 /***********************************************************************
1221 * GetTextMetricsW (GDI32.@)
1223 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1226 DC * dc = get_dc_ptr( hdc );
1227 if (!dc) return FALSE;
1230 ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1233 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pGetTextMetrics );
1234 ret = physdev->funcs->pGetTextMetrics( physdev, metrics );
1239 /* device layer returns values in device units
1240 * therefore we have to convert them to logical */
1242 metrics->tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1243 metrics->tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1245 #define WDPTOLP(x) ((x<0)? \
1246 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1247 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1248 #define HDPTOLP(y) ((y<0)? \
1249 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1250 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1252 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1253 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1254 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1255 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1256 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1257 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1258 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1259 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1263 TRACE("text metrics:\n"
1264 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1265 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1266 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1267 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1268 " PitchAndFamily = %02x\n"
1269 " --------------------\n"
1270 " InternalLeading = %i\n"
1274 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1275 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1276 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1277 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1278 metrics->tmPitchAndFamily,
1279 metrics->tmInternalLeading,
1282 metrics->tmHeight );
1284 release_dc_ptr( dc );
1289 /***********************************************************************
1290 * GetOutlineTextMetricsA (GDI32.@)
1291 * Gets metrics for TrueType fonts.
1294 * If the supplied buffer isn't big enough Windows partially fills it up to
1295 * its given length and returns that length.
1298 * Success: Non-zero or size of required buffer
1301 UINT WINAPI GetOutlineTextMetricsA(
1302 HDC hdc, /* [in] Handle of device context */
1303 UINT cbData, /* [in] Size of metric data array */
1304 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1306 char buf[512], *ptr;
1308 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1309 OUTLINETEXTMETRICA *output = lpOTM;
1312 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1314 if(ret > sizeof(buf))
1315 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1316 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1318 needed = sizeof(OUTLINETEXTMETRICA);
1319 if(lpOTMW->otmpFamilyName)
1320 needed += WideCharToMultiByte(CP_ACP, 0,
1321 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1322 NULL, 0, NULL, NULL);
1323 if(lpOTMW->otmpFaceName)
1324 needed += WideCharToMultiByte(CP_ACP, 0,
1325 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1326 NULL, 0, NULL, NULL);
1327 if(lpOTMW->otmpStyleName)
1328 needed += WideCharToMultiByte(CP_ACP, 0,
1329 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1330 NULL, 0, NULL, NULL);
1331 if(lpOTMW->otmpFullName)
1332 needed += WideCharToMultiByte(CP_ACP, 0,
1333 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1334 NULL, 0, NULL, NULL);
1341 TRACE("needed = %d\n", needed);
1343 /* Since the supplied buffer isn't big enough, we'll alloc one
1344 that is and memcpy the first cbData bytes into the lpOTM at
1346 output = HeapAlloc(GetProcessHeap(), 0, needed);
1348 ret = output->otmSize = min(needed, cbData);
1349 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1350 output->otmFiller = 0;
1351 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1352 output->otmfsSelection = lpOTMW->otmfsSelection;
1353 output->otmfsType = lpOTMW->otmfsType;
1354 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1355 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1356 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1357 output->otmEMSquare = lpOTMW->otmEMSquare;
1358 output->otmAscent = lpOTMW->otmAscent;
1359 output->otmDescent = lpOTMW->otmDescent;
1360 output->otmLineGap = lpOTMW->otmLineGap;
1361 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1362 output->otmsXHeight = lpOTMW->otmsXHeight;
1363 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1364 output->otmMacAscent = lpOTMW->otmMacAscent;
1365 output->otmMacDescent = lpOTMW->otmMacDescent;
1366 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1367 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1368 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1369 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1370 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1371 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1372 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1373 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1374 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1375 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1378 ptr = (char*)(output + 1);
1379 left = needed - sizeof(*output);
1381 if(lpOTMW->otmpFamilyName) {
1382 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1383 len = WideCharToMultiByte(CP_ACP, 0,
1384 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1385 ptr, left, NULL, NULL);
1389 output->otmpFamilyName = 0;
1391 if(lpOTMW->otmpFaceName) {
1392 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1393 len = WideCharToMultiByte(CP_ACP, 0,
1394 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1395 ptr, left, NULL, NULL);
1399 output->otmpFaceName = 0;
1401 if(lpOTMW->otmpStyleName) {
1402 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1403 len = WideCharToMultiByte(CP_ACP, 0,
1404 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1405 ptr, left, NULL, NULL);
1409 output->otmpStyleName = 0;
1411 if(lpOTMW->otmpFullName) {
1412 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1413 len = WideCharToMultiByte(CP_ACP, 0,
1414 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1415 ptr, left, NULL, NULL);
1418 output->otmpFullName = 0;
1422 if(output != lpOTM) {
1423 memcpy(lpOTM, output, cbData);
1424 HeapFree(GetProcessHeap(), 0, output);
1426 /* check if the string offsets really fit into the provided size */
1427 /* FIXME: should we check string length as well? */
1428 /* make sure that we don't read/write beyond the provided buffer */
1429 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(LPSTR))
1431 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1432 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1435 /* make sure that we don't read/write beyond the provided buffer */
1436 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(LPSTR))
1438 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1439 lpOTM->otmpFaceName = 0; /* doesn't fit */
1442 /* make sure that we don't read/write beyond the provided buffer */
1443 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(LPSTR))
1445 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1446 lpOTM->otmpStyleName = 0; /* doesn't fit */
1449 /* make sure that we don't read/write beyond the provided buffer */
1450 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(LPSTR))
1452 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1453 lpOTM->otmpFullName = 0; /* doesn't fit */
1458 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1459 HeapFree(GetProcessHeap(), 0, lpOTMW);
1465 /***********************************************************************
1466 * GetOutlineTextMetricsW [GDI32.@]
1468 UINT WINAPI GetOutlineTextMetricsW(
1469 HDC hdc, /* [in] Handle of device context */
1470 UINT cbData, /* [in] Size of metric data array */
1471 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1473 DC *dc = get_dc_ptr( hdc );
1474 OUTLINETEXTMETRICW *output = lpOTM;
1477 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1481 ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, output);
1484 output = HeapAlloc(GetProcessHeap(), 0, ret);
1485 WineEngGetOutlineTextMetrics(dc->gdiFont, ret, output);
1488 output->otmTextMetrics.tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1489 output->otmTextMetrics.tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1491 #define WDPTOLP(x) ((x<0)? \
1492 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1493 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1494 #define HDPTOLP(y) ((y<0)? \
1495 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1496 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1498 output->otmTextMetrics.tmHeight = HDPTOLP(output->otmTextMetrics.tmHeight);
1499 output->otmTextMetrics.tmAscent = HDPTOLP(output->otmTextMetrics.tmAscent);
1500 output->otmTextMetrics.tmDescent = HDPTOLP(output->otmTextMetrics.tmDescent);
1501 output->otmTextMetrics.tmInternalLeading = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1502 output->otmTextMetrics.tmExternalLeading = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1503 output->otmTextMetrics.tmAveCharWidth = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1504 output->otmTextMetrics.tmMaxCharWidth = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1505 output->otmTextMetrics.tmOverhang = WDPTOLP(output->otmTextMetrics.tmOverhang);
1506 output->otmAscent = HDPTOLP(output->otmAscent);
1507 output->otmDescent = HDPTOLP(output->otmDescent);
1508 output->otmLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmLineGap));
1509 output->otmsCapEmHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsCapEmHeight));
1510 output->otmsXHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsXHeight));
1511 output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1512 output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1513 output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1514 output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1515 output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1516 output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1517 output->otmMacLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmMacLineGap));
1518 output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1519 output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1520 output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1521 output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1522 output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1523 output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1524 output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1525 output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1526 output->otmsStrikeoutSize = abs(INTERNAL_YDSTOWS(dc,output->otmsStrikeoutSize));
1527 output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1528 output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1529 output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1532 if(output != lpOTM) {
1533 memcpy(lpOTM, output, cbData);
1534 HeapFree(GetProcessHeap(), 0, output);
1540 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1541 but really this should just be a return 0. */
1543 ret = sizeof(*lpOTM);
1548 memset(lpOTM, 0, ret);
1549 lpOTM->otmSize = sizeof(*lpOTM);
1550 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1552 Further fill of the structure not implemented,
1553 Needs real values for the structure members
1562 static LPSTR FONT_GetCharsByRangeA(HDC hdc, UINT firstChar, UINT lastChar, PINT pByteLen)
1564 INT i, count = lastChar - firstChar + 1;
1571 switch (GdiGetCodePage(hdc))
1578 if (lastChar > 0xffff)
1580 if ((firstChar ^ lastChar) > 0xff)
1584 if (lastChar > 0xff)
1589 str = HeapAlloc(GetProcessHeap(), 0, count * 2 + 1);
1593 for(i = 0, c = firstChar; c <= lastChar; i++, c++)
1596 str[i++] = (BYTE)(c >> 8);
1606 /***********************************************************************
1607 * GetCharWidthW (GDI32.@)
1608 * GetCharWidth32W (GDI32.@)
1610 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1616 DC * dc = get_dc_ptr( hdc );
1618 if (!dc) return FALSE;
1620 dev = GET_DC_PHYSDEV( dc, pGetCharWidth );
1621 ret = dev->funcs->pGetCharWidth( dev, firstChar, lastChar, buffer );
1625 /* convert device units to logical */
1626 for( i = firstChar; i <= lastChar; i++, buffer++ )
1627 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1629 release_dc_ptr( dc );
1634 /***********************************************************************
1635 * GetCharWidthA (GDI32.@)
1636 * GetCharWidth32A (GDI32.@)
1638 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1646 str = FONT_GetCharsByRangeA(hdc, firstChar, lastChar, &i);
1650 wstr = FONT_mbtowc(hdc, str, i, &wlen, NULL);
1652 for(i = 0; i < wlen; i++)
1654 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1662 HeapFree(GetProcessHeap(), 0, str);
1663 HeapFree(GetProcessHeap(), 0, wstr);
1669 /***********************************************************************
1670 * ExtTextOutA (GDI32.@)
1674 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1675 const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1683 if (flags & ETO_GLYPH_INDEX)
1684 return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
1686 p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
1689 unsigned int i = 0, j = 0;
1691 /* allocate enough for a ETO_PDY */
1692 lpDxW = HeapAlloc( GetProcessHeap(), 0, 2*wlen*sizeof(INT));
1694 if(IsDBCSLeadByteEx(codepage, str[i]))
1698 lpDxW[j++] = lpDx[i * 2] + lpDx[(i + 1) * 2];
1699 lpDxW[j++] = lpDx[i * 2 + 1] + lpDx[(i + 1) * 2 + 1];
1702 lpDxW[j++] = lpDx[i] + lpDx[i + 1];
1709 lpDxW[j++] = lpDx[i * 2];
1710 lpDxW[j++] = lpDx[i * 2 + 1];
1713 lpDxW[j++] = lpDx[i];
1719 ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1721 HeapFree( GetProcessHeap(), 0, p );
1722 HeapFree( GetProcessHeap(), 0, lpDxW );
1727 /***********************************************************************
1728 * ExtTextOutW (GDI32.@)
1730 * Draws text using the currently selected font, background color, and text color.
1734 * x,y [I] coordinates of string
1736 * ETO_GRAYED - undocumented on MSDN
1737 * ETO_OPAQUE - use background color for fill the rectangle
1738 * ETO_CLIPPED - clipping text to the rectangle
1739 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1740 * than encoded characters. Implies ETO_IGNORELANGUAGE
1741 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1742 * Affects BiDi ordering
1743 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1744 * ETO_PDY - unimplemented
1745 * ETO_NUMERICSLATIN - unimplemented always assumed -
1746 * do not translate numbers into locale representations
1747 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1748 * lprect [I] dimensions for clipping or/and opaquing
1749 * str [I] text string
1750 * count [I] number of symbols in string
1751 * lpDx [I] optional parameter with distance between drawing characters
1757 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1758 const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1761 LPWSTR reordered_str = (LPWSTR)str;
1762 WORD *glyphs = NULL;
1763 UINT align = GetTextAlign( hdc );
1764 DWORD layout = GetLayout( hdc );
1768 double cosEsc, sinEsc;
1772 BOOL done_extents = FALSE;
1773 POINT *deltas = NULL, width = {0, 0};
1775 DC * dc = get_dc_ptr( hdc );
1778 static int quietfixme = 0;
1780 if (!dc) return FALSE;
1782 breakRem = dc->breakRem;
1784 if (quietfixme == 0 && flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN))
1786 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN unimplemented\n");
1791 physdev = GET_DC_PHYSDEV( dc, pExtTextOut );
1792 type = GetObjectType(hdc);
1793 if(type == OBJ_METADC || type == OBJ_ENHMETADC)
1795 ret = physdev->funcs->pExtTextOut( physdev, x, y, flags, lprect, str, count, lpDx );
1796 release_dc_ptr( dc );
1801 flags &= ~ETO_CLIPPED;
1803 if (flags & ETO_RTLREADING) align |= TA_RTLREADING;
1804 if (layout & LAYOUT_RTL)
1806 if ((align & TA_CENTER) != TA_CENTER) align ^= TA_RIGHT;
1807 align ^= TA_RTLREADING;
1810 if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && count > 0 )
1813 reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1815 BIDI_Reorder( hdc, str, count, GCP_REORDER,
1816 (align & TA_RTLREADING) ? WINE_GCPW_FORCE_RTL : WINE_GCPW_FORCE_LTR,
1817 reordered_str, count, NULL, &glyphs, &cGlyphs);
1819 flags |= ETO_IGNORELANGUAGE;
1822 flags |= ETO_GLYPH_INDEX;
1823 if (cGlyphs != count)
1827 else if(flags & ETO_GLYPH_INDEX)
1828 glyphs = reordered_str;
1830 TRACE("%p, %d, %d, %08x, %s, %s, %d, %p)\n", hdc, x, y, flags,
1831 wine_dbgstr_rect(lprect), debugstr_wn(str, count), count, lpDx);
1832 TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
1834 if(align & TA_UPDATECP)
1836 GetCurrentPositionEx( hdc, &pt );
1841 GetTextMetricsW(hdc, &tm);
1842 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1844 if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
1845 lf.lfEscapement = 0;
1847 if(lf.lfEscapement != 0)
1849 cosEsc = cos(lf.lfEscapement * M_PI / 1800);
1850 sinEsc = sin(lf.lfEscapement * M_PI / 1800);
1858 if(flags & (ETO_CLIPPED | ETO_OPAQUE))
1862 if(flags & ETO_GLYPH_INDEX)
1863 GetTextExtentPointI(hdc, glyphs, count, &sz);
1865 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1867 done_extents = TRUE;
1870 rc.right = x + sz.cx;
1871 rc.bottom = y + sz.cy;
1878 LPtoDP(hdc, (POINT*)&rc, 2);
1880 if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
1881 if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
1884 if ((flags & ETO_OPAQUE) && !PATH_IsPathOpen(dc->path))
1885 physdev->funcs->pExtTextOut( physdev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL );
1895 LPtoDP(hdc, &pt, 1);
1899 char_extra = GetTextCharacterExtra(hdc);
1900 if(char_extra || dc->breakExtra || breakRem || lpDx || lf.lfEscapement != 0)
1904 POINT total = {0, 0}, desired[2];
1906 deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
1907 for(i = 0; i < count; i++)
1913 deltas[i].x = lpDx[i * 2] + char_extra;
1914 deltas[i].y = -lpDx[i * 2 + 1];
1918 deltas[i].x = lpDx[i] + char_extra;
1925 if(flags & ETO_GLYPH_INDEX)
1926 GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
1928 GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
1930 deltas[i].x = tmpsz.cx;
1934 if (!(flags & ETO_GLYPH_INDEX) && (dc->breakExtra || breakRem) && reordered_str[i] == tm.tmBreakChar)
1936 deltas[i].x = deltas[i].x + dc->breakExtra;
1943 total.x += deltas[i].x;
1944 total.y += deltas[i].y;
1946 desired[0].x = desired[0].y = 0;
1948 desired[1].x = cosEsc * total.x + sinEsc * total.y;
1949 desired[1].y = -sinEsc * total.x + cosEsc * total.y;
1951 LPtoDP(hdc, desired, 2);
1952 desired[1].x -= desired[0].x;
1953 desired[1].y -= desired[0].y;
1954 if (layout & LAYOUT_RTL) desired[1].x = -desired[1].x;
1956 deltas[i].x = desired[1].x - width.x;
1957 deltas[i].y = desired[1].y - width.y;
1967 if(flags & ETO_GLYPH_INDEX)
1968 GetTextExtentPointI(hdc, glyphs, count, &sz);
1970 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1971 done_extents = TRUE;
1973 width.x = abs(INTERNAL_XWSTODS(dc, sz.cx));
1977 tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
1978 tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
1979 switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
1982 if (align & TA_UPDATECP)
1986 DPtoLP(hdc, &pt, 1);
1987 MoveToEx(hdc, pt.x, pt.y, NULL);
1999 if (align & TA_UPDATECP)
2003 DPtoLP(hdc, &pt, 1);
2004 MoveToEx(hdc, pt.x, pt.y, NULL);
2009 switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
2012 y += tm.tmAscent * cosEsc;
2013 x += tm.tmAscent * sinEsc;
2017 y -= tm.tmDescent * cosEsc;
2018 x -= tm.tmDescent * sinEsc;
2025 if (GetBkMode(hdc) != TRANSPARENT && !PATH_IsPathOpen(dc->path))
2027 if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
2029 if(!(flags & ETO_OPAQUE) || x < rc.left || x + width.x >= rc.right ||
2030 y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
2034 rc.right = x + width.x;
2035 rc.top = y - tm.tmAscent;
2036 rc.bottom = y + tm.tmDescent;
2038 if(flags & ETO_CLIPPED)
2040 rc.left = max(lprect->left, rc.left);
2041 rc.right = min(lprect->right, rc.right);
2042 rc.top = max(lprect->top, rc.top);
2043 rc.bottom = min(lprect->bottom, rc.bottom);
2045 if(rc.left < rc.right && rc.top < rc.bottom)
2046 physdev->funcs->pExtTextOut( physdev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL );
2051 if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
2053 HFONT orig_font = dc->hFont, cur_font;
2056 POINT *offsets = NULL;
2059 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2060 for(i = 0; i < count; i++)
2062 WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
2063 if(cur_font != dc->hFont)
2068 offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
2069 offsets[0].x = offsets[0].y = 0;
2074 for(j = 1; j < count; j++)
2076 GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
2077 offsets[j].x = offsets[j - 1].x + abs(INTERNAL_XWSTODS(dc, tmpsz.cx));
2083 for(j = 1; j < count; j++)
2085 offsets[j].x = offsets[j - 1].x + deltas[j].x;
2086 offsets[j].y = offsets[j - 1].y + deltas[j].y;
2092 if (PATH_IsPathOpen(dc->path))
2093 ret = PATH_ExtTextOut(dc, x + offsets[i - span].x, y + offsets[i - span].y,
2094 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2095 glyphs, span, deltas ? (INT*)(deltas + (i - span)) : NULL);
2097 physdev->funcs->pExtTextOut( physdev, x + offsets[i - span].x,
2098 y + offsets[i - span].y,
2099 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc, glyphs,
2100 span, deltas ? (INT*)(deltas + (i - span)) : NULL);
2103 SelectObject(hdc, cur_font);
2105 glyphs[span++] = glyph;
2109 if (PATH_IsPathOpen(dc->path))
2110 ret = PATH_ExtTextOut(dc, x + (offsets ? offsets[count - span].x : 0),
2111 y + (offsets ? offsets[count - span].y : 0),
2112 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2113 glyphs, span, deltas ? (INT*)(deltas + (count - span)) : NULL);
2115 ret = physdev->funcs->pExtTextOut(physdev, x + (offsets ? offsets[count - span].x : 0),
2116 y + (offsets ? offsets[count - span].y : 0),
2117 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc, glyphs,
2118 span, deltas ? (INT*)(deltas + (count - span)) : NULL);
2119 SelectObject(hdc, orig_font);
2120 HeapFree(GetProcessHeap(), 0, offsets);
2126 if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
2128 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2129 GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
2130 flags |= ETO_GLYPH_INDEX;
2133 if (PATH_IsPathOpen(dc->path))
2134 ret = PATH_ExtTextOut(dc, x, y, (flags & ~ETO_OPAQUE), &rc,
2135 glyphs ? glyphs : reordered_str, count, (INT*)deltas);
2137 ret = physdev->funcs->pExtTextOut( physdev, x, y, (flags & ~ETO_OPAQUE), &rc,
2138 glyphs ? glyphs : reordered_str, count, (INT*)deltas );
2142 HeapFree(GetProcessHeap(), 0, deltas);
2143 if(glyphs != reordered_str)
2144 HeapFree(GetProcessHeap(), 0, glyphs);
2145 if(reordered_str != str)
2146 HeapFree(GetProcessHeap(), 0, reordered_str);
2148 release_dc_ptr( dc );
2150 if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2152 int underlinePos, strikeoutPos;
2153 int underlineWidth, strikeoutWidth;
2154 UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2155 OUTLINETEXTMETRICW* otm = NULL;
2160 underlineWidth = tm.tmAscent / 20 + 1;
2161 strikeoutPos = tm.tmAscent / 2;
2162 strikeoutWidth = underlineWidth;
2166 otm = HeapAlloc(GetProcessHeap(), 0, size);
2167 GetOutlineTextMetricsW(hdc, size, otm);
2168 underlinePos = otm->otmsUnderscorePosition;
2169 underlineWidth = otm->otmsUnderscoreSize;
2170 strikeoutPos = otm->otmsStrikeoutPosition;
2171 strikeoutWidth = otm->otmsStrikeoutSize;
2172 HeapFree(GetProcessHeap(), 0, otm);
2175 if (PATH_IsPathOpen(dc->path))
2179 HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2181 hbrush = SelectObject(hdc, hbrush);
2182 hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2186 pts[0].x = x - underlinePos * sinEsc;
2187 pts[0].y = y - underlinePos * cosEsc;
2188 pts[1].x = x + width.x - underlinePos * sinEsc;
2189 pts[1].y = y + width.y - underlinePos * cosEsc;
2190 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2191 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2192 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2193 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2194 pts[4].x = pts[0].x;
2195 pts[4].y = pts[0].y;
2196 DPtoLP(hdc, pts, 5);
2197 Polygon(hdc, pts, 5);
2202 pts[0].x = x - strikeoutPos * sinEsc;
2203 pts[0].y = y - strikeoutPos * cosEsc;
2204 pts[1].x = x + width.x - strikeoutPos * sinEsc;
2205 pts[1].y = y + width.y - strikeoutPos * cosEsc;
2206 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2207 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2208 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2209 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2210 pts[4].x = pts[0].x;
2211 pts[4].y = pts[0].y;
2212 DPtoLP(hdc, pts, 5);
2213 Polygon(hdc, pts, 5);
2216 SelectObject(hdc, hpen);
2217 hbrush = SelectObject(hdc, hbrush);
2218 DeleteObject(hbrush);
2222 POINT pts[2], oldpt;
2227 hpen = CreatePen(PS_SOLID, underlineWidth, GetTextColor(hdc));
2228 hpen = SelectObject(hdc, hpen);
2231 pts[1].x = x + width.x;
2232 pts[1].y = y + width.y;
2233 DPtoLP(hdc, pts, 2);
2234 MoveToEx(hdc, pts[0].x - underlinePos * sinEsc, pts[0].y - underlinePos * cosEsc, &oldpt);
2235 LineTo(hdc, pts[1].x - underlinePos * sinEsc, pts[1].y - underlinePos * cosEsc);
2236 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2237 DeleteObject(SelectObject(hdc, hpen));
2242 hpen = CreatePen(PS_SOLID, strikeoutWidth, GetTextColor(hdc));
2243 hpen = SelectObject(hdc, hpen);
2246 pts[1].x = x + width.x;
2247 pts[1].y = y + width.y;
2248 DPtoLP(hdc, pts, 2);
2249 MoveToEx(hdc, pts[0].x - strikeoutPos * sinEsc, pts[0].y - strikeoutPos * cosEsc, &oldpt);
2250 LineTo(hdc, pts[1].x - strikeoutPos * sinEsc, pts[1].y - strikeoutPos * cosEsc);
2251 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2252 DeleteObject(SelectObject(hdc, hpen));
2261 /***********************************************************************
2262 * TextOutA (GDI32.@)
2264 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2266 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2270 /***********************************************************************
2271 * TextOutW (GDI32.@)
2273 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2275 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2279 /***********************************************************************
2280 * PolyTextOutA (GDI32.@)
2284 BOOL WINAPI PolyTextOutA( HDC hdc, const POLYTEXTA *pptxt, INT cStrings )
2286 for (; cStrings>0; cStrings--, pptxt++)
2287 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2294 /***********************************************************************
2295 * PolyTextOutW (GDI32.@)
2297 * Draw several Strings
2303 BOOL WINAPI PolyTextOutW( HDC hdc, const POLYTEXTW *pptxt, INT cStrings )
2305 for (; cStrings>0; cStrings--, pptxt++)
2306 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2312 /***********************************************************************
2313 * SetMapperFlags (GDI32.@)
2315 DWORD WINAPI SetMapperFlags( HDC hdc, DWORD flags )
2317 DC *dc = get_dc_ptr( hdc );
2318 DWORD ret = GDI_ERROR;
2322 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetMapperFlags );
2323 flags = physdev->funcs->pSetMapperFlags( physdev, flags );
2324 if (flags != GDI_ERROR)
2326 ret = dc->mapperFlags;
2327 dc->mapperFlags = flags;
2329 release_dc_ptr( dc );
2334 /***********************************************************************
2335 * GetAspectRatioFilterEx (GDI32.@)
2337 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2339 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2344 /***********************************************************************
2345 * GetCharABCWidthsA (GDI32.@)
2347 * See GetCharABCWidthsW.
2349 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2357 str = FONT_GetCharsByRangeA(hdc, firstChar, lastChar, &i);
2361 wstr = FONT_mbtowc(hdc, str, i, &wlen, NULL);
2364 HeapFree(GetProcessHeap(), 0, str);
2368 for(i = 0; i < wlen; i++)
2370 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2378 HeapFree(GetProcessHeap(), 0, str);
2379 HeapFree(GetProcessHeap(), 0, wstr);
2385 /******************************************************************************
2386 * GetCharABCWidthsW [GDI32.@]
2388 * Retrieves widths of characters in range.
2391 * hdc [I] Handle of device context
2392 * firstChar [I] First character in range to query
2393 * lastChar [I] Last character in range to query
2394 * abc [O] Address of character-width structure
2397 * Only works with TrueType fonts
2403 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2406 DC *dc = get_dc_ptr(hdc);
2410 if (!dc) return FALSE;
2414 release_dc_ptr( dc );
2419 ret = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
2425 /* convert device units to logical */
2426 for( i = firstChar; i <= lastChar; i++, abc++ ) {
2427 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2428 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2429 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2434 release_dc_ptr( dc );
2439 /******************************************************************************
2440 * GetCharABCWidthsI [GDI32.@]
2442 * Retrieves widths of characters in range.
2445 * hdc [I] Handle of device context
2446 * firstChar [I] First glyphs in range to query
2447 * count [I] Last glyphs in range to query
2448 * pgi [i] Array of glyphs to query
2449 * abc [O] Address of character-width structure
2452 * Only works with TrueType fonts
2458 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2459 LPWORD pgi, LPABC abc)
2461 DC *dc = get_dc_ptr(hdc);
2465 if (!dc) return FALSE;
2469 release_dc_ptr( dc );
2474 ret = WineEngGetCharABCWidthsI( dc->gdiFont, firstChar, count, pgi, abc );
2480 /* convert device units to logical */
2481 for( i = 0; i < count; i++, abc++ ) {
2482 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2483 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2484 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2489 release_dc_ptr( dc );
2494 /***********************************************************************
2495 * GetGlyphOutlineA (GDI32.@)
2497 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2498 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2499 LPVOID lpBuffer, const MAT2 *lpmat2 )
2501 if (!lpmat2) return GDI_ERROR;
2503 if(!(fuFormat & GGO_GLYPH_INDEX)) {
2508 cp = GdiGetCodePage(hdc);
2509 if (IsDBCSLeadByteEx(cp, uChar >> 8)) {
2511 mbchs[0] = (uChar & 0xff00) >> 8;
2512 mbchs[1] = (uChar & 0xff);
2515 mbchs[0] = (uChar & 0xff);
2518 MultiByteToWideChar(cp, 0, mbchs, len, (LPWSTR)&uChar, 1);
2521 return GetGlyphOutlineW(hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer,
2525 /***********************************************************************
2526 * GetGlyphOutlineW (GDI32.@)
2528 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2529 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2530 LPVOID lpBuffer, const MAT2 *lpmat2 )
2535 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2536 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2538 if (!lpmat2) return GDI_ERROR;
2540 dc = get_dc_ptr(hdc);
2541 if(!dc) return GDI_ERROR;
2544 ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
2545 cbBuffer, lpBuffer, lpmat2);
2549 release_dc_ptr( dc );
2554 /***********************************************************************
2555 * CreateScalableFontResourceA (GDI32.@)
2557 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2558 LPCSTR lpszResourceFile,
2559 LPCSTR lpszFontFile,
2560 LPCSTR lpszCurrentPath )
2562 LPWSTR lpszResourceFileW = NULL;
2563 LPWSTR lpszFontFileW = NULL;
2564 LPWSTR lpszCurrentPathW = NULL;
2568 if (lpszResourceFile)
2570 len = MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, NULL, 0);
2571 lpszResourceFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2572 MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, lpszResourceFileW, len);
2577 len = MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, NULL, 0);
2578 lpszFontFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2579 MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, lpszFontFileW, len);
2582 if (lpszCurrentPath)
2584 len = MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, NULL, 0);
2585 lpszCurrentPathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2586 MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, lpszCurrentPathW, len);
2589 ret = CreateScalableFontResourceW(fHidden, lpszResourceFileW,
2590 lpszFontFileW, lpszCurrentPathW);
2592 HeapFree(GetProcessHeap(), 0, lpszResourceFileW);
2593 HeapFree(GetProcessHeap(), 0, lpszFontFileW);
2594 HeapFree(GetProcessHeap(), 0, lpszCurrentPathW);
2599 /***********************************************************************
2600 * CreateScalableFontResourceW (GDI32.@)
2602 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2603 LPCWSTR lpszResourceFile,
2604 LPCWSTR lpszFontFile,
2605 LPCWSTR lpszCurrentPath )
2608 FIXME("(%d,%s,%s,%s): stub\n",
2609 fHidden, debugstr_w(lpszResourceFile), debugstr_w(lpszFontFile),
2610 debugstr_w(lpszCurrentPath) );
2612 /* fHidden=1 - only visible for the calling app, read-only, not
2613 * enumerated with EnumFonts/EnumFontFamilies
2614 * lpszCurrentPath can be NULL
2617 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2618 if ((f = CreateFileW(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2620 SetLastError(ERROR_FILE_EXISTS);
2623 return FALSE; /* create failed */
2626 /*************************************************************************
2627 * GetKerningPairsA (GDI32.@)
2629 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2630 LPKERNINGPAIR kern_pairA )
2634 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2635 KERNINGPAIR *kern_pairW;
2637 if (!cPairs && kern_pairA)
2639 SetLastError(ERROR_INVALID_PARAMETER);
2643 cp = GdiGetCodePage(hDC);
2645 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2646 * to fail on an invalid character for CP_SYMBOL.
2648 cpi.DefaultChar[0] = 0;
2649 if (cp != CP_SYMBOL && !GetCPInfo(cp, &cpi))
2651 FIXME("Can't find codepage %u info\n", cp);
2655 total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2656 if (!total_kern_pairs) return 0;
2658 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2659 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2661 for (i = 0; i < total_kern_pairs; i++)
2665 if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2668 if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2671 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2676 if (kern_pairs_copied >= cPairs) break;
2678 kern_pairA->wFirst = (BYTE)first;
2679 kern_pairA->wSecond = (BYTE)second;
2680 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2683 kern_pairs_copied++;
2686 HeapFree(GetProcessHeap(), 0, kern_pairW);
2688 return kern_pairs_copied;
2691 /*************************************************************************
2692 * GetKerningPairsW (GDI32.@)
2694 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2695 LPKERNINGPAIR lpKerningPairs )
2700 TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2702 if (!cPairs && lpKerningPairs)
2704 SetLastError(ERROR_INVALID_PARAMETER);
2708 dc = get_dc_ptr(hDC);
2712 ret = WineEngGetKerningPairs(dc->gdiFont, cPairs, lpKerningPairs);
2714 release_dc_ptr( dc );
2718 /*************************************************************************
2719 * TranslateCharsetInfo [GDI32.@]
2721 * Fills a CHARSETINFO structure for a character set, code page, or
2722 * font. This allows making the correspondence between different labels
2723 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2724 * of the same encoding.
2726 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2727 * only one codepage should be set in *lpSrc.
2730 * TRUE on success, FALSE on failure.
2733 BOOL WINAPI TranslateCharsetInfo(
2734 LPDWORD lpSrc, /* [in]
2735 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2736 if flags == TCI_SRCCHARSET: a character set value
2737 if flags == TCI_SRCCODEPAGE: a code page value
2739 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2740 DWORD flags /* [in] determines interpretation of lpSrc */)
2744 case TCI_SRCFONTSIG:
2745 while (index < MAXTCIINDEX && !(*lpSrc>>index & 0x0001)) index++;
2747 case TCI_SRCCODEPAGE:
2748 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciACP) index++;
2750 case TCI_SRCCHARSET:
2751 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciCharset) index++;
2756 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2757 *lpCs = FONT_tci[index];
2761 /*************************************************************************
2762 * GetFontLanguageInfo (GDI32.@)
2764 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2766 FONTSIGNATURE fontsig;
2767 static const DWORD GCP_DBCS_MASK=0x003F0000,
2768 GCP_DIACRITIC_MASK=0x00000000,
2769 FLI_GLYPHS_MASK=0x00000000,
2770 GCP_GLYPHSHAPE_MASK=0x00000040,
2771 GCP_KASHIDA_MASK=0x00000000,
2772 GCP_LIGATE_MASK=0x00000000,
2773 GCP_USEKERNING_MASK=0x00000000,
2774 GCP_REORDER_MASK=0x00000060;
2778 GetTextCharsetInfo( hdc, &fontsig, 0 );
2779 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2781 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2784 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2785 result|=GCP_DIACRITIC;
2787 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2790 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2791 result|=GCP_GLYPHSHAPE;
2793 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2794 result|=GCP_KASHIDA;
2796 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2799 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2800 result|=GCP_USEKERNING;
2802 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2803 if( GetTextAlign( hdc) & TA_RTLREADING )
2804 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2805 result|=GCP_REORDER;
2811 /*************************************************************************
2812 * GetFontData [GDI32.@]
2814 * Retrieve data for TrueType font.
2818 * success: Number of bytes returned
2819 * failure: GDI_ERROR
2823 * Calls SetLastError()
2826 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2827 LPVOID buffer, DWORD length)
2829 DC *dc = get_dc_ptr(hdc);
2830 DWORD ret = GDI_ERROR;
2832 if(!dc) return GDI_ERROR;
2835 ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2837 release_dc_ptr( dc );
2841 /*************************************************************************
2842 * GetGlyphIndicesA [GDI32.@]
2844 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2845 LPWORD pgi, DWORD flags)
2851 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2852 hdc, debugstr_an(lpstr, count), count, pgi, flags);
2854 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2855 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2856 HeapFree(GetProcessHeap(), 0, lpstrW);
2861 /*************************************************************************
2862 * GetGlyphIndicesW [GDI32.@]
2864 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2865 LPWORD pgi, DWORD flags)
2867 DC *dc = get_dc_ptr(hdc);
2868 DWORD ret = GDI_ERROR;
2870 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2871 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2873 if(!dc) return GDI_ERROR;
2876 ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2878 release_dc_ptr( dc );
2882 /*************************************************************************
2883 * GetCharacterPlacementA [GDI32.@]
2885 * See GetCharacterPlacementW.
2888 * the web browser control of ie4 calls this with dwFlags=0
2891 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2892 INT nMaxExtent, GCP_RESULTSA *lpResults,
2897 GCP_RESULTSW resultsW;
2901 TRACE("%s, %d, %d, 0x%08x\n",
2902 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2904 /* both structs are equal in size */
2905 memcpy(&resultsW, lpResults, sizeof(resultsW));
2907 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2908 if(lpResults->lpOutString)
2909 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2911 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2913 lpResults->nGlyphs = resultsW.nGlyphs;
2914 lpResults->nMaxFit = resultsW.nMaxFit;
2916 if(lpResults->lpOutString) {
2917 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2918 lpResults->lpOutString, uCount, NULL, NULL );
2921 HeapFree(GetProcessHeap(), 0, lpStringW);
2922 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2927 /*************************************************************************
2928 * GetCharacterPlacementW [GDI32.@]
2930 * Retrieve information about a string. This includes the width, reordering,
2931 * Glyphing and so on.
2935 * The width and height of the string if successful, 0 if failed.
2939 * All flags except GCP_REORDER are not yet implemented.
2940 * Reordering is not 100% compliant to the Windows BiDi method.
2941 * Caret positioning is not yet implemented for BiDi.
2942 * Classes are not yet implemented.
2946 GetCharacterPlacementW(
2947 HDC hdc, /* [in] Device context for which the rendering is to be done */
2948 LPCWSTR lpString, /* [in] The string for which information is to be returned */
2949 INT uCount, /* [in] Number of WORDS in string. */
2950 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
2951 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2952 DWORD dwFlags /* [in] Flags specifying how to process the string */
2959 TRACE("%s, %d, %d, 0x%08x\n",
2960 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2962 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2963 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2964 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2965 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2966 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2968 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08x ignored\n", dwFlags);
2969 if(lpResults->lpClass) FIXME("classes not implemented\n");
2970 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2971 FIXME("Caret positions for complex scripts not implemented\n");
2973 nSet = (UINT)uCount;
2974 if(nSet > lpResults->nGlyphs)
2975 nSet = lpResults->nGlyphs;
2977 /* return number of initialized fields */
2978 lpResults->nGlyphs = nSet;
2980 if((dwFlags&GCP_REORDER)==0 )
2982 /* Treat the case where no special handling was requested in a fastpath way */
2983 /* copy will do if the GCP_REORDER flag is not set */
2984 if(lpResults->lpOutString)
2985 memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
2987 if(lpResults->lpOrder)
2989 for(i = 0; i < nSet; i++)
2990 lpResults->lpOrder[i] = i;
2994 BIDI_Reorder(NULL, lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
2995 nSet, lpResults->lpOrder, NULL, NULL );
2998 /* FIXME: Will use the placement chars */
2999 if (lpResults->lpDx)
3002 for (i = 0; i < nSet; i++)
3004 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
3005 lpResults->lpDx[i]= c;
3009 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
3013 lpResults->lpCaretPos[0] = 0;
3014 for (i = 1; i < nSet; i++)
3015 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
3016 lpResults->lpCaretPos[i] = (pos += size.cx);
3019 if(lpResults->lpGlyphs)
3020 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
3022 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
3023 ret = MAKELONG(size.cx, size.cy);
3028 /*************************************************************************
3029 * GetCharABCWidthsFloatA [GDI32.@]
3031 * See GetCharABCWidthsFloatW.
3033 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3040 str = FONT_GetCharsByRangeA(hdc, first, last, &i);
3044 wstr = FONT_mbtowc( hdc, str, i, &wlen, NULL );
3046 for (i = 0; i < wlen; i++)
3048 if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
3056 HeapFree( GetProcessHeap(), 0, str );
3057 HeapFree( GetProcessHeap(), 0, wstr );
3062 /*************************************************************************
3063 * GetCharABCWidthsFloatW [GDI32.@]
3065 * Retrieves widths of a range of characters.
3068 * hdc [I] Handle to device context.
3069 * first [I] First character in range to query.
3070 * last [I] Last character in range to query.
3071 * abcf [O] Array of LPABCFLOAT structures.
3077 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3081 DC *dc = get_dc_ptr( hdc );
3083 TRACE("%p, %d, %d, %p\n", hdc, first, last, abcf);
3085 if (!dc) return FALSE;
3089 release_dc_ptr( dc );
3094 ret = WineEngGetCharABCWidthsFloat( dc->gdiFont, first, last, abcf );
3100 /* convert device units to logical */
3101 for (i = first; i <= last; i++, abcf++)
3103 abcf->abcfA = abcf->abcfA * dc->xformVport2World.eM11;
3104 abcf->abcfB = abcf->abcfB * dc->xformVport2World.eM11;
3105 abcf->abcfC = abcf->abcfC * dc->xformVport2World.eM11;
3109 release_dc_ptr( dc );
3113 /*************************************************************************
3114 * GetCharWidthFloatA [GDI32.@]
3116 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
3117 UINT iLastChar, PFLOAT pxBuffer)
3119 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3123 /*************************************************************************
3124 * GetCharWidthFloatW [GDI32.@]
3126 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
3127 UINT iLastChar, PFLOAT pxBuffer)
3129 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3134 /***********************************************************************
3136 * Font Resource API *
3138 ***********************************************************************/
3140 /***********************************************************************
3141 * AddFontResourceA (GDI32.@)
3143 INT WINAPI AddFontResourceA( LPCSTR str )
3145 return AddFontResourceExA( str, 0, NULL);
3148 /***********************************************************************
3149 * AddFontResourceW (GDI32.@)
3151 INT WINAPI AddFontResourceW( LPCWSTR str )
3153 return AddFontResourceExW(str, 0, NULL);
3157 /***********************************************************************
3158 * AddFontResourceExA (GDI32.@)
3160 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3162 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3163 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3166 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3167 ret = AddFontResourceExW(strW, fl, pdv);
3168 HeapFree(GetProcessHeap(), 0, strW);
3172 static BOOL CALLBACK load_enumed_resource(HMODULE hModule, LPCWSTR type, LPWSTR name, LONG_PTR lParam)
3174 HRSRC rsrc = FindResourceW(hModule, name, type);
3175 HGLOBAL hMem = LoadResource(hModule, rsrc);
3176 LPVOID *pMem = LockResource(hMem);
3177 int *num_total = (int *)lParam;
3180 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type));
3181 if (!AddFontMemResourceEx(pMem, SizeofResource(hModule, rsrc), NULL, &num_in_res))
3183 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule, hMem);
3187 *num_total += num_in_res;
3191 /***********************************************************************
3192 * AddFontResourceExW (GDI32.@)
3194 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3196 int ret = WineEngAddFontResourceEx(str, fl, pdv);
3199 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3200 HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
3201 if (hModule != NULL)
3203 int num_resources = 0;
3204 LPWSTR rt_font = (LPWSTR)((ULONG_PTR)8); /* we don't want to include winuser.h */
3206 TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3207 wine_dbgstr_w(str));
3208 if (EnumResourceNamesW(hModule, rt_font, load_enumed_resource, (LONG_PTR)&num_resources))
3209 ret = num_resources;
3210 FreeLibrary(hModule);
3216 /***********************************************************************
3217 * RemoveFontResourceA (GDI32.@)
3219 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3221 return RemoveFontResourceExA(str, 0, 0);
3224 /***********************************************************************
3225 * RemoveFontResourceW (GDI32.@)
3227 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3229 return RemoveFontResourceExW(str, 0, 0);
3232 /***********************************************************************
3233 * AddFontMemResourceEx (GDI32.@)
3235 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3240 if (!pbFont || !cbFont || !pcFonts)
3242 SetLastError(ERROR_INVALID_PARAMETER);
3246 ret = WineEngAddFontMemResourceEx(pbFont, cbFont, pdv, &num_fonts);
3251 *pcFonts = num_fonts;
3255 WARN("page fault while writing to *pcFonts (%p)\n", pcFonts);
3256 RemoveFontMemResourceEx(ret);
3264 /***********************************************************************
3265 * RemoveFontMemResourceEx (GDI32.@)
3267 BOOL WINAPI RemoveFontMemResourceEx( HANDLE fh )
3269 FIXME("(%p) stub\n", fh);
3273 /***********************************************************************
3274 * RemoveFontResourceExA (GDI32.@)
3276 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3278 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3279 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3282 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3283 ret = RemoveFontResourceExW(strW, fl, pdv);
3284 HeapFree(GetProcessHeap(), 0, strW);
3288 /***********************************************************************
3289 * RemoveFontResourceExW (GDI32.@)
3291 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3293 return WineEngRemoveFontResourceEx(str, fl, pdv);
3296 /***********************************************************************
3297 * GetTextCharset (GDI32.@)
3299 UINT WINAPI GetTextCharset(HDC hdc)
3301 /* MSDN docs say this is equivalent */
3302 return GetTextCharsetInfo(hdc, NULL, 0);
3305 /***********************************************************************
3306 * GetTextCharsetInfo (GDI32.@)
3308 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3310 UINT ret = DEFAULT_CHARSET;
3311 DC *dc = get_dc_ptr(hdc);
3316 ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
3318 release_dc_ptr( dc );
3321 if (ret == DEFAULT_CHARSET && fs)
3322 memset(fs, 0, sizeof(FONTSIGNATURE));
3326 /***********************************************************************
3327 * GdiGetCharDimensions (GDI32.@)
3329 * Gets the average width of the characters in the English alphabet.
3332 * hdc [I] Handle to the device context to measure on.
3333 * lptm [O] Pointer to memory to store the text metrics into.
3334 * height [O] On exit, the maximum height of characters in the English alphabet.
3337 * The average width of characters in the English alphabet.
3340 * This function is used by the dialog manager to get the size of a dialog
3341 * unit. It should also be used by other pieces of code that need to know
3342 * the size of a dialog unit in logical units without having access to the
3343 * window handle of the dialog.
3344 * Windows caches the font metrics from this function, but we don't and
3345 * there doesn't appear to be an immediate advantage to do so.
3348 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3350 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3353 static const WCHAR alphabet[] = {
3354 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3355 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3356 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3358 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3360 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3362 if (height) *height = sz.cy;
3363 return (sz.cx / 26 + 1) / 2;
3366 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3368 FIXME("(%d): stub\n", fEnableEUDC);
3372 /***********************************************************************
3373 * GetCharWidthI (GDI32.@)
3375 * Retrieve widths of characters.
3378 * hdc [I] Handle to a device context.
3379 * first [I] First glyph in range to query.
3380 * count [I] Number of glyph indices to query.
3381 * glyphs [I] Array of glyphs to query.
3382 * buffer [O] Buffer to receive character widths.
3385 * Only works with TrueType fonts.
3391 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3396 TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3398 if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3401 if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3403 HeapFree(GetProcessHeap(), 0, abc);
3407 for (i = 0; i < count; i++)
3408 buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3410 HeapFree(GetProcessHeap(), 0, abc);
3414 /***********************************************************************
3415 * GetFontUnicodeRanges (GDI32.@)
3417 * Retrieve a list of supported Unicode characters in a font.
3420 * hdc [I] Handle to a device context.
3421 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3424 * Success: Number of bytes written to the buffer pointed to by lpgs.
3428 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3431 DC *dc = get_dc_ptr(hdc);
3433 TRACE("(%p, %p)\n", hdc, lpgs);
3437 if (dc->gdiFont) ret = WineEngGetFontUnicodeRanges(dc->gdiFont, lpgs);
3443 /*************************************************************
3444 * FontIsLinked (GDI32.@)
3446 BOOL WINAPI FontIsLinked(HDC hdc)
3448 DC *dc = get_dc_ptr(hdc);
3451 if (!dc) return FALSE;
3452 if (dc->gdiFont) ret = WineEngFontIsLinked(dc->gdiFont);
3454 TRACE("returning %d\n", ret);
3458 /*************************************************************
3459 * GdiRealizationInfo (GDI32.@)
3461 * Returns a structure that contains some font information.
3463 BOOL WINAPI GdiRealizationInfo(HDC hdc, realization_info_t *info)
3465 DC *dc = get_dc_ptr(hdc);
3468 if (!dc) return FALSE;
3469 if (dc->gdiFont) ret = WineEngRealizationInfo(dc->gdiFont, info);