4 * Copyright 1993 Alexandre Julliard
6 * Copyright 2002,2003 Shachar Shemesh
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "wine/port.h"
35 #include "gdi_private.h"
36 #include "wine/unicode.h"
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(font);
41 /* Device -> World size conversion */
43 /* Performs a device to world transformation on the specified width (which
44 * is in integer format).
46 static inline INT INTERNAL_XDSTOWS(DC *dc, INT width)
50 /* Perform operation with floating point */
51 floatWidth = (FLOAT)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 = (FLOAT)height * dc->xformVport2World.eM22;
65 /* Round to integers */
66 return GDI_ROUND(floatHeight);
69 static inline INT INTERNAL_XWSTODS(DC *dc, INT width)
72 pt[0].x = pt[0].y = 0;
75 LPtoDP(dc->hSelf, pt, 2);
76 return pt[1].x - pt[0].x;
79 static inline INT INTERNAL_YWSTODS(DC *dc, INT height)
82 pt[0].x = pt[0].y = 0;
85 LPtoDP(dc->hSelf, pt, 2);
86 return pt[1].y - pt[0].y;
89 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc );
90 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
91 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
92 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj );
94 static const struct gdi_obj_funcs font_funcs =
96 FONT_SelectObject, /* pSelectObject */
97 FONT_GetObjectA, /* pGetObjectA */
98 FONT_GetObjectW, /* pGetObjectW */
99 NULL, /* pUnrealizeObject */
100 FONT_DeleteObject /* pDeleteObject */
103 #define ENUM_UNICODE 0x00000001
104 #define ENUM_CALLED 0x00000002
114 LPLOGFONTW lpLogFontParam;
115 FONTENUMPROCW lpEnumFunc;
122 * For TranslateCharsetInfo
124 #define MAXTCIINDEX 32
125 static const CHARSETINFO FONT_tci[MAXTCIINDEX] = {
127 { ANSI_CHARSET, 1252, {{0,0,0,0},{FS_LATIN1,0}} },
128 { EASTEUROPE_CHARSET, 1250, {{0,0,0,0},{FS_LATIN2,0}} },
129 { RUSSIAN_CHARSET, 1251, {{0,0,0,0},{FS_CYRILLIC,0}} },
130 { GREEK_CHARSET, 1253, {{0,0,0,0},{FS_GREEK,0}} },
131 { TURKISH_CHARSET, 1254, {{0,0,0,0},{FS_TURKISH,0}} },
132 { HEBREW_CHARSET, 1255, {{0,0,0,0},{FS_HEBREW,0}} },
133 { ARABIC_CHARSET, 1256, {{0,0,0,0},{FS_ARABIC,0}} },
134 { BALTIC_CHARSET, 1257, {{0,0,0,0},{FS_BALTIC,0}} },
135 { VIETNAMESE_CHARSET, 1258, {{0,0,0,0},{FS_VIETNAMESE,0}} },
136 /* reserved by ANSI */
137 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
138 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
139 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
140 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
141 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
142 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
143 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
145 { THAI_CHARSET, 874, {{0,0,0,0},{FS_THAI,0}} },
146 { SHIFTJIS_CHARSET, 932, {{0,0,0,0},{FS_JISJAPAN,0}} },
147 { GB2312_CHARSET, 936, {{0,0,0,0},{FS_CHINESESIMP,0}} },
148 { HANGEUL_CHARSET, 949, {{0,0,0,0},{FS_WANSUNG,0}} },
149 { CHINESEBIG5_CHARSET, 950, {{0,0,0,0},{FS_CHINESETRAD,0}} },
150 { JOHAB_CHARSET, 1361, {{0,0,0,0},{FS_JOHAB,0}} },
151 /* reserved for alternate ANSI and OEM */
152 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
153 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
154 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
155 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
156 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
157 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
158 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
159 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
160 /* reserved for system */
161 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
162 { SYMBOL_CHARSET, CP_SYMBOL, {{0,0,0,0},{FS_SYMBOL,0}} }
165 static void FONT_LogFontAToW( const LOGFONTA *fontA, LPLOGFONTW fontW )
167 memcpy(fontW, fontA, sizeof(LOGFONTA) - LF_FACESIZE);
168 MultiByteToWideChar(CP_ACP, 0, fontA->lfFaceName, -1, fontW->lfFaceName,
170 fontW->lfFaceName[LF_FACESIZE-1] = 0;
173 static void FONT_LogFontWToA( const LOGFONTW *fontW, LPLOGFONTA fontA )
175 memcpy(fontA, fontW, sizeof(LOGFONTA) - LF_FACESIZE);
176 WideCharToMultiByte(CP_ACP, 0, fontW->lfFaceName, -1, fontA->lfFaceName,
177 LF_FACESIZE, NULL, NULL);
178 fontA->lfFaceName[LF_FACESIZE-1] = 0;
181 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEXA fontA )
183 FONT_LogFontWToA( (const LOGFONTW *)fontW, (LPLOGFONTA)fontA);
185 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
186 (LPSTR) fontA->elfFullName, LF_FULLFACESIZE, NULL, NULL );
187 fontA->elfFullName[LF_FULLFACESIZE-1] = '\0';
188 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
189 (LPSTR) fontA->elfStyle, LF_FACESIZE, NULL, NULL );
190 fontA->elfStyle[LF_FACESIZE-1] = '\0';
191 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
192 (LPSTR) fontA->elfScript, LF_FACESIZE, NULL, NULL );
193 fontA->elfScript[LF_FACESIZE-1] = '\0';
196 /***********************************************************************
197 * TEXTMETRIC conversion functions.
199 static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
201 ptmA->tmHeight = ptmW->tmHeight;
202 ptmA->tmAscent = ptmW->tmAscent;
203 ptmA->tmDescent = ptmW->tmDescent;
204 ptmA->tmInternalLeading = ptmW->tmInternalLeading;
205 ptmA->tmExternalLeading = ptmW->tmExternalLeading;
206 ptmA->tmAveCharWidth = ptmW->tmAveCharWidth;
207 ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth;
208 ptmA->tmWeight = ptmW->tmWeight;
209 ptmA->tmOverhang = ptmW->tmOverhang;
210 ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX;
211 ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
212 ptmA->tmFirstChar = min(ptmW->tmFirstChar, 255);
213 if (ptmW->tmCharSet == SYMBOL_CHARSET)
215 UINT last_char = ptmW->tmLastChar;
216 if (last_char > 0xf000) last_char -= 0xf000;
217 ptmA->tmLastChar = min(last_char, 255);
220 ptmA->tmLastChar = min(ptmW->tmLastChar, 255);
221 ptmA->tmDefaultChar = min(ptmW->tmDefaultChar, 255);
222 ptmA->tmBreakChar = min(ptmW->tmBreakChar, 255);
223 ptmA->tmItalic = ptmW->tmItalic;
224 ptmA->tmUnderlined = ptmW->tmUnderlined;
225 ptmA->tmStruckOut = ptmW->tmStruckOut;
226 ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
227 ptmA->tmCharSet = ptmW->tmCharSet;
231 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW *ptmW, NEWTEXTMETRICEXA *ptmA )
233 FONT_TextMetricWToA((const TEXTMETRICW *)ptmW, (LPTEXTMETRICA)ptmA);
234 ptmA->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
235 ptmA->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
236 ptmA->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
237 ptmA->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
238 memcpy(&ptmA->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
242 /***********************************************************************
243 * GdiGetCodePage (GDI32.@)
245 DWORD WINAPI GdiGetCodePage( HDC hdc )
249 int charset = GetTextCharset(hdc);
251 /* Hmm, nicely designed api this one! */
252 if(TranslateCharsetInfo(ULongToPtr(charset), &csi, TCI_SRCCHARSET))
259 case DEFAULT_CHARSET:
270 /* FIXME: These have no place here, but because x11drv
271 enumerates fonts with these (made up) charsets some apps
272 might use them and then the FIXME below would become
273 annoying. Now we could pick the intended codepage for
274 each of these, but since it's broken anyway we'll just
275 use CP_ACP and hope it'll go away...
281 FIXME("Can't find codepage for charset %d\n", charset);
286 TRACE("charset %d => cp %d\n", charset, cp);
290 /***********************************************************************
293 * Returns a Unicode translation of str using the charset of the
294 * currently selected font in hdc. If count is -1 then str is assumed
295 * to be '\0' terminated, otherwise it contains the number of bytes to
296 * convert. If plenW is non-NULL, on return it will point to the
297 * number of WCHARs that have been written. If pCP is non-NULL, on
298 * return it will point to the codepage used in the conversion. The
299 * caller should free the returned LPWSTR from the process heap
302 static LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
308 cp = GdiGetCodePage( hdc );
310 if(count == -1) count = strlen(str);
311 lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
312 strW = HeapAlloc(GetProcessHeap(), 0, lenW*sizeof(WCHAR));
313 MultiByteToWideChar(cp, 0, str, count, strW, lenW);
314 TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW));
315 if(plenW) *plenW = lenW;
321 /***********************************************************************
322 * CreateFontIndirectA (GDI32.@)
324 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *plfA )
330 FONT_LogFontAToW( plfA, &lfW );
331 return CreateFontIndirectW( &lfW );
334 /***********************************************************************
335 * CreateFontIndirectW (GDI32.@)
337 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
339 static const WCHAR ItalicW[] = {' ','I','t','a','l','i','c','\0'};
340 static const WCHAR BoldW[] = {' ','B','o','l','d','\0'};
341 WCHAR *pFaceNameItalicSuffix, *pFaceNameBoldSuffix;
342 WCHAR *pFaceNameSuffix = NULL;
348 if (!(fontPtr = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC, (HGDIOBJ *)&hFont,
349 &font_funcs ))) return 0;
351 fontPtr->logfont = *plf;
353 TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
354 plf->lfHeight, plf->lfWidth,
355 plf->lfEscapement, plf->lfOrientation,
356 plf->lfPitchAndFamily,
357 plf->lfOutPrecision, plf->lfClipPrecision,
358 plf->lfQuality, plf->lfCharSet,
359 debugstr_w(plf->lfFaceName),
360 plf->lfWeight > 400 ? "Bold" : "",
361 plf->lfItalic ? "Italic" : "",
362 plf->lfUnderline ? "Underline" : "", hFont);
364 if (plf->lfEscapement != plf->lfOrientation)
366 /* this should really depend on whether GM_ADVANCED is set */
367 fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
368 WARN("orientation angle %f set to "
369 "escapement angle %f for new font %p\n",
370 plf->lfOrientation/10., plf->lfEscapement/10., hFont);
373 pFaceNameItalicSuffix = strstrW(fontPtr->logfont.lfFaceName, ItalicW);
374 if (pFaceNameItalicSuffix)
376 fontPtr->logfont.lfItalic = TRUE;
377 pFaceNameSuffix = pFaceNameItalicSuffix;
380 pFaceNameBoldSuffix = strstrW(fontPtr->logfont.lfFaceName, BoldW);
381 if (pFaceNameBoldSuffix)
383 if (fontPtr->logfont.lfWeight < FW_BOLD)
384 fontPtr->logfont.lfWeight = FW_BOLD;
385 if (!pFaceNameSuffix || (pFaceNameBoldSuffix < pFaceNameSuffix))
386 pFaceNameSuffix = pFaceNameBoldSuffix;
389 if (pFaceNameSuffix) *pFaceNameSuffix = 0;
391 GDI_ReleaseObj( hFont );
395 /*************************************************************************
396 * CreateFontA (GDI32.@)
398 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
399 INT orient, INT weight, DWORD italic,
400 DWORD underline, DWORD strikeout, DWORD charset,
401 DWORD outpres, DWORD clippres, DWORD quality,
402 DWORD pitch, LPCSTR name )
406 logfont.lfHeight = height;
407 logfont.lfWidth = width;
408 logfont.lfEscapement = esc;
409 logfont.lfOrientation = orient;
410 logfont.lfWeight = weight;
411 logfont.lfItalic = italic;
412 logfont.lfUnderline = underline;
413 logfont.lfStrikeOut = strikeout;
414 logfont.lfCharSet = charset;
415 logfont.lfOutPrecision = outpres;
416 logfont.lfClipPrecision = clippres;
417 logfont.lfQuality = quality;
418 logfont.lfPitchAndFamily = pitch;
421 lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
423 logfont.lfFaceName[0] = '\0';
425 return CreateFontIndirectA( &logfont );
428 /*************************************************************************
429 * CreateFontW (GDI32.@)
431 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
432 INT orient, INT weight, DWORD italic,
433 DWORD underline, DWORD strikeout, DWORD charset,
434 DWORD outpres, DWORD clippres, DWORD quality,
435 DWORD pitch, LPCWSTR name )
439 logfont.lfHeight = height;
440 logfont.lfWidth = width;
441 logfont.lfEscapement = esc;
442 logfont.lfOrientation = orient;
443 logfont.lfWeight = weight;
444 logfont.lfItalic = italic;
445 logfont.lfUnderline = underline;
446 logfont.lfStrikeOut = strikeout;
447 logfont.lfCharSet = charset;
448 logfont.lfOutPrecision = outpres;
449 logfont.lfClipPrecision = clippres;
450 logfont.lfQuality = quality;
451 logfont.lfPitchAndFamily = pitch;
454 lstrcpynW(logfont.lfFaceName, name,
455 sizeof(logfont.lfFaceName) / sizeof(WCHAR));
457 logfont.lfFaceName[0] = '\0';
459 return CreateFontIndirectW( &logfont );
463 /***********************************************************************
466 * If the driver supports vector fonts we create a gdi font first and
467 * then call the driver to give it a chance to supply its own device
468 * font. If the driver wants to do this it returns TRUE and we can
469 * delete the gdi font, if the driver wants to use the gdi font it
470 * should return FALSE, to signal an error return GDI_ERROR. For
471 * drivers that don't support vector fonts they must supply their own
474 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc )
477 DC *dc = get_dc_ptr( hdc );
481 if (!GDI_inc_ref_count( handle ))
483 release_dc_ptr( dc );
487 if (dc->hFont != handle || dc->gdiFont == NULL)
489 if(GetDeviceCaps(dc->hSelf, TEXTCAPS) & TC_VA_ABLE)
491 FONTOBJ *font = GDI_GetObjPtr( handle, FONT_MAGIC ); /* to grab the GDI lock (FIXME) */
492 dc->gdiFont = WineEngCreateFontInstance(dc, handle);
493 if (font) GDI_ReleaseObj( handle );
497 if (dc->funcs->pSelectFont) ret = dc->funcs->pSelectFont( dc->physDev, handle, dc->gdiFont );
499 if (ret && dc->gdiFont) dc->gdiFont = 0;
501 if (ret == HGDI_ERROR)
503 GDI_dec_ref_count( handle );
504 ret = 0; /* SelectObject returns 0 on error */
510 GDI_dec_ref_count( ret );
512 release_dc_ptr( dc );
517 /***********************************************************************
520 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
527 FONT_LogFontWToA( &font->logfont, &lfA );
529 if (count > sizeof(lfA)) count = sizeof(lfA);
530 memcpy( buffer, &lfA, count );
534 /***********************************************************************
537 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
541 return sizeof(LOGFONTW);
542 if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
543 memcpy( buffer, &font->logfont, count );
548 /***********************************************************************
551 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj )
553 WineEngDestroyFontInstance( handle );
554 return GDI_FreeObject( handle, obj );
558 /***********************************************************************
561 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
562 * We have to use other types because of the FONTENUMPROCW definition.
564 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
565 DWORD fType, LPARAM lp )
567 fontEnum32 *pfe = (fontEnum32*)lp;
570 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
571 if ((!pfe->lpLogFontParam ||
572 pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
573 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
574 (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
576 /* convert font metrics */
577 ENUMLOGFONTEXA logfont;
578 NEWTEXTMETRICEXA tmA;
580 pfe->dwFlags |= ENUM_CALLED;
581 if (!(pfe->dwFlags & ENUM_UNICODE))
583 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
584 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
585 plf = (LOGFONTW *)&logfont.elfLogFont;
586 ptm = (TEXTMETRICW *)&tmA;
589 ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
594 /***********************************************************************
595 * FONT_EnumFontFamiliesEx
597 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf,
598 FONTENUMPROCW efproc,
599 LPARAM lParam, DWORD dwUnicode)
602 DC *dc = get_dc_ptr( hDC );
609 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName),
611 fe32.lpLogFontParam = plf;
612 fe32.lpEnumFunc = efproc;
613 fe32.lpData = lParam;
614 fe32.dwFlags = dwUnicode;
617 enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE;
619 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
626 ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
627 fe32.dwFlags &= ~ENUM_CALLED;
628 if (ret && dc->funcs->pEnumDeviceFonts) {
629 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, plf, FONT_EnumInstance, (LPARAM)&fe32 );
630 if(fe32.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
634 release_dc_ptr( dc );
638 /***********************************************************************
639 * EnumFontFamiliesExW (GDI32.@)
641 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
642 FONTENUMPROCW efproc,
643 LPARAM lParam, DWORD dwFlags )
645 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, ENUM_UNICODE );
648 /***********************************************************************
649 * EnumFontFamiliesExA (GDI32.@)
651 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
652 FONTENUMPROCA efproc,
653 LPARAM lParam, DWORD dwFlags)
659 FONT_LogFontAToW( plf, &lfW );
664 return FONT_EnumFontFamiliesEx( hDC, plfW, (FONTENUMPROCW)efproc, lParam, 0);
667 /***********************************************************************
668 * EnumFontFamiliesA (GDI32.@)
670 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
671 FONTENUMPROCA efproc, LPARAM lpData )
677 if (!*lpFamily) return 1;
678 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
679 lf.lfCharSet = DEFAULT_CHARSET;
680 lf.lfPitchAndFamily = 0;
685 return EnumFontFamiliesExA( hDC, plf, efproc, lpData, 0 );
688 /***********************************************************************
689 * EnumFontFamiliesW (GDI32.@)
691 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
692 FONTENUMPROCW efproc, LPARAM lpData )
698 if (!*lpFamily) return 1;
699 lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
700 lf.lfCharSet = DEFAULT_CHARSET;
701 lf.lfPitchAndFamily = 0;
706 return EnumFontFamiliesExW( hDC, plf, efproc, lpData, 0 );
709 /***********************************************************************
710 * EnumFontsA (GDI32.@)
712 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
715 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
718 /***********************************************************************
719 * EnumFontsW (GDI32.@)
721 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
724 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
728 /***********************************************************************
729 * GetTextCharacterExtra (GDI32.@)
731 INT WINAPI GetTextCharacterExtra( HDC hdc )
734 DC *dc = get_dc_ptr( hdc );
735 if (!dc) return 0x80000000;
737 release_dc_ptr( dc );
742 /***********************************************************************
743 * SetTextCharacterExtra (GDI32.@)
745 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
748 DC * dc = get_dc_ptr( hdc );
749 if (!dc) return 0x80000000;
750 if (dc->funcs->pSetTextCharacterExtra)
751 prev = dc->funcs->pSetTextCharacterExtra( dc->physDev, extra );
754 prev = dc->charExtra;
755 dc->charExtra = extra;
757 release_dc_ptr( dc );
762 /***********************************************************************
763 * SetTextJustification (GDI32.@)
765 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
768 DC * dc = get_dc_ptr( hdc );
769 if (!dc) return FALSE;
770 if (dc->funcs->pSetTextJustification)
771 ret = dc->funcs->pSetTextJustification( dc->physDev, extra, breaks );
774 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
775 if (!extra) breaks = 0;
778 dc->breakExtra = extra / breaks;
779 dc->breakRem = extra - (breaks * dc->breakExtra);
787 release_dc_ptr( dc );
792 /***********************************************************************
793 * GetTextFaceA (GDI32.@)
795 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
797 INT res = GetTextFaceW(hdc, 0, NULL);
798 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
799 GetTextFaceW( hdc, res, nameW );
803 if (count && !WideCharToMultiByte( CP_ACP, 0, nameW, -1, name, count, NULL, NULL))
808 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
809 HeapFree( GetProcessHeap(), 0, nameW );
813 /***********************************************************************
814 * GetTextFaceW (GDI32.@)
816 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
821 DC * dc = get_dc_ptr( hdc );
825 ret = WineEngGetTextFace(dc->gdiFont, count, name);
826 else if ((font = (FONTOBJ *) GDI_GetObjPtr( dc->hFont, FONT_MAGIC )))
830 lstrcpynW( name, font->logfont.lfFaceName, count );
833 else ret = strlenW(font->logfont.lfFaceName) + 1;
834 GDI_ReleaseObj( dc->hFont );
836 release_dc_ptr( dc );
841 /***********************************************************************
842 * GetTextExtentPoint32A (GDI32.@)
844 * See GetTextExtentPoint32W.
846 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
851 LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
854 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
855 HeapFree( GetProcessHeap(), 0, p );
858 TRACE("(%p %s %d %p): returning %d x %d\n",
859 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
864 /***********************************************************************
865 * GetTextExtentPoint32W [GDI32.@]
867 * Computes width/height for a string.
869 * Computes width and height of the specified string.
875 BOOL WINAPI GetTextExtentPoint32W(
876 HDC hdc, /* [in] Handle of device context */
877 LPCWSTR str, /* [in] Address of text string */
878 INT count, /* [in] Number of characters in string */
879 LPSIZE size) /* [out] Address of structure for string size */
881 return GetTextExtentExPointW(hdc, str, count, 0, NULL, NULL, size);
884 /***********************************************************************
885 * GetTextExtentExPointI [GDI32.@]
887 * Computes width and height of the array of glyph indices.
890 * hdc [I] Handle of device context.
891 * indices [I] Glyph index array.
892 * count [I] Number of glyphs in array.
893 * max_ext [I] Maximum width in glyphs.
894 * nfit [O] Maximum number of characters.
895 * dxs [O] Partial string widths.
896 * size [O] Returned string size.
902 BOOL WINAPI GetTextExtentExPointI( HDC hdc, const WORD *indices, INT count, INT max_ext,
903 LPINT nfit, LPINT dxs, LPSIZE size )
906 DC * dc = get_dc_ptr( hdc );
907 if (!dc) return FALSE;
910 ret = WineEngGetTextExtentExPointI(dc->gdiFont, indices, count, max_ext, nfit, dxs, size);
911 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
912 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
913 size->cx += count * dc->charExtra;
915 else if(dc->funcs->pGetTextExtentExPoint) {
916 FIXME("calling GetTextExtentExPoint\n");
917 ret = dc->funcs->pGetTextExtentExPoint( dc->physDev, (LPCWSTR)indices,
918 count, max_ext, nfit, dxs, size );
921 release_dc_ptr( dc );
923 TRACE("(%p %p %d %p): returning %d x %d\n",
924 hdc, indices, count, size, size->cx, size->cy );
928 /***********************************************************************
929 * GetTextExtentPointI [GDI32.@]
931 * Computes width and height of the array of glyph indices.
934 * hdc [I] Handle of device context.
935 * indices [I] Glyph index array.
936 * count [I] Number of glyphs in array.
937 * size [O] Returned string size.
943 BOOL WINAPI GetTextExtentPointI( HDC hdc, const WORD *indices, INT count, LPSIZE size )
945 return GetTextExtentExPointI( hdc, indices, count, 0, NULL, NULL, size );
949 /***********************************************************************
950 * GetTextExtentPointA (GDI32.@)
952 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
955 TRACE("not bug compatible.\n");
956 return GetTextExtentPoint32A( hdc, str, count, size );
959 /***********************************************************************
960 * GetTextExtentPointW (GDI32.@)
962 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
965 TRACE("not bug compatible.\n");
966 return GetTextExtentPoint32W( hdc, str, count, size );
970 /***********************************************************************
971 * GetTextExtentExPointA (GDI32.@)
973 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
974 INT maxExt, LPINT lpnFit,
975 LPINT alpDx, LPSIZE size )
983 NULL == (walpDx = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT))))
986 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
987 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
990 INT n = lpnFit ? *lpnFit : wlen;
992 for(i = 0, j = 0; i < n; i++, j++)
994 alpDx[j] = walpDx[i];
995 if (IsDBCSLeadByte(str[j])) alpDx[++j] = walpDx[i];
998 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
999 HeapFree( GetProcessHeap(), 0, p );
1000 HeapFree( GetProcessHeap(), 0, walpDx );
1005 /***********************************************************************
1006 * GetTextExtentExPointW (GDI32.@)
1008 * Return the size of the string as it would be if it was output properly by
1011 * This should include
1012 * - Intercharacter spacing
1013 * - justification spacing (not yet done)
1014 * - kerning? see below
1016 * Kerning. Since kerning would be carried out by the rendering code it should
1017 * be done by the driver. However they don't support it yet. Also I am not
1018 * yet persuaded that (certainly under Win95) any kerning is actually done.
1020 * str: According to MSDN this should be null-terminated. That is not true; a
1021 * null will not terminate it early.
1022 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1023 * than count. I have seen it be either the size of the full string or
1024 * 1 less than the size of the full string. I have not seen it bear any
1025 * resemblance to the portion that would fit.
1026 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1027 * trailing intercharacter spacing and any trailing justification.
1030 * Currently we do this by measuring each character etc. We should do it by
1031 * passing the request to the driver, perhaps by extending the
1032 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1033 * thinking about kerning issues and rounding issues in the justification.
1036 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1037 INT maxExt, LPINT lpnFit,
1038 LPINT alpDx, LPSIZE size )
1046 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1048 dc = get_dc_ptr(hdc);
1052 GetTextMetricsW(hdc, &tm);
1054 /* If we need to calculate nFit, then we need the partial extents even if
1055 the user hasn't provided us with an array. */
1058 dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]);
1062 SetLastError(ERROR_OUTOFMEMORY);
1070 ret = WineEngGetTextExtentExPoint(dc->gdiFont, str, count,
1071 0, NULL, dxs, size);
1072 else if (dc->funcs->pGetTextExtentExPoint)
1073 ret = dc->funcs->pGetTextExtentExPoint(dc->physDev, str, count,
1074 0, NULL, dxs, size);
1076 /* Perform device size to world size transformations. */
1079 INT extra = dc->charExtra,
1080 breakExtra = dc->breakExtra,
1081 breakRem = dc->breakRem,
1086 for (i = 0; i < count; ++i)
1088 dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
1089 dxs[i] += (i+1) * extra;
1090 if (count > 1 && (breakExtra || breakRem) && str[i] == tm.tmBreakChar)
1092 dxs[i] += breakExtra;
1099 if (dxs[i] <= maxExt)
1102 breakRem = dc->breakRem;
1104 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1105 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1107 if (!dxs && count > 1 && (breakExtra || breakRem))
1109 for (i = 0; i < count; i++)
1111 if (str[i] == tm.tmBreakChar)
1113 size->cx += breakExtra;
1128 HeapFree(GetProcessHeap(), 0, dxs);
1130 release_dc_ptr( dc );
1132 TRACE("returning %d %d x %d\n",nFit,size->cx,size->cy);
1136 /***********************************************************************
1137 * GetTextMetricsA (GDI32.@)
1139 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1143 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1144 FONT_TextMetricWToA( &tm32, metrics );
1148 /***********************************************************************
1149 * GetTextMetricsW (GDI32.@)
1151 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1154 DC * dc = get_dc_ptr( hdc );
1155 if (!dc) return FALSE;
1158 ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1159 else if (dc->funcs->pGetTextMetrics)
1160 ret = dc->funcs->pGetTextMetrics( dc->physDev, metrics );
1164 /* device layer returns values in device units
1165 * therefore we have to convert them to logical */
1167 metrics->tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1168 metrics->tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1170 #define WDPTOLP(x) ((x<0)? \
1171 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1172 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1173 #define HDPTOLP(y) ((y<0)? \
1174 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1175 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1177 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1178 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1179 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1180 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1181 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1182 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1183 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1184 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1188 TRACE("text metrics:\n"
1189 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1190 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1191 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1192 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1193 " PitchAndFamily = %02x\n"
1194 " --------------------\n"
1195 " InternalLeading = %i\n"
1199 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1200 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1201 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1202 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1203 metrics->tmPitchAndFamily,
1204 metrics->tmInternalLeading,
1207 metrics->tmHeight );
1209 release_dc_ptr( dc );
1214 /***********************************************************************
1215 * GetOutlineTextMetricsA (GDI32.@)
1216 * Gets metrics for TrueType fonts.
1219 * If the supplied buffer isn't big enough Windows partially fills it up to
1220 * its given length and returns that length.
1223 * Success: Non-zero or size of required buffer
1226 UINT WINAPI GetOutlineTextMetricsA(
1227 HDC hdc, /* [in] Handle of device context */
1228 UINT cbData, /* [in] Size of metric data array */
1229 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1231 char buf[512], *ptr;
1233 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1234 OUTLINETEXTMETRICA *output = lpOTM;
1237 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1239 if(ret > sizeof(buf))
1240 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1241 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1243 needed = sizeof(OUTLINETEXTMETRICA);
1244 if(lpOTMW->otmpFamilyName)
1245 needed += WideCharToMultiByte(CP_ACP, 0,
1246 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1247 NULL, 0, NULL, NULL);
1248 if(lpOTMW->otmpFaceName)
1249 needed += WideCharToMultiByte(CP_ACP, 0,
1250 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1251 NULL, 0, NULL, NULL);
1252 if(lpOTMW->otmpStyleName)
1253 needed += WideCharToMultiByte(CP_ACP, 0,
1254 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1255 NULL, 0, NULL, NULL);
1256 if(lpOTMW->otmpFullName)
1257 needed += WideCharToMultiByte(CP_ACP, 0,
1258 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1259 NULL, 0, NULL, NULL);
1266 TRACE("needed = %d\n", needed);
1268 /* Since the supplied buffer isn't big enough, we'll alloc one
1269 that is and memcpy the first cbData bytes into the lpOTM at
1271 output = HeapAlloc(GetProcessHeap(), 0, needed);
1273 ret = output->otmSize = min(needed, cbData);
1274 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1275 output->otmFiller = 0;
1276 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1277 output->otmfsSelection = lpOTMW->otmfsSelection;
1278 output->otmfsType = lpOTMW->otmfsType;
1279 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1280 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1281 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1282 output->otmEMSquare = lpOTMW->otmEMSquare;
1283 output->otmAscent = lpOTMW->otmAscent;
1284 output->otmDescent = lpOTMW->otmDescent;
1285 output->otmLineGap = lpOTMW->otmLineGap;
1286 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1287 output->otmsXHeight = lpOTMW->otmsXHeight;
1288 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1289 output->otmMacAscent = lpOTMW->otmMacAscent;
1290 output->otmMacDescent = lpOTMW->otmMacDescent;
1291 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1292 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1293 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1294 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1295 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1296 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1297 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1298 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1299 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1300 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1303 ptr = (char*)(output + 1);
1304 left = needed - sizeof(*output);
1306 if(lpOTMW->otmpFamilyName) {
1307 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1308 len = WideCharToMultiByte(CP_ACP, 0,
1309 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1310 ptr, left, NULL, NULL);
1314 output->otmpFamilyName = 0;
1316 if(lpOTMW->otmpFaceName) {
1317 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1318 len = WideCharToMultiByte(CP_ACP, 0,
1319 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1320 ptr, left, NULL, NULL);
1324 output->otmpFaceName = 0;
1326 if(lpOTMW->otmpStyleName) {
1327 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1328 len = WideCharToMultiByte(CP_ACP, 0,
1329 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1330 ptr, left, NULL, NULL);
1334 output->otmpStyleName = 0;
1336 if(lpOTMW->otmpFullName) {
1337 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1338 len = WideCharToMultiByte(CP_ACP, 0,
1339 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1340 ptr, left, NULL, NULL);
1343 output->otmpFullName = 0;
1347 if(output != lpOTM) {
1348 memcpy(lpOTM, output, cbData);
1349 HeapFree(GetProcessHeap(), 0, output);
1351 /* check if the string offsets really fit into the provided size */
1352 /* FIXME: should we check string length as well? */
1353 /* make sure that we don't read/write beyond the provided buffer */
1354 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(LPSTR))
1356 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1357 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1360 /* make sure that we don't read/write beyond the provided buffer */
1361 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(LPSTR))
1363 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1364 lpOTM->otmpFaceName = 0; /* doesn't fit */
1367 /* make sure that we don't read/write beyond the provided buffer */
1368 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(LPSTR))
1370 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1371 lpOTM->otmpStyleName = 0; /* doesn't fit */
1374 /* make sure that we don't read/write beyond the provided buffer */
1375 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(LPSTR))
1377 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1378 lpOTM->otmpFullName = 0; /* doesn't fit */
1383 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1384 HeapFree(GetProcessHeap(), 0, lpOTMW);
1390 /***********************************************************************
1391 * GetOutlineTextMetricsW [GDI32.@]
1393 UINT WINAPI GetOutlineTextMetricsW(
1394 HDC hdc, /* [in] Handle of device context */
1395 UINT cbData, /* [in] Size of metric data array */
1396 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1398 DC *dc = get_dc_ptr( hdc );
1399 OUTLINETEXTMETRICW *output = lpOTM;
1402 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1406 ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, output);
1409 output = HeapAlloc(GetProcessHeap(), 0, ret);
1410 WineEngGetOutlineTextMetrics(dc->gdiFont, ret, output);
1413 #define WDPTOLP(x) ((x<0)? \
1414 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1415 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1416 #define HDPTOLP(y) ((y<0)? \
1417 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1418 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1420 output->otmTextMetrics.tmHeight = HDPTOLP(output->otmTextMetrics.tmHeight);
1421 output->otmTextMetrics.tmAscent = HDPTOLP(output->otmTextMetrics.tmAscent);
1422 output->otmTextMetrics.tmDescent = HDPTOLP(output->otmTextMetrics.tmDescent);
1423 output->otmTextMetrics.tmInternalLeading = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1424 output->otmTextMetrics.tmExternalLeading = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1425 output->otmTextMetrics.tmAveCharWidth = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1426 output->otmTextMetrics.tmMaxCharWidth = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1427 output->otmTextMetrics.tmOverhang = WDPTOLP(output->otmTextMetrics.tmOverhang);
1428 output->otmAscent = HDPTOLP(output->otmAscent);
1429 output->otmDescent = HDPTOLP(output->otmDescent);
1430 output->otmLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmLineGap));
1431 output->otmsCapEmHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsCapEmHeight));
1432 output->otmsXHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsXHeight));
1433 output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1434 output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1435 output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1436 output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1437 output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1438 output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1439 output->otmMacLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmMacLineGap));
1440 output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1441 output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1442 output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1443 output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1444 output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1445 output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1446 output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1447 output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1448 output->otmsStrikeoutSize = abs(INTERNAL_YDSTOWS(dc,output->otmsStrikeoutSize));
1449 output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1450 output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1451 output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1454 if(output != lpOTM) {
1455 memcpy(lpOTM, output, cbData);
1456 HeapFree(GetProcessHeap(), 0, output);
1462 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1463 but really this should just be a return 0. */
1465 ret = sizeof(*lpOTM);
1470 memset(lpOTM, 0, ret);
1471 lpOTM->otmSize = sizeof(*lpOTM);
1472 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1474 Further fill of the structure not implemented,
1475 Needs real values for the structure members
1485 /***********************************************************************
1486 * GetCharWidthW (GDI32.@)
1487 * GetCharWidth32W (GDI32.@)
1489 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1494 DC * dc = get_dc_ptr( hdc );
1495 if (!dc) return FALSE;
1498 ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1499 else if (dc->funcs->pGetCharWidth)
1500 ret = dc->funcs->pGetCharWidth( dc->physDev, firstChar, lastChar, buffer);
1504 /* convert device units to logical */
1505 for( i = firstChar; i <= lastChar; i++, buffer++ )
1506 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1509 release_dc_ptr( dc );
1514 /***********************************************************************
1515 * GetCharWidthA (GDI32.@)
1516 * GetCharWidth32A (GDI32.@)
1518 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1521 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1526 if(count <= 0) return FALSE;
1528 str = HeapAlloc(GetProcessHeap(), 0, count);
1529 for(i = 0; i < count; i++)
1530 str[i] = (BYTE)(firstChar + i);
1532 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1534 for(i = 0; i < wlen; i++)
1536 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1544 HeapFree(GetProcessHeap(), 0, str);
1545 HeapFree(GetProcessHeap(), 0, wstr);
1551 /***********************************************************************
1552 * ExtTextOutA (GDI32.@)
1556 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1557 const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1565 if (flags & ETO_GLYPH_INDEX)
1566 return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
1568 p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
1571 unsigned int i = 0, j = 0;
1573 lpDxW = HeapAlloc( GetProcessHeap(), 0, wlen*sizeof(INT));
1575 if(IsDBCSLeadByteEx(codepage, str[i])) {
1576 lpDxW[j++] = lpDx[i] + lpDx[i+1];
1579 lpDxW[j++] = lpDx[i];
1585 ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1587 HeapFree( GetProcessHeap(), 0, p );
1588 HeapFree( GetProcessHeap(), 0, lpDxW );
1593 /***********************************************************************
1594 * ExtTextOutW (GDI32.@)
1596 * Draws text using the currently selected font, background color, and text color.
1600 * x,y [I] coordinates of string
1602 * ETO_GRAYED - undocumented on MSDN
1603 * ETO_OPAQUE - use background color for fill the rectangle
1604 * ETO_CLIPPED - clipping text to the rectangle
1605 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1606 * than encoded characters. Implies ETO_IGNORELANGUAGE
1607 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1608 * Affects BiDi ordering
1609 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1610 * ETO_PDY - unimplemented
1611 * ETO_NUMERICSLATIN - unimplemented always assumed -
1612 * do not translate numbers into locale representations
1613 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1614 * lprect [I] dimensions for clipping or/and opaquing
1615 * str [I] text string
1616 * count [I] number of symbols in string
1617 * lpDx [I] optional parameter with distance between drawing characters
1623 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1624 const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1627 LPWSTR reordered_str = (LPWSTR)str;
1628 WORD *glyphs = NULL;
1629 UINT align = GetTextAlign( hdc );
1633 double cosEsc, sinEsc;
1634 INT *deltas = NULL, char_extra;
1637 BOOL done_extents = FALSE;
1638 INT width = 0, xwidth = 0, ywidth = 0;
1640 DC * dc = get_dc_ptr( hdc );
1643 if (!dc) return FALSE;
1645 breakRem = dc->breakRem;
1647 if (flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY))
1648 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY unimplemented\n");
1650 if (!dc->funcs->pExtTextOut && !PATH_IsPathOpen(dc->path))
1652 release_dc_ptr( dc );
1657 type = GetObjectType(hdc);
1658 if(type == OBJ_METADC || type == OBJ_ENHMETADC)
1660 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, flags, lprect, str, count, lpDx);
1661 release_dc_ptr( dc );
1666 flags &= ~ETO_CLIPPED;
1668 if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && count > 0 )
1670 reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1672 BIDI_Reorder( str, count, GCP_REORDER,
1673 ((flags&ETO_RTLREADING)!=0 || (GetTextAlign(hdc)&TA_RTLREADING)!=0)?
1674 WINE_GCPW_FORCE_RTL:WINE_GCPW_FORCE_LTR,
1675 reordered_str, count, NULL );
1677 flags |= ETO_IGNORELANGUAGE;
1680 TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc, x, y, flags,
1681 lprect, debugstr_wn(str, count), count, lpDx);
1683 if(flags & ETO_GLYPH_INDEX)
1684 glyphs = reordered_str;
1687 TRACE("rect: %d,%d - %d,%d\n", lprect->left, lprect->top, lprect->right,
1689 TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
1691 if(align & TA_UPDATECP)
1693 GetCurrentPositionEx( hdc, &pt );
1698 GetTextMetricsW(hdc, &tm);
1699 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1701 if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
1702 lf.lfEscapement = 0;
1704 if(lf.lfEscapement != 0)
1706 cosEsc = cos(lf.lfEscapement * M_PI / 1800);
1707 sinEsc = sin(lf.lfEscapement * M_PI / 1800);
1715 if(flags & (ETO_CLIPPED | ETO_OPAQUE))
1719 if(flags & ETO_GLYPH_INDEX)
1720 GetTextExtentPointI(hdc, glyphs, count, &sz);
1722 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1724 done_extents = TRUE;
1727 rc.right = x + sz.cx;
1728 rc.bottom = y + sz.cy;
1735 LPtoDP(hdc, (POINT*)&rc, 2);
1737 if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
1738 if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
1741 if ((flags & ETO_OPAQUE) && !PATH_IsPathOpen(dc->path))
1742 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1752 LPtoDP(hdc, &pt, 1);
1756 char_extra = GetTextCharacterExtra(hdc);
1757 if(char_extra || dc->breakExtra || breakRem || lpDx || lf.lfEscapement != 0)
1761 deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT));
1762 for(i = 0; i < count; i++)
1764 if(lpDx && (flags & ETO_PDY))
1765 deltas[i] = lpDx[i*2] + char_extra;
1767 deltas[i] = lpDx[i] + char_extra;
1770 if(flags & ETO_GLYPH_INDEX)
1771 GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
1773 GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
1775 deltas[i] = tmpsz.cx;
1778 if (!(flags & ETO_GLYPH_INDEX) && (dc->breakExtra || breakRem) && reordered_str[i] == tm.tmBreakChar)
1780 deltas[i] = deltas[i] + dc->breakExtra;
1787 deltas[i] = INTERNAL_XWSTODS(dc, deltas[i]);
1795 if(flags & ETO_GLYPH_INDEX)
1796 GetTextExtentPointI(hdc, glyphs, count, &sz);
1798 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1799 done_extents = TRUE;
1801 width = INTERNAL_XWSTODS(dc, sz.cx);
1803 xwidth = width * cosEsc;
1804 ywidth = width * sinEsc;
1806 tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
1807 tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
1808 switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
1811 if (align & TA_UPDATECP)
1815 DPtoLP(hdc, &pt, 1);
1816 MoveToEx(hdc, pt.x, pt.y, NULL);
1828 if (align & TA_UPDATECP)
1832 DPtoLP(hdc, &pt, 1);
1833 MoveToEx(hdc, pt.x, pt.y, NULL);
1838 switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
1841 y += tm.tmAscent * cosEsc;
1842 x += tm.tmAscent * sinEsc;
1846 y -= tm.tmDescent * cosEsc;
1847 x -= tm.tmDescent * sinEsc;
1854 if (GetBkMode(hdc) != TRANSPARENT && !PATH_IsPathOpen(dc->path))
1856 if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
1858 if(!(flags & ETO_OPAQUE) || x < rc.left || x + width >= rc.right ||
1859 y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
1863 rc.right = x + width;
1864 rc.top = y - tm.tmAscent;
1865 rc.bottom = y + tm.tmDescent;
1866 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1871 if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
1873 HFONT orig_font = dc->hFont, cur_font;
1875 INT span = 0, *offsets = NULL;
1878 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
1879 for(i = 0; i < count; i++)
1881 WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
1882 if(cur_font != dc->hFont)
1887 offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
1892 for(j = 1; j < count; j++)
1894 GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
1895 offsets[j] = offsets[j-1] + INTERNAL_XWSTODS(dc, tmpsz.cx);
1900 for(j = 1; j < count; j++)
1901 offsets[j] = offsets[j-1] + deltas[j];
1906 if (PATH_IsPathOpen(dc->path))
1907 ret = PATH_ExtTextOut(dc, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
1908 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
1909 glyphs, span, deltas ? deltas + i - span : NULL);
1911 dc->funcs->pExtTextOut(dc->physDev, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
1912 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
1913 glyphs, span, deltas ? deltas + i - span : NULL);
1916 SelectObject(hdc, cur_font);
1918 glyphs[span++] = glyph;
1922 if (PATH_IsPathOpen(dc->path))
1923 ret = PATH_ExtTextOut(dc, x + (offsets ? offsets[count - span] * cosEsc : 0),
1924 y - (offsets ? offsets[count - span] * sinEsc : 0),
1925 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
1926 glyphs, span, deltas ? deltas + count - span : NULL);
1928 ret = dc->funcs->pExtTextOut(dc->physDev, x + (offsets ? offsets[count - span] * cosEsc : 0),
1929 y - (offsets ? offsets[count - span] * sinEsc : 0),
1930 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
1931 glyphs, span, deltas ? deltas + count - span : NULL);
1932 SelectObject(hdc, orig_font);
1933 HeapFree(GetProcessHeap(), 0, offsets);
1939 if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
1941 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
1942 GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
1943 flags |= ETO_GLYPH_INDEX;
1946 if (PATH_IsPathOpen(dc->path))
1947 ret = PATH_ExtTextOut(dc, x, y, (flags & ~ETO_OPAQUE), &rc,
1948 glyphs ? glyphs : reordered_str, count, deltas);
1950 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, (flags & ~ETO_OPAQUE), &rc,
1951 glyphs ? glyphs : reordered_str, count, deltas);
1955 HeapFree(GetProcessHeap(), 0, deltas);
1956 if(glyphs != reordered_str)
1957 HeapFree(GetProcessHeap(), 0, glyphs);
1958 if(reordered_str != str)
1959 HeapFree(GetProcessHeap(), 0, reordered_str);
1961 release_dc_ptr( dc );
1963 if (ret && (lf.lfUnderline || lf.lfStrikeOut))
1965 int underlinePos, strikeoutPos;
1966 int underlineWidth, strikeoutWidth;
1967 UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
1968 OUTLINETEXTMETRICW* otm = NULL;
1973 underlineWidth = tm.tmAscent / 20 + 1;
1974 strikeoutPos = tm.tmAscent / 2;
1975 strikeoutWidth = underlineWidth;
1979 otm = HeapAlloc(GetProcessHeap(), 0, size);
1980 GetOutlineTextMetricsW(hdc, size, otm);
1981 underlinePos = otm->otmsUnderscorePosition;
1982 underlineWidth = otm->otmsUnderscoreSize;
1983 strikeoutPos = otm->otmsStrikeoutPosition;
1984 strikeoutWidth = otm->otmsStrikeoutSize;
1985 HeapFree(GetProcessHeap(), 0, otm);
1988 if (PATH_IsPathOpen(dc->path))
1992 HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
1994 hbrush = SelectObject(hdc, hbrush);
1995 hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
1999 pts[0].x = x - underlinePos * sinEsc;
2000 pts[0].y = y - underlinePos * cosEsc;
2001 pts[1].x = x + xwidth - underlinePos * sinEsc;
2002 pts[1].y = y - ywidth - underlinePos * cosEsc;
2003 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2004 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2005 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2006 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2007 pts[4].x = pts[0].x;
2008 pts[4].y = pts[0].y;
2009 DPtoLP(hdc, pts, 5);
2010 Polygon(hdc, pts, 5);
2015 pts[0].x = x - strikeoutPos * sinEsc;
2016 pts[0].y = y - strikeoutPos * cosEsc;
2017 pts[1].x = x + xwidth - strikeoutPos * sinEsc;
2018 pts[1].y = y - ywidth - strikeoutPos * cosEsc;
2019 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2020 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2021 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2022 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2023 pts[4].x = pts[0].x;
2024 pts[4].y = pts[0].y;
2025 DPtoLP(hdc, pts, 5);
2026 Polygon(hdc, pts, 5);
2029 SelectObject(hdc, hpen);
2030 hbrush = SelectObject(hdc, hbrush);
2031 DeleteObject(hbrush);
2035 POINT pts[2], oldpt;
2040 hpen = CreatePen(PS_SOLID, underlineWidth, GetTextColor(hdc));
2041 hpen = SelectObject(hdc, hpen);
2044 pts[1].x = x + xwidth;
2045 pts[1].y = y - ywidth;
2046 DPtoLP(hdc, pts, 2);
2047 MoveToEx(hdc, pts[0].x - underlinePos * sinEsc, pts[0].y - underlinePos * cosEsc, &oldpt);
2048 LineTo(hdc, pts[1].x - underlinePos * sinEsc, pts[1].y - underlinePos * cosEsc);
2049 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2050 DeleteObject(SelectObject(hdc, hpen));
2055 hpen = CreatePen(PS_SOLID, strikeoutWidth, GetTextColor(hdc));
2056 hpen = SelectObject(hdc, hpen);
2059 pts[1].x = x + xwidth;
2060 pts[1].y = y - ywidth;
2061 DPtoLP(hdc, pts, 2);
2062 MoveToEx(hdc, pts[0].x - strikeoutPos * sinEsc, pts[0].y - strikeoutPos * cosEsc, &oldpt);
2063 LineTo(hdc, pts[1].x - strikeoutPos * sinEsc, pts[1].y - strikeoutPos * cosEsc);
2064 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2065 DeleteObject(SelectObject(hdc, hpen));
2074 /***********************************************************************
2075 * TextOutA (GDI32.@)
2077 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2079 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2083 /***********************************************************************
2084 * TextOutW (GDI32.@)
2086 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2088 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2092 /***********************************************************************
2093 * PolyTextOutA (GDI32.@)
2097 BOOL WINAPI PolyTextOutA( HDC hdc, const POLYTEXTA *pptxt, INT cStrings )
2099 for (; cStrings>0; cStrings--, pptxt++)
2100 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2107 /***********************************************************************
2108 * PolyTextOutW (GDI32.@)
2110 * Draw several Strings
2116 BOOL WINAPI PolyTextOutW( HDC hdc, const POLYTEXTW *pptxt, INT cStrings )
2118 for (; cStrings>0; cStrings--, pptxt++)
2119 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2125 /* FIXME: all following APIs ******************************************/
2128 /***********************************************************************
2129 * SetMapperFlags (GDI32.@)
2131 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
2133 DC *dc = get_dc_ptr( hDC );
2136 if(dc->funcs->pSetMapperFlags)
2138 ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
2139 /* FIXME: ret is just a success flag, we should return a proper value */
2142 FIXME("(%p, 0x%08x): stub - harmless\n", hDC, dwFlag);
2143 release_dc_ptr( dc );
2147 /***********************************************************************
2148 * GetAspectRatioFilterEx (GDI32.@)
2150 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2152 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2157 /***********************************************************************
2158 * GetCharABCWidthsA (GDI32.@)
2160 * See GetCharABCWidthsW.
2162 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2165 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
2170 if(count <= 0) return FALSE;
2172 str = HeapAlloc(GetProcessHeap(), 0, count);
2173 for(i = 0; i < count; i++)
2174 str[i] = (BYTE)(firstChar + i);
2176 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
2178 for(i = 0; i < wlen; i++)
2180 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2188 HeapFree(GetProcessHeap(), 0, str);
2189 HeapFree(GetProcessHeap(), 0, wstr);
2195 /******************************************************************************
2196 * GetCharABCWidthsW [GDI32.@]
2198 * Retrieves widths of characters in range.
2201 * hdc [I] Handle of device context
2202 * firstChar [I] First character in range to query
2203 * lastChar [I] Last character in range to query
2204 * abc [O] Address of character-width structure
2207 * Only works with TrueType fonts
2213 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2216 DC *dc = get_dc_ptr(hdc);
2220 if (!dc) return FALSE;
2224 release_dc_ptr( dc );
2229 ret = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
2235 /* convert device units to logical */
2236 for( i = firstChar; i <= lastChar; i++, abc++ ) {
2237 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2238 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2239 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2244 release_dc_ptr( dc );
2249 /******************************************************************************
2250 * GetCharABCWidthsI [GDI32.@]
2252 * Retrieves widths of characters in range.
2255 * hdc [I] Handle of device context
2256 * firstChar [I] First glyphs in range to query
2257 * count [I] Last glyphs in range to query
2258 * pgi [i] Array of glyphs to query
2259 * abc [O] Address of character-width structure
2262 * Only works with TrueType fonts
2268 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2269 LPWORD pgi, LPABC abc)
2271 DC *dc = get_dc_ptr(hdc);
2275 if (!dc) return FALSE;
2279 release_dc_ptr( dc );
2284 ret = WineEngGetCharABCWidthsI( dc->gdiFont, firstChar, count, pgi, abc );
2290 /* convert device units to logical */
2291 for( i = 0; i < count; i++, abc++ ) {
2292 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2293 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2294 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2299 release_dc_ptr( dc );
2304 /***********************************************************************
2305 * GetGlyphOutlineA (GDI32.@)
2307 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2308 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2309 LPVOID lpBuffer, const MAT2 *lpmat2 )
2315 if(!(fuFormat & GGO_GLYPH_INDEX)) {
2318 if(uChar > 0xff) { /* but, 2 bytes character only */
2320 mbchs[0] = (uChar & 0xff00) >> 8;
2321 mbchs[1] = (uChar & 0xff);
2324 mbchs[0] = (uChar & 0xff);
2326 p = FONT_mbtowc(hdc, mbchs, len, NULL, NULL);
2330 ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
2332 HeapFree(GetProcessHeap(), 0, p);
2336 /***********************************************************************
2337 * GetGlyphOutlineW (GDI32.@)
2339 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2340 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2341 LPVOID lpBuffer, const MAT2 *lpmat2 )
2343 DC *dc = get_dc_ptr(hdc);
2346 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2347 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2349 if(!dc) return GDI_ERROR;
2352 ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
2353 cbBuffer, lpBuffer, lpmat2);
2357 release_dc_ptr( dc );
2362 /***********************************************************************
2363 * CreateScalableFontResourceA (GDI32.@)
2365 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2366 LPCSTR lpszResourceFile,
2367 LPCSTR lpszFontFile,
2368 LPCSTR lpszCurrentPath )
2370 LPWSTR lpszResourceFileW = NULL;
2371 LPWSTR lpszFontFileW = NULL;
2372 LPWSTR lpszCurrentPathW = NULL;
2376 if (lpszResourceFile)
2378 len = MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, NULL, 0);
2379 lpszResourceFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2380 MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, lpszResourceFileW, len);
2385 len = MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, NULL, 0);
2386 lpszFontFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2387 MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, lpszFontFileW, len);
2390 if (lpszCurrentPath)
2392 len = MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, NULL, 0);
2393 lpszCurrentPathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2394 MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, lpszCurrentPathW, len);
2397 ret = CreateScalableFontResourceW(fHidden, lpszResourceFileW,
2398 lpszFontFileW, lpszCurrentPathW);
2400 HeapFree(GetProcessHeap(), 0, lpszResourceFileW);
2401 HeapFree(GetProcessHeap(), 0, lpszFontFileW);
2402 HeapFree(GetProcessHeap(), 0, lpszCurrentPathW);
2407 /***********************************************************************
2408 * CreateScalableFontResourceW (GDI32.@)
2410 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2411 LPCWSTR lpszResourceFile,
2412 LPCWSTR lpszFontFile,
2413 LPCWSTR lpszCurrentPath )
2416 FIXME("(%d,%s,%s,%s): stub\n",
2417 fHidden, debugstr_w(lpszResourceFile), debugstr_w(lpszFontFile),
2418 debugstr_w(lpszCurrentPath) );
2420 /* fHidden=1 - only visible for the calling app, read-only, not
2421 * enumerated with EnumFonts/EnumFontFamilies
2422 * lpszCurrentPath can be NULL
2425 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2426 if ((f = CreateFileW(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2428 SetLastError(ERROR_FILE_EXISTS);
2431 return FALSE; /* create failed */
2434 /*************************************************************************
2435 * GetKerningPairsA (GDI32.@)
2437 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2438 LPKERNINGPAIR kern_pairA )
2443 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2444 KERNINGPAIR *kern_pairW;
2446 if (!cPairs && kern_pairA)
2448 SetLastError(ERROR_INVALID_PARAMETER);
2452 charset = GetTextCharset(hDC);
2453 if (!TranslateCharsetInfo(ULongToPtr(charset), &csi, TCI_SRCCHARSET))
2455 FIXME("Can't find codepage for charset %d\n", charset);
2458 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2459 * to fail on an invalid character for CP_SYMBOL.
2461 cpi.DefaultChar[0] = 0;
2462 if (csi.ciACP != CP_SYMBOL && !GetCPInfo(csi.ciACP, &cpi))
2464 FIXME("Can't find codepage %u info\n", csi.ciACP);
2467 TRACE("charset %d => codepage %u\n", charset, csi.ciACP);
2469 total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2470 if (!total_kern_pairs) return 0;
2472 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2473 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2475 for (i = 0; i < total_kern_pairs; i++)
2479 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2482 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2485 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2490 if (kern_pairs_copied >= cPairs) break;
2492 kern_pairA->wFirst = (BYTE)first;
2493 kern_pairA->wSecond = (BYTE)second;
2494 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2497 kern_pairs_copied++;
2500 HeapFree(GetProcessHeap(), 0, kern_pairW);
2502 return kern_pairs_copied;
2505 /*************************************************************************
2506 * GetKerningPairsW (GDI32.@)
2508 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2509 LPKERNINGPAIR lpKerningPairs )
2514 TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2516 if (!cPairs && lpKerningPairs)
2518 SetLastError(ERROR_INVALID_PARAMETER);
2522 dc = get_dc_ptr(hDC);
2526 ret = WineEngGetKerningPairs(dc->gdiFont, cPairs, lpKerningPairs);
2528 release_dc_ptr( dc );
2532 /*************************************************************************
2533 * TranslateCharsetInfo [GDI32.@]
2535 * Fills a CHARSETINFO structure for a character set, code page, or
2536 * font. This allows making the correspondence between different labels
2537 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2538 * of the same encoding.
2540 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2541 * only one codepage should be set in *lpSrc.
2544 * TRUE on success, FALSE on failure.
2547 BOOL WINAPI TranslateCharsetInfo(
2548 LPDWORD lpSrc, /* [in]
2549 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2550 if flags == TCI_SRCCHARSET: a character set value
2551 if flags == TCI_SRCCODEPAGE: a code page value
2553 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2554 DWORD flags /* [in] determines interpretation of lpSrc */)
2558 case TCI_SRCFONTSIG:
2559 while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
2561 case TCI_SRCCODEPAGE:
2562 while (PtrToUlong(lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
2564 case TCI_SRCCHARSET:
2565 while (PtrToUlong(lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
2570 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2571 *lpCs = FONT_tci[index];
2575 /*************************************************************************
2576 * GetFontLanguageInfo (GDI32.@)
2578 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2580 FONTSIGNATURE fontsig;
2581 static const DWORD GCP_DBCS_MASK=0x003F0000,
2582 GCP_DIACRITIC_MASK=0x00000000,
2583 FLI_GLYPHS_MASK=0x00000000,
2584 GCP_GLYPHSHAPE_MASK=0x00000040,
2585 GCP_KASHIDA_MASK=0x00000000,
2586 GCP_LIGATE_MASK=0x00000000,
2587 GCP_USEKERNING_MASK=0x00000000,
2588 GCP_REORDER_MASK=0x00000060;
2592 GetTextCharsetInfo( hdc, &fontsig, 0 );
2593 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2595 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2598 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2599 result|=GCP_DIACRITIC;
2601 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2604 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2605 result|=GCP_GLYPHSHAPE;
2607 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2608 result|=GCP_KASHIDA;
2610 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2613 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2614 result|=GCP_USEKERNING;
2616 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2617 if( GetTextAlign( hdc) & TA_RTLREADING )
2618 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2619 result|=GCP_REORDER;
2625 /*************************************************************************
2626 * GetFontData [GDI32.@]
2628 * Retrieve data for TrueType font.
2632 * success: Number of bytes returned
2633 * failure: GDI_ERROR
2637 * Calls SetLastError()
2640 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2641 LPVOID buffer, DWORD length)
2643 DC *dc = get_dc_ptr(hdc);
2644 DWORD ret = GDI_ERROR;
2646 if(!dc) return GDI_ERROR;
2649 ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2651 release_dc_ptr( dc );
2655 /*************************************************************************
2656 * GetGlyphIndicesA [GDI32.@]
2658 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2659 LPWORD pgi, DWORD flags)
2665 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2666 hdc, debugstr_an(lpstr, count), count, pgi, flags);
2668 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2669 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2670 HeapFree(GetProcessHeap(), 0, lpstrW);
2675 /*************************************************************************
2676 * GetGlyphIndicesW [GDI32.@]
2678 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2679 LPWORD pgi, DWORD flags)
2681 DC *dc = get_dc_ptr(hdc);
2682 DWORD ret = GDI_ERROR;
2684 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2685 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2687 if(!dc) return GDI_ERROR;
2690 ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2692 release_dc_ptr( dc );
2696 /*************************************************************************
2697 * GetCharacterPlacementA [GDI32.@]
2699 * See GetCharacterPlacementW.
2702 * the web browser control of ie4 calls this with dwFlags=0
2705 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2706 INT nMaxExtent, GCP_RESULTSA *lpResults,
2711 GCP_RESULTSW resultsW;
2715 TRACE("%s, %d, %d, 0x%08x\n",
2716 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2718 /* both structs are equal in size */
2719 memcpy(&resultsW, lpResults, sizeof(resultsW));
2721 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2722 if(lpResults->lpOutString)
2723 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2725 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2727 lpResults->nGlyphs = resultsW.nGlyphs;
2728 lpResults->nMaxFit = resultsW.nMaxFit;
2730 if(lpResults->lpOutString) {
2731 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2732 lpResults->lpOutString, uCount, NULL, NULL );
2735 HeapFree(GetProcessHeap(), 0, lpStringW);
2736 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2741 /*************************************************************************
2742 * GetCharacterPlacementW [GDI32.@]
2744 * Retrieve information about a string. This includes the width, reordering,
2745 * Glyphing and so on.
2749 * The width and height of the string if successful, 0 if failed.
2753 * All flags except GCP_REORDER are not yet implemented.
2754 * Reordering is not 100% compliant to the Windows BiDi method.
2755 * Caret positioning is not yet implemented for BiDi.
2756 * Classes are not yet implemented.
2760 GetCharacterPlacementW(
2761 HDC hdc, /* [in] Device context for which the rendering is to be done */
2762 LPCWSTR lpString, /* [in] The string for which information is to be returned */
2763 INT uCount, /* [in] Number of WORDS in string. */
2764 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
2765 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2766 DWORD dwFlags /* [in] Flags specifying how to process the string */
2773 TRACE("%s, %d, %d, 0x%08x\n",
2774 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2776 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2777 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2778 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2779 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2780 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2782 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08x ignored\n", dwFlags);
2783 if(lpResults->lpClass) FIXME("classes not implemented\n");
2784 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2785 FIXME("Caret positions for complex scripts not implemented\n");
2787 nSet = (UINT)uCount;
2788 if(nSet > lpResults->nGlyphs)
2789 nSet = lpResults->nGlyphs;
2791 /* return number of initialized fields */
2792 lpResults->nGlyphs = nSet;
2794 if((dwFlags&GCP_REORDER)==0 )
2796 /* Treat the case where no special handling was requested in a fastpath way */
2797 /* copy will do if the GCP_REORDER flag is not set */
2798 if(lpResults->lpOutString)
2799 memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
2801 if(lpResults->lpOrder)
2803 for(i = 0; i < nSet; i++)
2804 lpResults->lpOrder[i] = i;
2808 BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
2809 nSet, lpResults->lpOrder );
2812 /* FIXME: Will use the placement chars */
2813 if (lpResults->lpDx)
2816 for (i = 0; i < nSet; i++)
2818 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
2819 lpResults->lpDx[i]= c;
2823 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
2827 lpResults->lpCaretPos[0] = 0;
2828 for (i = 1; i < nSet; i++)
2829 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
2830 lpResults->lpCaretPos[i] = (pos += size.cx);
2833 if(lpResults->lpGlyphs)
2834 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
2836 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
2837 ret = MAKELONG(size.cx, size.cy);
2842 /*************************************************************************
2843 * GetCharABCWidthsFloatA [GDI32.@]
2845 * See GetCharABCWidthsFloatW.
2847 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
2849 INT i, wlen, count = (INT)(last - first + 1);
2854 if (count <= 0) return FALSE;
2856 str = HeapAlloc(GetProcessHeap(), 0, count);
2858 for(i = 0; i < count; i++)
2859 str[i] = (BYTE)(first + i);
2861 wstr = FONT_mbtowc( hdc, str, count, &wlen, NULL );
2863 for (i = 0; i < wlen; i++)
2865 if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
2873 HeapFree( GetProcessHeap(), 0, str );
2874 HeapFree( GetProcessHeap(), 0, wstr );
2879 /*************************************************************************
2880 * GetCharABCWidthsFloatW [GDI32.@]
2882 * Retrieves widths of a range of characters.
2885 * hdc [I] Handle to device context.
2886 * first [I] First character in range to query.
2887 * last [I] Last character in range to query.
2888 * abcf [O] Array of LPABCFLOAT structures.
2895 * Only works with TrueType fonts. It also doesn't return real
2896 * floats but converted integers because it's implemented on
2897 * top of GetCharABCWidthsW.
2899 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
2902 unsigned int i, size = sizeof(ABC) * (last - first + 1);
2905 TRACE("%p, %d, %d, %p - partial stub\n", hdc, first, last, abcf);
2907 abc = HeapAlloc( GetProcessHeap(), 0, size );
2908 if (!abc) return FALSE;
2910 ret = GetCharABCWidthsW( hdc, first, last, abc );
2913 for (i = first; i <= last; i++, abc++, abcf++)
2915 abcf->abcfA = abc->abcA;
2916 abcf->abcfB = abc->abcB;
2917 abcf->abcfC = abc->abcC;
2920 HeapFree( GetProcessHeap(), 0, abc );
2924 /*************************************************************************
2925 * GetCharWidthFloatA [GDI32.@]
2927 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
2928 UINT iLastChar, PFLOAT pxBuffer)
2930 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
2934 /*************************************************************************
2935 * GetCharWidthFloatW [GDI32.@]
2937 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
2938 UINT iLastChar, PFLOAT pxBuffer)
2940 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
2945 /***********************************************************************
2947 * Font Resource API *
2949 ***********************************************************************/
2951 /***********************************************************************
2952 * AddFontResourceA (GDI32.@)
2954 INT WINAPI AddFontResourceA( LPCSTR str )
2956 return AddFontResourceExA( str, 0, NULL);
2959 /***********************************************************************
2960 * AddFontResourceW (GDI32.@)
2962 INT WINAPI AddFontResourceW( LPCWSTR str )
2964 return AddFontResourceExW(str, 0, NULL);
2968 /***********************************************************************
2969 * AddFontResourceExA (GDI32.@)
2971 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
2973 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
2974 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2977 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
2978 ret = AddFontResourceExW(strW, fl, pdv);
2979 HeapFree(GetProcessHeap(), 0, strW);
2983 static BOOL CALLBACK load_enumed_resource(HMODULE hModule, LPCWSTR type, LPWSTR name, LONG_PTR lParam)
2985 HRSRC rsrc = FindResourceW(hModule, name, type);
2986 HGLOBAL hMem = LoadResource(hModule, rsrc);
2987 LPVOID *pMem = LockResource(hMem);
2988 int *num_total = (int *)lParam;
2991 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type));
2992 if (!AddFontMemResourceEx(pMem, SizeofResource(hModule, rsrc), NULL, &num_in_res))
2994 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule, hMem);
2998 *num_total += num_in_res;
3002 /***********************************************************************
3003 * AddFontResourceExW (GDI32.@)
3005 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3007 int ret = WineEngAddFontResourceEx(str, fl, pdv);
3010 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3011 HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
3012 if (hModule != NULL)
3014 int num_resources = 0;
3015 LPWSTR rt_font = (LPWSTR)((ULONG_PTR)8); /* we don't want to include winuser.h */
3017 TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3018 wine_dbgstr_w(str));
3019 if (EnumResourceNamesW(hModule, rt_font, load_enumed_resource, (LONG_PTR)&num_resources))
3020 ret = num_resources;
3021 FreeLibrary(hModule);
3027 /***********************************************************************
3028 * RemoveFontResourceA (GDI32.@)
3030 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3032 return RemoveFontResourceExA(str, 0, 0);
3035 /***********************************************************************
3036 * RemoveFontResourceW (GDI32.@)
3038 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3040 return RemoveFontResourceExW(str, 0, 0);
3043 /***********************************************************************
3044 * AddFontMemResourceEx (GDI32.@)
3046 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3048 return WineEngAddFontMemResourceEx(pbFont, cbFont, pdv, pcFonts);
3051 /***********************************************************************
3052 * RemoveFontMemResourceEx (GDI32.@)
3054 BOOL WINAPI RemoveFontMemResourceEx( HANDLE fh )
3056 FIXME("(%p) stub\n", fh);
3060 /***********************************************************************
3061 * RemoveFontResourceExA (GDI32.@)
3063 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3065 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3066 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3069 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3070 ret = RemoveFontResourceExW(strW, fl, pdv);
3071 HeapFree(GetProcessHeap(), 0, strW);
3075 /***********************************************************************
3076 * RemoveFontResourceExW (GDI32.@)
3078 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3080 return WineEngRemoveFontResourceEx(str, fl, pdv);
3083 /***********************************************************************
3084 * GetTextCharset (GDI32.@)
3086 UINT WINAPI GetTextCharset(HDC hdc)
3088 /* MSDN docs say this is equivalent */
3089 return GetTextCharsetInfo(hdc, NULL, 0);
3092 /***********************************************************************
3093 * GetTextCharsetInfo (GDI32.@)
3095 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3097 UINT ret = DEFAULT_CHARSET;
3098 DC *dc = get_dc_ptr(hdc);
3103 ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
3105 release_dc_ptr( dc );
3108 if (ret == DEFAULT_CHARSET && fs)
3109 memset(fs, 0, sizeof(FONTSIGNATURE));
3113 /***********************************************************************
3114 * GdiGetCharDimensions (GDI32.@)
3116 * Gets the average width of the characters in the English alphabet.
3119 * hdc [I] Handle to the device context to measure on.
3120 * lptm [O] Pointer to memory to store the text metrics into.
3121 * height [O] On exit, the maximum height of characters in the English alphabet.
3124 * The average width of characters in the English alphabet.
3127 * This function is used by the dialog manager to get the size of a dialog
3128 * unit. It should also be used by other pieces of code that need to know
3129 * the size of a dialog unit in logical units without having access to the
3130 * window handle of the dialog.
3131 * Windows caches the font metrics from this function, but we don't and
3132 * there doesn't appear to be an immediate advantage to do so.
3135 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3137 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3140 static const WCHAR alphabet[] = {
3141 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3142 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3143 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3145 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3147 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3149 if (height) *height = sz.cy;
3150 return (sz.cx / 26 + 1) / 2;
3153 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3155 FIXME("(%d): stub\n", fEnableEUDC);
3159 /***********************************************************************
3160 * GetCharWidthI (GDI32.@)
3162 * Retrieve widths of characters.
3165 * hdc [I] Handle to a device context.
3166 * first [I] First glyph in range to query.
3167 * count [I] Number of glyph indices to query.
3168 * glyphs [I] Array of glyphs to query.
3169 * buffer [O] Buffer to receive character widths.
3172 * Only works with TrueType fonts.
3178 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3183 TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3185 if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3188 if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3190 HeapFree(GetProcessHeap(), 0, abc);
3194 for (i = 0; i < count; i++)
3195 buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3197 HeapFree(GetProcessHeap(), 0, abc);
3201 /***********************************************************************
3202 * GetFontUnicodeRanges (GDI32.@)
3204 * Retrieve a list of supported Unicode characters in a font.
3207 * hdc [I] Handle to a device context.
3208 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3211 * Success: Number of bytes written to the buffer pointed to by lpgs.
3215 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3218 DC *dc = get_dc_ptr(hdc);
3220 TRACE("(%p, %p)\n", hdc, lpgs);
3224 if (dc->gdiFont) ret = WineEngGetFontUnicodeRanges(dc->gdiFont, lpgs);
3230 /*************************************************************
3231 * FontIsLinked (GDI32.@)
3233 BOOL WINAPI FontIsLinked(HDC hdc)
3235 DC *dc = get_dc_ptr(hdc);
3238 if (!dc) return FALSE;
3239 if (dc->gdiFont) ret = WineEngFontIsLinked(dc->gdiFont);
3241 TRACE("returning %d\n", ret);
3245 /*************************************************************
3246 * GdiRealizationInfo (GDI32.@)
3248 * Returns a structure that contains some font information.
3252 DWORD flags; /* 1 for bitmap fonts, 3 for scalable fonts */
3253 DWORD unknown1; /* keeps incrementing - num of fonts that have been created or selected into a dc ?? */
3254 DWORD unknown2; /* fixed for a given font - looks like it could be the order of the face in the font list or the order
3255 in which the face was first rendered. */
3256 } realization_info_t;
3258 BOOL WINAPI GdiRealizationInfo(HDC hdc, realization_info_t *info)
3261 FIXME("(%p, %p): stub!\n", hdc, info);
3264 otm_size = GetOutlineTextMetricsW(hdc, 0, NULL);
3265 if(otm_size) info->flags |= 2; /* scalable */
3267 info->unknown1 = -1;
3268 info->unknown2 = -1;