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, void *obj, HDC hdc );
90 static INT FONT_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
91 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
92 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
93 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj );
95 static const struct gdi_obj_funcs font_funcs =
97 FONT_SelectObject, /* pSelectObject */
98 FONT_GetObject16, /* pGetObject16 */
99 FONT_GetObjectA, /* pGetObjectA */
100 FONT_GetObjectW, /* pGetObjectW */
101 NULL, /* pUnrealizeObject */
102 FONT_DeleteObject /* pDeleteObject */
105 #define ENUM_UNICODE 0x00000001
106 #define ENUM_CALLED 0x00000002
116 LPLOGFONT16 lpLogFontParam;
117 FONTENUMPROC16 lpEnumFunc;
120 LPNEWTEXTMETRICEX16 lpTextMetric;
121 LPENUMLOGFONTEX16 lpLogFont;
122 SEGPTR segTextMetric;
132 LPLOGFONTW lpLogFontParam;
133 FONTENUMPROCW lpEnumFunc;
142 * For TranslateCharsetInfo
144 #define FS(x) {{0,0,0,0},{0x1<<(x),0}}
145 #define MAXTCIINDEX 32
146 static const CHARSETINFO FONT_tci[MAXTCIINDEX] = {
148 { ANSI_CHARSET, 1252, FS(0)},
149 { EASTEUROPE_CHARSET, 1250, FS(1)},
150 { RUSSIAN_CHARSET, 1251, FS(2)},
151 { GREEK_CHARSET, 1253, FS(3)},
152 { TURKISH_CHARSET, 1254, FS(4)},
153 { HEBREW_CHARSET, 1255, FS(5)},
154 { ARABIC_CHARSET, 1256, FS(6)},
155 { BALTIC_CHARSET, 1257, FS(7)},
156 { VIETNAMESE_CHARSET, 1258, FS(8)},
157 /* reserved by ANSI */
158 { DEFAULT_CHARSET, 0, FS(0)},
159 { DEFAULT_CHARSET, 0, FS(0)},
160 { DEFAULT_CHARSET, 0, FS(0)},
161 { DEFAULT_CHARSET, 0, FS(0)},
162 { DEFAULT_CHARSET, 0, FS(0)},
163 { DEFAULT_CHARSET, 0, FS(0)},
164 { DEFAULT_CHARSET, 0, FS(0)},
166 { THAI_CHARSET, 874, FS(16)},
167 { SHIFTJIS_CHARSET, 932, FS(17)},
168 { GB2312_CHARSET, 936, FS(18)},
169 { HANGEUL_CHARSET, 949, FS(19)},
170 { CHINESEBIG5_CHARSET, 950, FS(20)},
171 { JOHAB_CHARSET, 1361, FS(21)},
172 /* reserved for alternate ANSI and OEM */
173 { DEFAULT_CHARSET, 0, FS(0)},
174 { DEFAULT_CHARSET, 0, FS(0)},
175 { DEFAULT_CHARSET, 0, FS(0)},
176 { DEFAULT_CHARSET, 0, FS(0)},
177 { DEFAULT_CHARSET, 0, FS(0)},
178 { DEFAULT_CHARSET, 0, FS(0)},
179 { DEFAULT_CHARSET, 0, FS(0)},
180 { DEFAULT_CHARSET, 0, FS(0)},
181 /* reserved for system */
182 { DEFAULT_CHARSET, 0, FS(0)},
183 { SYMBOL_CHARSET, CP_SYMBOL, FS(31)},
186 /***********************************************************************
187 * LOGFONT conversion functions.
189 static void FONT_LogFontWTo16( const LOGFONTW* font32, LPLOGFONT16 font16 )
191 font16->lfHeight = font32->lfHeight;
192 font16->lfWidth = font32->lfWidth;
193 font16->lfEscapement = font32->lfEscapement;
194 font16->lfOrientation = font32->lfOrientation;
195 font16->lfWeight = font32->lfWeight;
196 font16->lfItalic = font32->lfItalic;
197 font16->lfUnderline = font32->lfUnderline;
198 font16->lfStrikeOut = font32->lfStrikeOut;
199 font16->lfCharSet = font32->lfCharSet;
200 font16->lfOutPrecision = font32->lfOutPrecision;
201 font16->lfClipPrecision = font32->lfClipPrecision;
202 font16->lfQuality = font32->lfQuality;
203 font16->lfPitchAndFamily = font32->lfPitchAndFamily;
204 WideCharToMultiByte( CP_ACP, 0, font32->lfFaceName, -1,
205 font16->lfFaceName, LF_FACESIZE, NULL, NULL );
206 font16->lfFaceName[LF_FACESIZE-1] = 0;
209 static void FONT_LogFont16ToW( const LOGFONT16 *font16, LPLOGFONTW font32 )
211 font32->lfHeight = font16->lfHeight;
212 font32->lfWidth = font16->lfWidth;
213 font32->lfEscapement = font16->lfEscapement;
214 font32->lfOrientation = font16->lfOrientation;
215 font32->lfWeight = font16->lfWeight;
216 font32->lfItalic = font16->lfItalic;
217 font32->lfUnderline = font16->lfUnderline;
218 font32->lfStrikeOut = font16->lfStrikeOut;
219 font32->lfCharSet = font16->lfCharSet;
220 font32->lfOutPrecision = font16->lfOutPrecision;
221 font32->lfClipPrecision = font16->lfClipPrecision;
222 font32->lfQuality = font16->lfQuality;
223 font32->lfPitchAndFamily = font16->lfPitchAndFamily;
224 MultiByteToWideChar( CP_ACP, 0, font16->lfFaceName, -1, font32->lfFaceName, LF_FACESIZE );
225 font32->lfFaceName[LF_FACESIZE-1] = 0;
228 static void FONT_LogFontAToW( const LOGFONTA *fontA, LPLOGFONTW fontW )
230 memcpy(fontW, fontA, sizeof(LOGFONTA) - LF_FACESIZE);
231 MultiByteToWideChar(CP_ACP, 0, fontA->lfFaceName, -1, fontW->lfFaceName,
233 fontW->lfFaceName[LF_FACESIZE-1] = 0;
236 static void FONT_LogFontWToA( const LOGFONTW *fontW, LPLOGFONTA fontA )
238 memcpy(fontA, fontW, sizeof(LOGFONTA) - LF_FACESIZE);
239 WideCharToMultiByte(CP_ACP, 0, fontW->lfFaceName, -1, fontA->lfFaceName,
240 LF_FACESIZE, NULL, NULL);
241 fontA->lfFaceName[LF_FACESIZE-1] = 0;
244 static void FONT_EnumLogFontExWTo16( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEX16 font16 )
246 FONT_LogFontWTo16( (const LOGFONTW *)fontW, (LPLOGFONT16)font16);
248 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
249 (LPSTR) font16->elfFullName, LF_FULLFACESIZE, NULL, NULL );
250 font16->elfFullName[LF_FULLFACESIZE-1] = '\0';
251 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
252 (LPSTR) font16->elfStyle, LF_FACESIZE, NULL, NULL );
253 font16->elfStyle[LF_FACESIZE-1] = '\0';
254 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
255 (LPSTR) font16->elfScript, LF_FACESIZE, NULL, NULL );
256 font16->elfScript[LF_FACESIZE-1] = '\0';
259 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEXA fontA )
261 FONT_LogFontWToA( (const LOGFONTW *)fontW, (LPLOGFONTA)fontA);
263 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
264 (LPSTR) fontA->elfFullName, LF_FULLFACESIZE, NULL, NULL );
265 fontA->elfFullName[LF_FULLFACESIZE-1] = '\0';
266 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
267 (LPSTR) fontA->elfStyle, LF_FACESIZE, NULL, NULL );
268 fontA->elfStyle[LF_FACESIZE-1] = '\0';
269 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
270 (LPSTR) fontA->elfScript, LF_FACESIZE, NULL, NULL );
271 fontA->elfScript[LF_FACESIZE-1] = '\0';
274 /***********************************************************************
275 * TEXTMETRIC conversion functions.
277 static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
279 ptmA->tmHeight = ptmW->tmHeight;
280 ptmA->tmAscent = ptmW->tmAscent;
281 ptmA->tmDescent = ptmW->tmDescent;
282 ptmA->tmInternalLeading = ptmW->tmInternalLeading;
283 ptmA->tmExternalLeading = ptmW->tmExternalLeading;
284 ptmA->tmAveCharWidth = ptmW->tmAveCharWidth;
285 ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth;
286 ptmA->tmWeight = ptmW->tmWeight;
287 ptmA->tmOverhang = ptmW->tmOverhang;
288 ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX;
289 ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
290 ptmA->tmFirstChar = ptmW->tmFirstChar > 255 ? 255 : ptmW->tmFirstChar;
291 ptmA->tmLastChar = ptmW->tmLastChar > 255 ? 255 : ptmW->tmLastChar;
292 ptmA->tmDefaultChar = ptmW->tmDefaultChar > 255 ? 255 : ptmW->tmDefaultChar;
293 ptmA->tmBreakChar = ptmW->tmBreakChar > 255 ? 255 : ptmW->tmBreakChar;
294 ptmA->tmItalic = ptmW->tmItalic;
295 ptmA->tmUnderlined = ptmW->tmUnderlined;
296 ptmA->tmStruckOut = ptmW->tmStruckOut;
297 ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
298 ptmA->tmCharSet = ptmW->tmCharSet;
302 static void FONT_NewTextMetricExWTo16(const NEWTEXTMETRICEXW *ptmW, LPNEWTEXTMETRICEX16 ptm16 )
304 ptm16->ntmTm.tmHeight = ptmW->ntmTm.tmHeight;
305 ptm16->ntmTm.tmAscent = ptmW->ntmTm.tmAscent;
306 ptm16->ntmTm.tmDescent = ptmW->ntmTm.tmDescent;
307 ptm16->ntmTm.tmInternalLeading = ptmW->ntmTm.tmInternalLeading;
308 ptm16->ntmTm.tmExternalLeading = ptmW->ntmTm.tmExternalLeading;
309 ptm16->ntmTm.tmAveCharWidth = ptmW->ntmTm.tmAveCharWidth;
310 ptm16->ntmTm.tmMaxCharWidth = ptmW->ntmTm.tmMaxCharWidth;
311 ptm16->ntmTm.tmWeight = ptmW->ntmTm.tmWeight;
312 ptm16->ntmTm.tmOverhang = ptmW->ntmTm.tmOverhang;
313 ptm16->ntmTm.tmDigitizedAspectX = ptmW->ntmTm.tmDigitizedAspectX;
314 ptm16->ntmTm.tmDigitizedAspectY = ptmW->ntmTm.tmDigitizedAspectY;
315 ptm16->ntmTm.tmFirstChar = ptmW->ntmTm.tmFirstChar > 255 ? 255 : ptmW->ntmTm.tmFirstChar;
316 ptm16->ntmTm.tmLastChar = ptmW->ntmTm.tmLastChar > 255 ? 255 : ptmW->ntmTm.tmLastChar;
317 ptm16->ntmTm.tmDefaultChar = ptmW->ntmTm.tmDefaultChar > 255 ? 255 : ptmW->ntmTm.tmDefaultChar;
318 ptm16->ntmTm.tmBreakChar = ptmW->ntmTm.tmBreakChar > 255 ? 255 : ptmW->ntmTm.tmBreakChar;
319 ptm16->ntmTm.tmItalic = ptmW->ntmTm.tmItalic;
320 ptm16->ntmTm.tmUnderlined = ptmW->ntmTm.tmUnderlined;
321 ptm16->ntmTm.tmStruckOut = ptmW->ntmTm.tmStruckOut;
322 ptm16->ntmTm.tmPitchAndFamily = ptmW->ntmTm.tmPitchAndFamily;
323 ptm16->ntmTm.tmCharSet = ptmW->ntmTm.tmCharSet;
324 ptm16->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
325 ptm16->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
326 ptm16->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
327 ptm16->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
328 memcpy(&ptm16->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
331 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW *ptmW, NEWTEXTMETRICEXA *ptmA )
333 FONT_TextMetricWToA((const TEXTMETRICW *)ptmW, (LPTEXTMETRICA)ptmA);
334 ptmA->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
335 ptmA->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
336 ptmA->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
337 ptmA->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
338 memcpy(&ptmA->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
342 /***********************************************************************
345 * Returns a Unicode translation of str using the charset of the
346 * currently selected font in hdc. If count is -1 then str is assumed
347 * to be '\0' terminated, otherwise it contains the number of bytes to
348 * convert. If plenW is non-NULL, on return it will point to the
349 * number of WCHARs that have been written. If pCP is non-NULL, on
350 * return it will point to the codepage used in the conversion. The
351 * caller should free the returned LPWSTR from the process heap
354 static LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
360 int charset = GetTextCharset(hdc);
362 /* Hmm, nicely designed api this one! */
363 if(TranslateCharsetInfo((DWORD*)charset, &csi, TCI_SRCCHARSET))
370 case DEFAULT_CHARSET:
381 /* FIXME: These have no place here, but because x11drv
382 enumerates fonts with these (made up) charsets some apps
383 might use them and then the FIXME below would become
384 annoying. Now we could pick the intended codepage for
385 each of these, but since it's broken anyway we'll just
386 use CP_ACP and hope it'll go away...
392 FIXME("Can't find codepage for charset %d\n", charset);
397 TRACE("charset %d => cp %d\n", charset, cp);
399 if(count == -1) count = strlen(str);
400 lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
401 strW = HeapAlloc(GetProcessHeap(), 0, lenW*sizeof(WCHAR));
402 MultiByteToWideChar(cp, 0, str, count, strW, lenW);
403 TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW));
404 if(plenW) *plenW = lenW;
410 /***********************************************************************
411 * CreateFontIndirectA (GDI32.@)
413 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *plfA )
418 FONT_LogFontAToW( plfA, &lfW );
419 return CreateFontIndirectW( &lfW );
421 return CreateFontIndirectW( NULL );
425 /***********************************************************************
426 * CreateFontIndirectW (GDI32.@)
428 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
435 if ((fontPtr = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC,
436 (HGDIOBJ *)&hFont, &font_funcs )))
438 static const WCHAR ItalicW[] = {' ','I','t','a','l','i','c','\0'};
439 static const WCHAR BoldW[] = {' ','B','o','l','d','\0'};
440 WCHAR *pFaceNameItalicSuffix, *pFaceNameBoldSuffix;
441 WCHAR* pFaceNameSuffix = NULL;
443 memcpy( &fontPtr->logfont, plf, sizeof(LOGFONTW) );
445 TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
446 plf->lfHeight, plf->lfWidth,
447 plf->lfEscapement, plf->lfOrientation,
448 plf->lfPitchAndFamily,
449 plf->lfOutPrecision, plf->lfClipPrecision,
450 plf->lfQuality, plf->lfCharSet,
451 debugstr_w(plf->lfFaceName),
452 plf->lfWeight > 400 ? "Bold" : "",
453 plf->lfItalic ? "Italic" : "",
454 plf->lfUnderline ? "Underline" : "", hFont);
456 if (plf->lfEscapement != plf->lfOrientation) {
457 /* this should really depend on whether GM_ADVANCED is set */
458 fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
459 WARN("orientation angle %f set to "
460 "escapement angle %f for new font %p\n",
461 plf->lfOrientation/10., plf->lfEscapement/10., hFont);
464 pFaceNameItalicSuffix = strstrW(fontPtr->logfont.lfFaceName, ItalicW);
465 if (pFaceNameItalicSuffix) {
466 fontPtr->logfont.lfItalic = TRUE;
467 pFaceNameSuffix = pFaceNameItalicSuffix;
470 pFaceNameBoldSuffix = strstrW(fontPtr->logfont.lfFaceName, BoldW);
471 if (pFaceNameBoldSuffix) {
472 if (fontPtr->logfont.lfWeight < FW_BOLD) {
473 fontPtr->logfont.lfWeight = FW_BOLD;
475 if (!pFaceNameSuffix ||
476 (pFaceNameBoldSuffix < pFaceNameSuffix)) {
477 pFaceNameSuffix = pFaceNameBoldSuffix;
481 if (pFaceNameSuffix) *pFaceNameSuffix = 0;
483 GDI_ReleaseObj( hFont );
486 else WARN("(NULL) => NULL\n");
491 /*************************************************************************
492 * CreateFontA (GDI32.@)
494 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
495 INT orient, INT weight, DWORD italic,
496 DWORD underline, DWORD strikeout, DWORD charset,
497 DWORD outpres, DWORD clippres, DWORD quality,
498 DWORD pitch, LPCSTR name )
502 logfont.lfHeight = height;
503 logfont.lfWidth = width;
504 logfont.lfEscapement = esc;
505 logfont.lfOrientation = orient;
506 logfont.lfWeight = weight;
507 logfont.lfItalic = italic;
508 logfont.lfUnderline = underline;
509 logfont.lfStrikeOut = strikeout;
510 logfont.lfCharSet = charset;
511 logfont.lfOutPrecision = outpres;
512 logfont.lfClipPrecision = clippres;
513 logfont.lfQuality = quality;
514 logfont.lfPitchAndFamily = pitch;
517 lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
519 logfont.lfFaceName[0] = '\0';
521 return CreateFontIndirectA( &logfont );
524 /*************************************************************************
525 * CreateFontW (GDI32.@)
527 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
528 INT orient, INT weight, DWORD italic,
529 DWORD underline, DWORD strikeout, DWORD charset,
530 DWORD outpres, DWORD clippres, DWORD quality,
531 DWORD pitch, LPCWSTR name )
535 logfont.lfHeight = height;
536 logfont.lfWidth = width;
537 logfont.lfEscapement = esc;
538 logfont.lfOrientation = orient;
539 logfont.lfWeight = weight;
540 logfont.lfItalic = italic;
541 logfont.lfUnderline = underline;
542 logfont.lfStrikeOut = strikeout;
543 logfont.lfCharSet = charset;
544 logfont.lfOutPrecision = outpres;
545 logfont.lfClipPrecision = clippres;
546 logfont.lfQuality = quality;
547 logfont.lfPitchAndFamily = pitch;
550 lstrcpynW(logfont.lfFaceName, name,
551 sizeof(logfont.lfFaceName) / sizeof(WCHAR));
553 logfont.lfFaceName[0] = '\0';
555 return CreateFontIndirectW( &logfont );
559 /***********************************************************************
562 * If the driver supports vector fonts we create a gdi font first and
563 * then call the driver to give it a chance to supply its own device
564 * font. If the driver wants to do this it returns TRUE and we can
565 * delete the gdi font, if the driver wants to use the gdi font it
566 * should return FALSE, to signal an error return GDI_ERROR. For
567 * drivers that don't support vector fonts they must supply their own
570 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, void *obj, HDC hdc )
573 DC *dc = DC_GetDCPtr( hdc );
577 if (dc->hFont != handle || dc->gdiFont == NULL)
579 if(GetDeviceCaps(dc->hSelf, TEXTCAPS) & TC_VA_ABLE)
580 dc->gdiFont = WineEngCreateFontInstance(dc, handle);
583 if (dc->funcs->pSelectFont) ret = dc->funcs->pSelectFont( dc->physDev, handle, dc->gdiFont );
585 if (ret && dc->gdiFont) dc->gdiFont = 0;
587 if (ret == HGDI_ERROR)
588 ret = 0; /* SelectObject returns 0 on error */
594 GDI_ReleaseObj( hdc );
599 /***********************************************************************
602 static INT FONT_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
607 FONT_LogFontWTo16( &font->logfont, &lf16 );
609 if (count > sizeof(LOGFONT16)) count = sizeof(LOGFONT16);
610 memcpy( buffer, &lf16, count );
614 /***********************************************************************
617 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
624 FONT_LogFontWToA( &font->logfont, &lfA );
626 if (count > sizeof(lfA)) count = sizeof(lfA);
627 memcpy( buffer, &lfA, count );
631 /***********************************************************************
634 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
638 return sizeof(LOGFONTW);
639 if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
640 memcpy( buffer, &font->logfont, count );
645 /***********************************************************************
648 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj )
650 WineEngDestroyFontInstance( handle );
651 return GDI_FreeObject( handle, obj );
655 /***********************************************************************
656 * FONT_EnumInstance16
658 * Called by the device driver layer to pass font info
659 * down to the application.
661 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
662 * We have to use other types because of the FONTENUMPROCW definition.
664 static INT CALLBACK FONT_EnumInstance16( const LOGFONTW *plf, const TEXTMETRICW *ptm,
665 DWORD fType, LPARAM lp )
667 fontEnum16 *pfe = (fontEnum16*)lp;
671 if( pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
672 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet )
677 FONT_EnumLogFontExWTo16((const ENUMLOGFONTEXW *)plf, pfe->lpLogFont);
678 FONT_NewTextMetricExWTo16((const NEWTEXTMETRICEXW *)ptm, pfe->lpTextMetric);
679 pfe->dwFlags |= ENUM_CALLED;
680 GDI_ReleaseObj( pfe->hdc ); /* release the GDI lock */
682 args[6] = SELECTOROF(pfe->segLogFont);
683 args[5] = OFFSETOF(pfe->segLogFont);
684 args[4] = SELECTOROF(pfe->segTextMetric);
685 args[3] = OFFSETOF(pfe->segTextMetric);
687 args[1] = HIWORD(pfe->lpData);
688 args[0] = LOWORD(pfe->lpData);
689 WOWCallback16Ex( (DWORD)pfe->lpEnumFunc, WCB16_PASCAL, sizeof(args), args, &result );
690 ret = LOWORD(result);
692 /* get the lock again and make sure the DC is still valid */
693 dc = DC_GetDCPtr( pfe->hdc );
694 if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
696 if (dc) GDI_ReleaseObj( pfe->hdc );
697 pfe->hdc = 0; /* make sure we don't try to release it later on */
704 /***********************************************************************
707 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
708 * We have to use other types because of the FONTENUMPROCW definition.
710 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
711 DWORD fType, LPARAM lp )
713 fontEnum32 *pfe = (fontEnum32*)lp;
717 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
718 if((pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
719 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
720 (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
722 /* convert font metrics */
723 ENUMLOGFONTEXA logfont;
724 NEWTEXTMETRICEXA tmA;
726 pfe->dwFlags |= ENUM_CALLED;
727 if (!(pfe->dwFlags & ENUM_UNICODE))
729 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
730 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
731 plf = (LOGFONTW *)&logfont.elfLogFont;
732 ptm = (TEXTMETRICW *)&tmA;
734 GDI_ReleaseObj( pfe->hdc ); /* release the GDI lock */
736 ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
738 /* get the lock again and make sure the DC is still valid */
739 dc = DC_GetDCPtr( pfe->hdc );
740 if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
742 if (dc) GDI_ReleaseObj( pfe->hdc );
743 pfe->hdc = 0; /* make sure we don't try to release it later on */
750 /***********************************************************************
751 * EnumFontFamiliesEx (GDI.613)
753 INT16 WINAPI EnumFontFamiliesEx16( HDC16 hDC, LPLOGFONT16 plf,
754 FONTENUMPROC16 efproc, LPARAM lParam,
759 DC* dc = DC_GetDCPtr( HDC_32(hDC) );
760 NEWTEXTMETRICEX16 tm16;
761 ENUMLOGFONTEX16 lf16;
766 FONT_LogFont16ToW(plf, &lfW);
768 fe16.hdc = HDC_32(hDC);
770 fe16.physDev = dc->physDev;
771 fe16.lpLogFontParam = plf;
772 fe16.lpEnumFunc = efproc;
773 fe16.lpData = lParam;
774 fe16.lpTextMetric = &tm16;
775 fe16.lpLogFont = &lf16;
776 fe16.segTextMetric = MapLS( &tm16 );
777 fe16.segLogFont = MapLS( &lf16 );
780 enum_gdi_fonts = GetDeviceCaps(fe16.hdc, TEXTCAPS) & TC_VA_ABLE;
782 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
789 ret = WineEngEnumFonts( &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
790 fe16.dwFlags &= ~ENUM_CALLED;
791 if (ret && dc->funcs->pEnumDeviceFonts) {
792 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
793 if(fe16.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
797 UnMapLS( fe16.segTextMetric );
798 UnMapLS( fe16.segLogFont );
799 if (fe16.hdc) GDI_ReleaseObj( fe16.hdc );
803 /***********************************************************************
804 * FONT_EnumFontFamiliesEx
806 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf,
807 FONTENUMPROCW efproc,
808 LPARAM lParam, DWORD dwUnicode)
811 DC *dc = DC_GetDCPtr( hDC );
817 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName),
819 fe32.lpLogFontParam = plf;
820 fe32.lpEnumFunc = efproc;
821 fe32.lpData = lParam;
822 fe32.dwFlags = dwUnicode;
825 fe32.physDev = dc->physDev;
827 enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE;
829 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
836 ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
837 fe32.dwFlags &= ~ENUM_CALLED;
838 if (ret && dc->funcs->pEnumDeviceFonts) {
839 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, plf, FONT_EnumInstance, (LPARAM)&fe32 );
840 if(fe32.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
844 if (fe32.hdc) GDI_ReleaseObj( fe32.hdc );
848 /***********************************************************************
849 * EnumFontFamiliesExW (GDI32.@)
851 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
852 FONTENUMPROCW efproc,
853 LPARAM lParam, DWORD dwFlags )
855 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, ENUM_UNICODE );
858 /***********************************************************************
859 * EnumFontFamiliesExA (GDI32.@)
861 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
862 FONTENUMPROCA efproc,
863 LPARAM lParam, DWORD dwFlags)
866 FONT_LogFontAToW( plf, &lfW );
868 return FONT_EnumFontFamiliesEx( hDC, &lfW, (FONTENUMPROCW)efproc, lParam, 0);
871 /***********************************************************************
872 * EnumFontFamilies (GDI.330)
874 INT16 WINAPI EnumFontFamilies16( HDC16 hDC, LPCSTR lpFamily,
875 FONTENUMPROC16 efproc, LPARAM lpData )
879 lf.lfCharSet = DEFAULT_CHARSET;
880 if( lpFamily ) lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
881 else lf.lfFaceName[0] = '\0';
883 return EnumFontFamiliesEx16( hDC, &lf, efproc, lpData, 0 );
886 /***********************************************************************
887 * EnumFontFamiliesA (GDI32.@)
889 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
890 FONTENUMPROCA efproc, LPARAM lpData )
894 lf.lfCharSet = DEFAULT_CHARSET;
895 if( lpFamily ) lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
896 else lf.lfFaceName[0] = lf.lfFaceName[1] = '\0';
898 return EnumFontFamiliesExA( hDC, &lf, efproc, lpData, 0 );
901 /***********************************************************************
902 * EnumFontFamiliesW (GDI32.@)
904 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
905 FONTENUMPROCW efproc, LPARAM lpData )
909 lf.lfCharSet = DEFAULT_CHARSET;
910 if( lpFamily ) lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
911 else lf.lfFaceName[0] = 0;
913 return EnumFontFamiliesExW( hDC, &lf, efproc, lpData, 0 );
916 /***********************************************************************
919 INT16 WINAPI EnumFonts16( HDC16 hDC, LPCSTR lpName, FONTENUMPROC16 efproc,
922 return EnumFontFamilies16( hDC, lpName, efproc, lpData );
925 /***********************************************************************
926 * EnumFontsA (GDI32.@)
928 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
931 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
934 /***********************************************************************
935 * EnumFontsW (GDI32.@)
937 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
940 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
944 /***********************************************************************
945 * GetTextCharacterExtra (GDI32.@)
947 INT WINAPI GetTextCharacterExtra( HDC hdc )
950 DC *dc = DC_GetDCPtr( hdc );
951 if (!dc) return 0x80000000;
953 GDI_ReleaseObj( hdc );
958 /***********************************************************************
959 * SetTextCharacterExtra (GDI32.@)
961 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
964 DC * dc = DC_GetDCPtr( hdc );
965 if (!dc) return 0x80000000;
966 if (dc->funcs->pSetTextCharacterExtra)
967 prev = dc->funcs->pSetTextCharacterExtra( dc->physDev, extra );
970 prev = dc->charExtra;
971 dc->charExtra = extra;
973 GDI_ReleaseObj( hdc );
978 /***********************************************************************
979 * SetTextJustification (GDI32.@)
981 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
984 DC * dc = DC_GetDCPtr( hdc );
985 if (!dc) return FALSE;
986 if (dc->funcs->pSetTextJustification)
987 ret = dc->funcs->pSetTextJustification( dc->physDev, extra, breaks );
990 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
991 if (!extra) breaks = 0;
994 dc->breakExtra = extra / breaks;
995 dc->breakRem = extra - (breaks * dc->breakExtra);
1003 GDI_ReleaseObj( hdc );
1008 /***********************************************************************
1009 * GetTextFaceA (GDI32.@)
1011 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
1013 INT res = GetTextFaceW(hdc, 0, NULL);
1014 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
1015 GetTextFaceW( hdc, res, nameW );
1019 if (count && !WideCharToMultiByte( CP_ACP, 0, nameW, -1, name, count, NULL, NULL))
1024 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
1025 HeapFree( GetProcessHeap(), 0, nameW );
1029 /***********************************************************************
1030 * GetTextFaceW (GDI32.@)
1032 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
1037 DC * dc = DC_GetDCPtr( hdc );
1041 ret = WineEngGetTextFace(dc->gdiFont, count, name);
1042 else if ((font = (FONTOBJ *) GDI_GetObjPtr( dc->hFont, FONT_MAGIC )))
1046 lstrcpynW( name, font->logfont.lfFaceName, count );
1047 ret = strlenW(name);
1049 else ret = strlenW(font->logfont.lfFaceName) + 1;
1050 GDI_ReleaseObj( dc->hFont );
1052 GDI_ReleaseObj( hdc );
1057 /***********************************************************************
1058 * GetTextExtentPoint32A (GDI32.@)
1060 * See GetTextExtentPoint32W.
1062 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
1067 LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1070 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
1071 HeapFree( GetProcessHeap(), 0, p );
1074 TRACE("(%p %s %d %p): returning %d x %d\n",
1075 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
1080 /***********************************************************************
1081 * GetTextExtentPoint32W [GDI32.@]
1083 * Computes width/height for a string.
1085 * Computes width and height of the specified string.
1091 BOOL WINAPI GetTextExtentPoint32W(
1092 HDC hdc, /* [in] Handle of device context */
1093 LPCWSTR str, /* [in] Address of text string */
1094 INT count, /* [in] Number of characters in string */
1095 LPSIZE size) /* [out] Address of structure for string size */
1097 return GetTextExtentExPointW(hdc, str, count, 0, NULL, NULL, size);
1100 /***********************************************************************
1101 * GetTextExtentPointI [GDI32.@]
1103 * Computes width and height of the array of glyph indices.
1109 BOOL WINAPI GetTextExtentPointI(
1110 HDC hdc, /* [in] Handle of device context */
1111 const WORD *indices, /* [in] Address of glyph index array */
1112 INT count, /* [in] Number of glyphs in array */
1113 LPSIZE size) /* [out] Address of structure for string size */
1116 DC * dc = DC_GetDCPtr( hdc );
1117 if (!dc) return FALSE;
1120 ret = WineEngGetTextExtentPointI(dc->gdiFont, indices, count, size);
1121 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1122 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1123 size->cx += count * dc->charExtra;
1125 else if(dc->funcs->pGetTextExtentExPoint) {
1126 FIXME("calling GetTextExtentExPoint\n");
1127 ret = dc->funcs->pGetTextExtentExPoint( dc->physDev, (LPCWSTR)indices,
1128 count, 0, NULL, NULL, size );
1131 GDI_ReleaseObj( hdc );
1133 TRACE("(%p %p %d %p): returning %d x %d\n",
1134 hdc, indices, count, size, size->cx, size->cy );
1139 /***********************************************************************
1140 * GetTextExtentPointA (GDI32.@)
1142 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
1145 TRACE("not bug compatible.\n");
1146 return GetTextExtentPoint32A( hdc, str, count, size );
1149 /***********************************************************************
1150 * GetTextExtentPointW (GDI32.@)
1152 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1155 TRACE("not bug compatible.\n");
1156 return GetTextExtentPoint32W( hdc, str, count, size );
1160 /***********************************************************************
1161 * GetTextExtentExPointA (GDI32.@)
1163 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1164 INT maxExt, LPINT lpnFit,
1165 LPINT alpDx, LPSIZE size )
1173 NULL == (walpDx = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT))))
1176 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1177 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
1180 INT n = lpnFit ? *lpnFit : wlen;
1182 for(i = 0, j = 0; i < n; i++, j++)
1184 alpDx[j] = walpDx[i];
1185 if (IsDBCSLeadByte(str[j])) alpDx[++j] = walpDx[i];
1188 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1189 HeapFree( GetProcessHeap(), 0, p );
1190 HeapFree( GetProcessHeap(), 0, walpDx );
1195 /***********************************************************************
1196 * GetTextExtentExPointW (GDI32.@)
1198 * Return the size of the string as it would be if it was output properly by
1201 * This should include
1202 * - Intercharacter spacing
1203 * - justification spacing (not yet done)
1204 * - kerning? see below
1206 * Kerning. Since kerning would be carried out by the rendering code it should
1207 * be done by the driver. However they don't support it yet. Also I am not
1208 * yet persuaded that (certainly under Win95) any kerning is actually done.
1210 * str: According to MSDN this should be null-terminated. That is not true; a
1211 * null will not terminate it early.
1212 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1213 * than count. I have seen it be either the size of the full string or
1214 * 1 less than the size of the full string. I have not seen it bear any
1215 * resemblance to the portion that would fit.
1216 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1217 * trailing intercharacter spacing and any trailing justification.
1220 * Currently we do this by measuring each character etc. We should do it by
1221 * passing the request to the driver, perhaps by extending the
1222 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1223 * thinking about kerning issues and rounding issues in the justification.
1226 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1227 INT maxExt, LPINT lpnFit,
1228 LPINT alpDx, LPSIZE size )
1236 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1238 dc = DC_GetDCPtr(hdc);
1242 GetTextMetricsW(hdc, &tm);
1244 /* If we need to calculate nFit, then we need the partial extents even if
1245 the user hasn't provided us with an array. */
1248 dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]);
1251 GDI_ReleaseObj(hdc);
1252 SetLastError(ERROR_OUTOFMEMORY);
1260 ret = WineEngGetTextExtentExPoint(dc->gdiFont, str, count,
1261 0, NULL, dxs, size);
1262 else if (dc->funcs->pGetTextExtentExPoint)
1263 ret = dc->funcs->pGetTextExtentExPoint(dc->physDev, str, count,
1264 0, NULL, dxs, size);
1266 /* Perform device size to world size transformations. */
1269 INT extra = dc->charExtra,
1270 breakExtra = dc->breakExtra,
1271 breakRem = dc->breakRem,
1276 for (i = 0; i < count; ++i)
1278 dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
1279 dxs[i] += (i+1) * extra;
1280 if (count > 1 && (breakExtra || breakRem) && str[i] == tm.tmBreakChar)
1282 dxs[i] += breakExtra;
1289 if (dxs[i] <= maxExt)
1292 breakRem = dc->breakRem;
1294 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1295 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1297 if (!dxs && count > 1 && (breakExtra || breakRem))
1299 for (i = 0; i < count; i++)
1301 if (str[i] == tm.tmBreakChar)
1303 size->cx += breakExtra;
1318 HeapFree(GetProcessHeap(), 0, dxs);
1320 GDI_ReleaseObj( hdc );
1322 TRACE("returning %d %d x %d\n",nFit,size->cx,size->cy);
1326 /***********************************************************************
1327 * GetTextMetricsA (GDI32.@)
1329 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1333 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1334 FONT_TextMetricWToA( &tm32, metrics );
1338 /***********************************************************************
1339 * GetTextMetricsW (GDI32.@)
1341 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1344 DC * dc = DC_GetDCPtr( hdc );
1345 if (!dc) return FALSE;
1348 ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1349 else if (dc->funcs->pGetTextMetrics)
1350 ret = dc->funcs->pGetTextMetrics( dc->physDev, metrics );
1354 /* device layer returns values in device units
1355 * therefore we have to convert them to logical */
1357 #define WDPTOLP(x) ((x<0)? \
1358 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1359 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1360 #define HDPTOLP(y) ((y<0)? \
1361 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1362 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1364 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1365 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1366 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1367 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1368 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1369 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1370 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1371 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1375 TRACE("text metrics:\n"
1376 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1377 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1378 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1379 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1380 " PitchAndFamily = %02x\n"
1381 " --------------------\n"
1382 " InternalLeading = %i\n"
1386 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1387 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1388 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1389 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1390 metrics->tmPitchAndFamily,
1391 metrics->tmInternalLeading,
1394 metrics->tmHeight );
1396 GDI_ReleaseObj( hdc );
1401 /***********************************************************************
1402 * GetOutlineTextMetrics [GDI.308] Gets metrics for TrueType fonts.
1405 * lpOTM should be LPOUTLINETEXTMETRIC
1408 * Success: Non-zero or size of required buffer
1411 UINT16 WINAPI GetOutlineTextMetrics16(
1412 HDC16 hdc, /* [in] Handle of device context */
1413 UINT16 cbData, /* [in] Size of metric data array */
1414 LPOUTLINETEXTMETRIC16 lpOTM) /* [out] Address of metric data array */
1416 FIXME("(%04x,%04x,%p): stub\n", hdc,cbData,lpOTM);
1421 /***********************************************************************
1422 * GetOutlineTextMetricsA (GDI32.@)
1423 * Gets metrics for TrueType fonts.
1426 * If the supplied buffer isn't big enough Windows partially fills it up to
1427 * its given length and returns that length.
1430 * Success: Non-zero or size of required buffer
1433 UINT WINAPI GetOutlineTextMetricsA(
1434 HDC hdc, /* [in] Handle of device context */
1435 UINT cbData, /* [in] Size of metric data array */
1436 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1438 char buf[512], *ptr;
1440 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1441 OUTLINETEXTMETRICA *output = lpOTM;
1444 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1446 if(ret > sizeof(buf))
1447 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1448 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1450 needed = sizeof(OUTLINETEXTMETRICA);
1451 if(lpOTMW->otmpFamilyName)
1452 needed += WideCharToMultiByte(CP_ACP, 0,
1453 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1454 NULL, 0, NULL, NULL);
1455 if(lpOTMW->otmpFaceName)
1456 needed += WideCharToMultiByte(CP_ACP, 0,
1457 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1458 NULL, 0, NULL, NULL);
1459 if(lpOTMW->otmpStyleName)
1460 needed += WideCharToMultiByte(CP_ACP, 0,
1461 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1462 NULL, 0, NULL, NULL);
1463 if(lpOTMW->otmpFullName)
1464 needed += WideCharToMultiByte(CP_ACP, 0,
1465 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1466 NULL, 0, NULL, NULL);
1473 TRACE("needed = %d\n", needed);
1475 /* Since the supplied buffer isn't big enough, we'll alloc one
1476 that is and memcpy the first cbData bytes into the lpOTM at
1478 output = HeapAlloc(GetProcessHeap(), 0, needed);
1480 ret = output->otmSize = min(needed, cbData);
1481 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1482 output->otmFiller = 0;
1483 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1484 output->otmfsSelection = lpOTMW->otmfsSelection;
1485 output->otmfsType = lpOTMW->otmfsType;
1486 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1487 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1488 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1489 output->otmEMSquare = lpOTMW->otmEMSquare;
1490 output->otmAscent = lpOTMW->otmAscent;
1491 output->otmDescent = lpOTMW->otmDescent;
1492 output->otmLineGap = lpOTMW->otmLineGap;
1493 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1494 output->otmsXHeight = lpOTMW->otmsXHeight;
1495 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1496 output->otmMacAscent = lpOTMW->otmMacAscent;
1497 output->otmMacDescent = lpOTMW->otmMacDescent;
1498 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1499 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1500 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1501 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1502 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1503 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1504 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1505 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1506 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1507 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1510 ptr = (char*)(output + 1);
1511 left = needed - sizeof(*output);
1513 if(lpOTMW->otmpFamilyName) {
1514 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1515 len = WideCharToMultiByte(CP_ACP, 0,
1516 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1517 ptr, left, NULL, NULL);
1521 output->otmpFamilyName = 0;
1523 if(lpOTMW->otmpFaceName) {
1524 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1525 len = WideCharToMultiByte(CP_ACP, 0,
1526 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1527 ptr, left, NULL, NULL);
1531 output->otmpFaceName = 0;
1533 if(lpOTMW->otmpStyleName) {
1534 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1535 len = WideCharToMultiByte(CP_ACP, 0,
1536 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1537 ptr, left, NULL, NULL);
1541 output->otmpStyleName = 0;
1543 if(lpOTMW->otmpFullName) {
1544 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1545 len = WideCharToMultiByte(CP_ACP, 0,
1546 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1547 ptr, left, NULL, NULL);
1550 output->otmpFullName = 0;
1554 if(output != lpOTM) {
1555 memcpy(lpOTM, output, cbData);
1556 HeapFree(GetProcessHeap(), 0, output);
1558 /* check if the string offsets really fit into the provided size */
1559 /* FIXME: should we check string length as well? */
1560 /* make sure that we don't read/write beyond the provided buffer */
1561 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(LPSTR))
1563 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1564 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1567 /* make sure that we don't read/write beyond the provided buffer */
1568 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(LPSTR))
1570 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1571 lpOTM->otmpFaceName = 0; /* doesn't fit */
1574 /* make sure that we don't read/write beyond the provided buffer */
1575 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(LPSTR))
1577 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1578 lpOTM->otmpStyleName = 0; /* doesn't fit */
1581 /* make sure that we don't read/write beyond the provided buffer */
1582 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(LPSTR))
1584 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1585 lpOTM->otmpFullName = 0; /* doesn't fit */
1590 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1591 HeapFree(GetProcessHeap(), 0, lpOTMW);
1597 /***********************************************************************
1598 * GetOutlineTextMetricsW [GDI32.@]
1600 UINT WINAPI GetOutlineTextMetricsW(
1601 HDC hdc, /* [in] Handle of device context */
1602 UINT cbData, /* [in] Size of metric data array */
1603 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1605 DC *dc = DC_GetDCPtr( hdc );
1606 OUTLINETEXTMETRICW *output = lpOTM;
1609 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1613 ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, output);
1616 output = HeapAlloc(GetProcessHeap(), 0, ret);
1617 WineEngGetOutlineTextMetrics(dc->gdiFont, ret, output);
1620 #define WDPTOLP(x) ((x<0)? \
1621 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1622 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1623 #define HDPTOLP(y) ((y<0)? \
1624 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1625 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1627 output->otmTextMetrics.tmHeight = HDPTOLP(output->otmTextMetrics.tmHeight);
1628 output->otmTextMetrics.tmAscent = HDPTOLP(output->otmTextMetrics.tmAscent);
1629 output->otmTextMetrics.tmDescent = HDPTOLP(output->otmTextMetrics.tmDescent);
1630 output->otmTextMetrics.tmInternalLeading = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1631 output->otmTextMetrics.tmExternalLeading = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1632 output->otmTextMetrics.tmAveCharWidth = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1633 output->otmTextMetrics.tmMaxCharWidth = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1634 output->otmTextMetrics.tmOverhang = WDPTOLP(output->otmTextMetrics.tmOverhang);
1635 output->otmAscent = HDPTOLP(output->otmAscent);
1636 output->otmDescent = HDPTOLP(output->otmDescent);
1637 output->otmLineGap = HDPTOLP(output->otmLineGap);
1638 output->otmsCapEmHeight = HDPTOLP(output->otmsCapEmHeight);
1639 output->otmsXHeight = HDPTOLP(output->otmsXHeight);
1640 output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1641 output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1642 output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1643 output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1644 output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1645 output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1646 output->otmMacLineGap = HDPTOLP(output->otmMacLineGap);
1647 output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1648 output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1649 output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1650 output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1651 output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1652 output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1653 output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1654 output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1655 output->otmsStrikeoutSize = HDPTOLP(output->otmsStrikeoutSize);
1656 output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1657 output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1658 output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1661 if(output != lpOTM) {
1662 memcpy(lpOTM, output, cbData);
1663 HeapFree(GetProcessHeap(), 0, output);
1669 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1670 but really this should just be a return 0. */
1672 ret = sizeof(*lpOTM);
1677 memset(lpOTM, 0, ret);
1678 lpOTM->otmSize = sizeof(*lpOTM);
1679 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1681 Further fill of the structure not implemented,
1682 Needs real values for the structure members
1687 GDI_ReleaseObj(hdc);
1692 /***********************************************************************
1693 * GetCharWidthW (GDI32.@)
1694 * GetCharWidth32W (GDI32.@)
1696 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1701 DC * dc = DC_GetDCPtr( hdc );
1702 if (!dc) return FALSE;
1705 ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1706 else if (dc->funcs->pGetCharWidth)
1707 ret = dc->funcs->pGetCharWidth( dc->physDev, firstChar, lastChar, buffer);
1711 /* convert device units to logical */
1712 for( i = firstChar; i <= lastChar; i++, buffer++ )
1713 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1716 GDI_ReleaseObj( hdc );
1721 /***********************************************************************
1722 * GetCharWidthA (GDI32.@)
1723 * GetCharWidth32A (GDI32.@)
1725 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1728 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1733 if(count <= 0) return FALSE;
1735 str = HeapAlloc(GetProcessHeap(), 0, count);
1736 for(i = 0; i < count; i++)
1737 str[i] = (BYTE)(firstChar + i);
1739 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1741 for(i = 0; i < wlen; i++)
1743 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1751 HeapFree(GetProcessHeap(), 0, str);
1752 HeapFree(GetProcessHeap(), 0, wstr);
1758 /***********************************************************************
1759 * ExtTextOutA (GDI32.@)
1763 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1764 const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1772 if (flags & ETO_GLYPH_INDEX)
1773 return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
1775 p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
1778 unsigned int i = 0, j = 0;
1780 lpDxW = HeapAlloc( GetProcessHeap(), 0, wlen*sizeof(INT));
1782 if(IsDBCSLeadByteEx(codepage, str[i])) {
1783 lpDxW[j++] = lpDx[i] + lpDx[i+1];
1786 lpDxW[j++] = lpDx[i];
1792 ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1794 HeapFree( GetProcessHeap(), 0, p );
1795 HeapFree( GetProcessHeap(), 0, lpDxW );
1800 /***********************************************************************
1801 * ExtTextOutW (GDI32.@)
1803 * Draws text using the currently selected font, background color, and text color.
1807 * x,y [I] coordinates of string
1809 * ETO_GRAYED - undocumented on MSDN
1810 * ETO_OPAQUE - use background color for fill the rectangle
1811 * ETO_CLIPPED - clipping text to the rectangle
1812 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1813 * than encoded characters. Implies ETO_IGNORELANGUAGE
1814 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1815 * Affects BiDi ordering
1816 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1817 * ETO_PDY - unimplemented
1818 * ETO_NUMERICSLATIN - unimplemented always assumed -
1819 * do not translate numbers into locale representations
1820 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1821 * lprect [I] dimensions for clipping or/and opaquing
1822 * str [I] text string
1823 * count [I] number of symbols in string
1824 * lpDx [I] optional parameter with distance between drawing characters
1830 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1831 const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1834 LPWSTR reordered_str = (LPWSTR)str;
1835 WORD *glyphs = NULL;
1836 UINT align = GetTextAlign( hdc );
1840 double cosEsc, sinEsc;
1841 INT *deltas = NULL, char_extra;
1844 BOOL done_extents = FALSE;
1845 INT width = 0, xwidth = 0, ywidth = 0;
1847 DC * dc = DC_GetDCUpdate( hdc );
1850 if (!dc) return FALSE;
1852 breakRem = dc->breakRem;
1854 if (flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY))
1855 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY unimplemented\n");
1857 if (!dc->funcs->pExtTextOut && !PATH_IsPathOpen(dc->path))
1859 GDI_ReleaseObj( hdc );
1863 type = GetObjectType(hdc);
1864 if(type == OBJ_METADC || type == OBJ_ENHMETADC)
1866 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, flags, lprect, str, count, lpDx);
1867 GDI_ReleaseObj( hdc );
1872 flags &= ~ETO_CLIPPED;
1874 if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && BidiAvail && count > 0 )
1876 reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1878 BIDI_Reorder( str, count, GCP_REORDER,
1879 ((flags&ETO_RTLREADING)!=0 || (GetTextAlign(hdc)&TA_RTLREADING)!=0)?
1880 WINE_GCPW_FORCE_RTL:WINE_GCPW_FORCE_LTR,
1881 reordered_str, count, NULL );
1883 flags |= ETO_IGNORELANGUAGE;
1886 TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc, x, y, flags,
1887 lprect, debugstr_wn(str, count), count, lpDx);
1889 if(flags & ETO_GLYPH_INDEX)
1890 glyphs = reordered_str;
1893 TRACE("rect: %d,%d - %d,%d\n", lprect->left, lprect->top, lprect->right,
1895 TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
1897 if(align & TA_UPDATECP)
1899 GetCurrentPositionEx( hdc, &pt );
1904 GetTextMetricsW(hdc, &tm);
1905 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1907 if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
1908 lf.lfEscapement = 0;
1910 if(lf.lfEscapement != 0)
1912 cosEsc = cos(lf.lfEscapement * M_PI / 1800);
1913 sinEsc = sin(lf.lfEscapement * M_PI / 1800);
1921 if(flags & (ETO_CLIPPED | ETO_OPAQUE))
1925 if(flags & ETO_GLYPH_INDEX)
1926 GetTextExtentPointI(hdc, glyphs, count, &sz);
1928 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1930 done_extents = TRUE;
1933 rc.right = x + sz.cx;
1934 rc.bottom = y + sz.cy;
1941 LPtoDP(hdc, (POINT*)&rc, 2);
1943 if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
1944 if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
1947 if ((flags & ETO_OPAQUE) && !PATH_IsPathOpen(dc->path))
1948 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1958 LPtoDP(hdc, &pt, 1);
1962 char_extra = GetTextCharacterExtra(hdc);
1963 if(char_extra || dc->breakExtra || breakRem || lpDx)
1967 deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT));
1968 for(i = 0; i < count; i++)
1970 if(lpDx && (flags & ETO_PDY))
1971 deltas[i] = lpDx[i*2] + char_extra;
1973 deltas[i] = lpDx[i] + char_extra;
1976 if(flags & ETO_GLYPH_INDEX)
1977 GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
1979 GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
1981 deltas[i] = tmpsz.cx;
1984 if (!(flags & ETO_GLYPH_INDEX) && (dc->breakExtra || breakRem) && reordered_str[i] == tm.tmBreakChar)
1986 deltas[i] = deltas[i] + dc->breakExtra;
1993 deltas[i] = INTERNAL_XWSTODS(dc, deltas[i]);
2001 if(flags & ETO_GLYPH_INDEX)
2002 GetTextExtentPointI(hdc, glyphs, count, &sz);
2004 GetTextExtentPointW(hdc, reordered_str, count, &sz);
2005 done_extents = TRUE;
2007 width = INTERNAL_XWSTODS(dc, sz.cx);
2009 xwidth = width * cosEsc;
2010 ywidth = width * sinEsc;
2012 tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
2013 tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
2014 switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
2017 if (align & TA_UPDATECP)
2021 DPtoLP(hdc, &pt, 1);
2022 MoveToEx(hdc, pt.x, pt.y, NULL);
2034 if (align & TA_UPDATECP)
2038 DPtoLP(hdc, &pt, 1);
2039 MoveToEx(hdc, pt.x, pt.y, NULL);
2044 switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
2047 y += tm.tmAscent * cosEsc;
2048 x += tm.tmAscent * sinEsc;
2052 y -= tm.tmDescent * cosEsc;
2053 x -= tm.tmDescent * sinEsc;
2060 if (GetBkMode(hdc) != TRANSPARENT && !PATH_IsPathOpen(dc->path))
2062 if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
2064 if(!(flags & ETO_OPAQUE) || x < rc.left || x + width >= rc.right ||
2065 y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
2069 rc.right = x + width;
2070 rc.top = y - tm.tmAscent;
2071 rc.bottom = y + tm.tmDescent;
2072 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
2077 if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
2079 HFONT orig_font = dc->hFont, cur_font;
2081 INT span = 0, *offsets = NULL, i;
2083 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2084 for(i = 0; i < count; i++)
2086 WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
2087 if(cur_font != dc->hFont)
2092 offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
2097 for(j = 1; j < count; j++)
2099 GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
2100 offsets[j] = offsets[j-1] + INTERNAL_XWSTODS(dc, tmpsz.cx);
2105 for(j = 1; j < count; j++)
2106 offsets[j] = offsets[j-1] + deltas[j];
2111 if (PATH_IsPathOpen(dc->path))
2112 ret = PATH_ExtTextOut(dc, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
2113 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2114 glyphs, span, deltas ? deltas + i - span : NULL);
2116 dc->funcs->pExtTextOut(dc->physDev, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
2117 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2118 glyphs, span, deltas ? deltas + i - span : NULL);
2121 SelectObject(hdc, cur_font);
2123 glyphs[span++] = glyph;
2127 if (PATH_IsPathOpen(dc->path))
2128 ret = PATH_ExtTextOut(dc, x + (offsets ? offsets[count - span] * cosEsc : 0),
2129 y - (offsets ? offsets[count - span] * sinEsc : 0),
2130 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2131 glyphs, span, deltas ? deltas + count - span : NULL);
2133 ret = dc->funcs->pExtTextOut(dc->physDev, x + (offsets ? offsets[count - span] * cosEsc : 0),
2134 y - (offsets ? offsets[count - span] * sinEsc : 0),
2135 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2136 glyphs, span, deltas ? deltas + count - span : NULL);
2137 SelectObject(hdc, orig_font);
2138 HeapFree(GetProcessHeap(), 0, offsets);
2144 if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
2146 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2147 GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
2148 flags |= ETO_GLYPH_INDEX;
2151 if (PATH_IsPathOpen(dc->path))
2152 ret = PATH_ExtTextOut(dc, x, y, (flags & ~ETO_OPAQUE), &rc,
2153 glyphs ? glyphs : reordered_str, count, deltas);
2155 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, (flags & ~ETO_OPAQUE), &rc,
2156 glyphs ? glyphs : reordered_str, count, deltas);
2160 HeapFree(GetProcessHeap(), 0, deltas);
2161 if(glyphs != reordered_str)
2162 HeapFree(GetProcessHeap(), 0, glyphs);
2163 if(reordered_str != str)
2164 HeapFree(GetProcessHeap(), 0, reordered_str);
2166 GDI_ReleaseObj( hdc );
2168 if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2170 int underlinePos, strikeoutPos;
2171 int underlineWidth, strikeoutWidth;
2172 UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2173 OUTLINETEXTMETRICW* otm = NULL;
2178 underlineWidth = tm.tmAscent / 20 + 1;
2179 strikeoutPos = tm.tmAscent / 2;
2180 strikeoutWidth = underlineWidth;
2184 otm = HeapAlloc(GetProcessHeap(), 0, size);
2185 GetOutlineTextMetricsW(hdc, size, otm);
2186 underlinePos = otm->otmsUnderscorePosition;
2187 underlineWidth = otm->otmsUnderscoreSize;
2188 strikeoutPos = otm->otmsStrikeoutPosition;
2189 strikeoutWidth = otm->otmsStrikeoutSize;
2190 HeapFree(GetProcessHeap(), 0, otm);
2193 if (PATH_IsPathOpen(dc->path))
2197 HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2199 hbrush = SelectObject(hdc, hbrush);
2200 hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2204 pts[0].x = x - underlinePos * sinEsc;
2205 pts[0].y = y - underlinePos * cosEsc;
2206 pts[1].x = x + xwidth - underlinePos * sinEsc;
2207 pts[1].y = y - ywidth - underlinePos * cosEsc;
2208 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2209 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2210 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2211 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2212 pts[4].x = pts[0].x;
2213 pts[4].y = pts[0].y;
2214 DPtoLP(hdc, pts, 5);
2215 Polygon(hdc, pts, 5);
2220 pts[0].x = x - strikeoutPos * sinEsc;
2221 pts[0].y = y - strikeoutPos * cosEsc;
2222 pts[1].x = x + xwidth - strikeoutPos * sinEsc;
2223 pts[1].y = y - ywidth - strikeoutPos * cosEsc;
2224 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2225 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2226 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2227 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2228 pts[4].x = pts[0].x;
2229 pts[4].y = pts[0].y;
2230 DPtoLP(hdc, pts, 5);
2231 Polygon(hdc, pts, 5);
2234 SelectObject(hdc, hpen);
2235 hbrush = SelectObject(hdc, hbrush);
2236 DeleteObject(hbrush);
2240 POINT pts[2], oldpt;
2245 hpen = CreatePen(PS_SOLID, underlineWidth, GetTextColor(hdc));
2246 hpen = SelectObject(hdc, hpen);
2249 pts[1].x = x + xwidth;
2250 pts[1].y = y - ywidth;
2251 DPtoLP(hdc, pts, 2);
2252 MoveToEx(hdc, pts[0].x - underlinePos * sinEsc, pts[0].y - underlinePos * cosEsc, &oldpt);
2253 LineTo(hdc, pts[1].x - underlinePos * sinEsc, pts[1].y - underlinePos * cosEsc);
2254 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2255 DeleteObject(SelectObject(hdc, hpen));
2260 hpen = CreatePen(PS_SOLID, strikeoutWidth, GetTextColor(hdc));
2261 hpen = SelectObject(hdc, hpen);
2264 pts[1].x = x + xwidth;
2265 pts[1].y = y - ywidth;
2266 DPtoLP(hdc, pts, 2);
2267 MoveToEx(hdc, pts[0].x - strikeoutPos * sinEsc, pts[0].y - strikeoutPos * cosEsc, &oldpt);
2268 LineTo(hdc, pts[1].x - strikeoutPos * sinEsc, pts[1].y - strikeoutPos * cosEsc);
2269 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2270 DeleteObject(SelectObject(hdc, hpen));
2279 /***********************************************************************
2280 * TextOutA (GDI32.@)
2282 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2284 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2288 /***********************************************************************
2289 * TextOutW (GDI32.@)
2291 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2293 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2297 /***********************************************************************
2298 * PolyTextOutA (GDI32.@)
2302 BOOL WINAPI PolyTextOutA ( HDC hdc, /* [in] Handle to device context */
2303 PPOLYTEXTA pptxt, /* [in] Array of strings */
2304 INT cStrings ) /* [in] Number of strings in array */
2306 for (; cStrings>0; cStrings--, pptxt++)
2307 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2314 /***********************************************************************
2315 * PolyTextOutW (GDI32.@)
2317 * Draw several Strings
2323 BOOL WINAPI PolyTextOutW ( HDC hdc, /* [in] Handle to device context */
2324 PPOLYTEXTW pptxt, /* [in] Array of strings */
2325 INT cStrings ) /* [in] Number of strings in array */
2327 for (; cStrings>0; cStrings--, pptxt++)
2328 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2334 /* FIXME: all following APIs ******************************************/
2337 /***********************************************************************
2338 * SetMapperFlags (GDI32.@)
2340 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
2342 DC *dc = DC_GetDCPtr( hDC );
2345 if(dc->funcs->pSetMapperFlags)
2347 ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
2348 /* FIXME: ret is just a success flag, we should return a proper value */
2351 FIXME("(%p, 0x%08x): stub - harmless\n", hDC, dwFlag);
2352 GDI_ReleaseObj( hDC );
2356 /***********************************************************************
2357 * GetAspectRatioFilterEx (GDI.486)
2359 BOOL16 WINAPI GetAspectRatioFilterEx16( HDC16 hdc, LPSIZE16 pAspectRatio )
2361 FIXME("(%04x, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2365 /***********************************************************************
2366 * GetAspectRatioFilterEx (GDI32.@)
2368 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2370 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2375 /***********************************************************************
2376 * GetCharABCWidthsA (GDI32.@)
2378 * See GetCharABCWidthsW.
2380 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2383 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
2388 if(count <= 0) return FALSE;
2390 str = HeapAlloc(GetProcessHeap(), 0, count);
2391 for(i = 0; i < count; i++)
2392 str[i] = (BYTE)(firstChar + i);
2394 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
2396 for(i = 0; i < wlen; i++)
2398 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2406 HeapFree(GetProcessHeap(), 0, str);
2407 HeapFree(GetProcessHeap(), 0, wstr);
2413 /******************************************************************************
2414 * GetCharABCWidthsW [GDI32.@]
2416 * Retrieves widths of characters in range.
2419 * hdc [I] Handle of device context
2420 * firstChar [I] First character in range to query
2421 * lastChar [I] Last character in range to query
2422 * abc [O] Address of character-width structure
2425 * Only works with TrueType fonts
2431 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2434 DC *dc = DC_GetDCPtr(hdc);
2438 if (!dc) return FALSE;
2441 ret = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
2447 /* convert device units to logical */
2448 for( i = firstChar; i <= lastChar; i++, abc++ ) {
2449 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2450 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2451 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2456 GDI_ReleaseObj(hdc);
2461 /******************************************************************************
2462 * GetCharABCWidthsI [GDI32.@]
2464 * Retrieves widths of characters in range.
2467 * hdc [I] Handle of device context
2468 * firstChar [I] First glyphs in range to query
2469 * count [I] Last glyphs in range to query
2470 * pgi [i] Array of glyphs to query
2471 * abc [O] Address of character-width structure
2474 * Only works with TrueType fonts
2480 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2481 LPWORD pgi, LPABC abc)
2483 DC *dc = DC_GetDCPtr(hdc);
2487 if (!dc) return FALSE;
2490 ret = WineEngGetCharABCWidthsI( dc->gdiFont, firstChar, count, pgi, abc );
2496 /* convert device units to logical */
2497 for( i = 0; i < count; i++, abc++ ) {
2498 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2499 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2500 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2505 GDI_ReleaseObj(hdc);
2510 /***********************************************************************
2511 * GetGlyphOutlineA (GDI32.@)
2513 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2514 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2515 LPVOID lpBuffer, const MAT2 *lpmat2 )
2521 if(!(fuFormat & GGO_GLYPH_INDEX)) {
2524 if(uChar > 0xff) { /* but, 2 bytes character only */
2526 mbchs[0] = (uChar & 0xff00) >> 8;
2527 mbchs[1] = (uChar & 0xff);
2530 mbchs[0] = (uChar & 0xff);
2532 p = FONT_mbtowc(hdc, mbchs, len, NULL, NULL);
2536 ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
2538 HeapFree(GetProcessHeap(), 0, p);
2542 /***********************************************************************
2543 * GetGlyphOutlineW (GDI32.@)
2545 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2546 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2547 LPVOID lpBuffer, const MAT2 *lpmat2 )
2549 DC *dc = DC_GetDCPtr(hdc);
2552 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2553 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2555 if(!dc) return GDI_ERROR;
2558 ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
2559 cbBuffer, lpBuffer, lpmat2);
2563 GDI_ReleaseObj(hdc);
2568 /***********************************************************************
2569 * CreateScalableFontResourceA (GDI32.@)
2571 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2572 LPCSTR lpszResourceFile,
2573 LPCSTR lpszFontFile,
2574 LPCSTR lpszCurrentPath )
2578 /* fHidden=1 - only visible for the calling app, read-only, not
2579 * enumbered with EnumFonts/EnumFontFamilies
2580 * lpszCurrentPath can be NULL
2582 FIXME("(%d,%s,%s,%s): stub\n",
2583 fHidden, debugstr_a(lpszResourceFile), debugstr_a(lpszFontFile),
2584 debugstr_a(lpszCurrentPath) );
2586 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2587 if ((f = CreateFileA(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2589 SetLastError(ERROR_FILE_EXISTS);
2592 return FALSE; /* create failed */
2595 /***********************************************************************
2596 * CreateScalableFontResourceW (GDI32.@)
2598 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2599 LPCWSTR lpszResourceFile,
2600 LPCWSTR lpszFontFile,
2601 LPCWSTR lpszCurrentPath )
2603 FIXME("(%d,%p,%p,%p): stub\n",
2604 fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
2605 return FALSE; /* create failed */
2608 /*************************************************************************
2609 * GetKerningPairsA (GDI32.@)
2611 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2612 LPKERNINGPAIR kern_pairA )
2617 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2618 KERNINGPAIR *kern_pairW;
2620 if (!cPairs && kern_pairA)
2622 SetLastError(ERROR_INVALID_PARAMETER);
2626 charset = GetTextCharset(hDC);
2627 if (!TranslateCharsetInfo((DWORD *)charset, &csi, TCI_SRCCHARSET))
2629 FIXME("Can't find codepage for charset %d\n", charset);
2632 if (!GetCPInfo(csi.ciACP, &cpi))
2634 FIXME("Can't find codepage %u info\n", csi.ciACP);
2637 TRACE("charset %d => codepage %u\n", charset, csi.ciACP);
2639 total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2640 if (!total_kern_pairs) return 0;
2642 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2643 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2645 for (i = 0; i < total_kern_pairs; i++)
2649 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2652 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2655 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2660 if (kern_pairs_copied >= cPairs) break;
2662 kern_pairA->wFirst = (BYTE)first;
2663 kern_pairA->wSecond = (BYTE)second;
2664 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2667 kern_pairs_copied++;
2670 HeapFree(GetProcessHeap(), 0, kern_pairW);
2672 return kern_pairs_copied;
2675 /*************************************************************************
2676 * GetKerningPairsW (GDI32.@)
2678 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2679 LPKERNINGPAIR lpKerningPairs )
2684 TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2686 if (!cPairs && lpKerningPairs)
2688 SetLastError(ERROR_INVALID_PARAMETER);
2692 dc = DC_GetDCPtr(hDC);
2696 ret = WineEngGetKerningPairs(dc->gdiFont, cPairs, lpKerningPairs);
2698 GDI_ReleaseObj(hDC);
2702 /*************************************************************************
2703 * TranslateCharsetInfo [GDI32.@]
2705 * Fills a CHARSETINFO structure for a character set, code page, or
2706 * font. This allows making the correspondance between different labelings
2707 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2708 * of the same encoding.
2710 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2711 * only one codepage should be set in *lpSrc.
2714 * TRUE on success, FALSE on failure.
2717 BOOL WINAPI TranslateCharsetInfo(
2718 LPDWORD lpSrc, /* [in]
2719 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2720 if flags == TCI_SRCCHARSET: a character set value
2721 if flags == TCI_SRCCODEPAGE: a code page value
2723 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2724 DWORD flags /* [in] determines interpretation of lpSrc */)
2728 case TCI_SRCFONTSIG:
2729 while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
2731 case TCI_SRCCODEPAGE:
2732 while ((UINT) (lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
2734 case TCI_SRCCHARSET:
2735 while ((UINT) (lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
2740 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2741 memcpy(lpCs, &FONT_tci[index], sizeof(CHARSETINFO));
2745 /*************************************************************************
2746 * GetFontLanguageInfo (GDI32.@)
2748 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2750 FONTSIGNATURE fontsig;
2751 static const DWORD GCP_DBCS_MASK=0x003F0000,
2752 GCP_DIACRITIC_MASK=0x00000000,
2753 FLI_GLYPHS_MASK=0x00000000,
2754 GCP_GLYPHSHAPE_MASK=0x00000040,
2755 GCP_KASHIDA_MASK=0x00000000,
2756 GCP_LIGATE_MASK=0x00000000,
2757 GCP_USEKERNING_MASK=0x00000000,
2758 GCP_REORDER_MASK=0x00000060;
2762 GetTextCharsetInfo( hdc, &fontsig, 0 );
2763 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2765 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2768 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2769 result|=GCP_DIACRITIC;
2771 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2774 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2775 result|=GCP_GLYPHSHAPE;
2777 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2778 result|=GCP_KASHIDA;
2780 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2783 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2784 result|=GCP_USEKERNING;
2786 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2787 if( GetTextAlign( hdc) & TA_RTLREADING )
2788 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2789 result|=GCP_REORDER;
2795 /*************************************************************************
2796 * GetFontData [GDI32.@]
2798 * Retrieve data for TrueType font.
2802 * success: Number of bytes returned
2803 * failure: GDI_ERROR
2807 * Calls SetLastError()
2810 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2811 LPVOID buffer, DWORD length)
2813 DC *dc = DC_GetDCPtr(hdc);
2814 DWORD ret = GDI_ERROR;
2816 if(!dc) return GDI_ERROR;
2819 ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2821 GDI_ReleaseObj(hdc);
2825 /*************************************************************************
2826 * GetGlyphIndicesA [GDI32.@]
2828 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2829 LPWORD pgi, DWORD flags)
2835 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2836 hdc, debugstr_an(lpstr, count), count, pgi, flags);
2838 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2839 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2840 HeapFree(GetProcessHeap(), 0, lpstrW);
2845 /*************************************************************************
2846 * GetGlyphIndicesW [GDI32.@]
2848 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2849 LPWORD pgi, DWORD flags)
2851 DC *dc = DC_GetDCPtr(hdc);
2852 DWORD ret = GDI_ERROR;
2854 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2855 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2857 if(!dc) return GDI_ERROR;
2860 ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2862 GDI_ReleaseObj(hdc);
2866 /*************************************************************************
2867 * GetCharacterPlacementA [GDI32.@]
2869 * See GetCharacterPlacementW.
2872 * the web browser control of ie4 calls this with dwFlags=0
2875 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2876 INT nMaxExtent, GCP_RESULTSA *lpResults,
2881 GCP_RESULTSW resultsW;
2885 TRACE("%s, %d, %d, 0x%08x\n",
2886 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2888 /* both structs are equal in size */
2889 memcpy(&resultsW, lpResults, sizeof(resultsW));
2891 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2892 if(lpResults->lpOutString)
2893 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2895 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2897 lpResults->nGlyphs = resultsW.nGlyphs;
2898 lpResults->nMaxFit = resultsW.nMaxFit;
2900 if(lpResults->lpOutString) {
2901 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2902 lpResults->lpOutString, uCount, NULL, NULL );
2905 HeapFree(GetProcessHeap(), 0, lpStringW);
2906 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2911 /*************************************************************************
2912 * GetCharacterPlacementW [GDI32.@]
2914 * Retrieve information about a string. This includes the width, reordering,
2915 * Glyphing and so on.
2919 * The width and height of the string if successful, 0 if failed.
2923 * All flags except GCP_REORDER are not yet implemented.
2924 * Reordering is not 100% complient to the Windows BiDi method.
2925 * Caret positioning is not yet implemented for BiDi.
2926 * Classes are not yet implemented.
2930 GetCharacterPlacementW(
2931 HDC hdc, /* [in] Device context for which the rendering is to be done */
2932 LPCWSTR lpString, /* [in] The string for which information is to be returned */
2933 INT uCount, /* [in] Number of WORDS in string. */
2934 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
2935 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2936 DWORD dwFlags /* [in] Flags specifying how to process the string */
2943 TRACE("%s, %d, %d, 0x%08x\n",
2944 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2946 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2947 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2948 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2949 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2950 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2952 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08x ignored\n", dwFlags);
2953 if(lpResults->lpClass) FIXME("classes not implemented\n");
2954 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2955 FIXME("Caret positions for complex scripts not implemented\n");
2957 nSet = (UINT)uCount;
2958 if(nSet > lpResults->nGlyphs)
2959 nSet = lpResults->nGlyphs;
2961 /* return number of initialized fields */
2962 lpResults->nGlyphs = nSet;
2964 if((dwFlags&GCP_REORDER)==0 || !BidiAvail)
2966 /* Treat the case where no special handling was requested in a fastpath way */
2967 /* copy will do if the GCP_REORDER flag is not set */
2968 if(lpResults->lpOutString)
2969 memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
2971 if(lpResults->lpOrder)
2973 for(i = 0; i < nSet; i++)
2974 lpResults->lpOrder[i] = i;
2978 BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
2979 nSet, lpResults->lpOrder );
2982 /* FIXME: Will use the placement chars */
2983 if (lpResults->lpDx)
2986 for (i = 0; i < nSet; i++)
2988 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
2989 lpResults->lpDx[i]= c;
2993 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
2997 lpResults->lpCaretPos[0] = 0;
2998 for (i = 1; i < nSet; i++)
2999 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
3000 lpResults->lpCaretPos[i] = (pos += size.cx);
3003 if(lpResults->lpGlyphs)
3004 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
3006 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
3007 ret = MAKELONG(size.cx, size.cy);
3012 /*************************************************************************
3013 * GetCharABCWidthsFloatA [GDI32.@]
3015 * See GetCharABCWidthsFloatW.
3017 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3019 INT i, wlen, count = (INT)(last - first + 1);
3024 if (count <= 0) return FALSE;
3026 str = HeapAlloc(GetProcessHeap(), 0, count);
3028 for(i = 0; i < count; i++)
3029 str[i] = (BYTE)(first + i);
3031 wstr = FONT_mbtowc( hdc, str, count, &wlen, NULL );
3033 for (i = 0; i < wlen; i++)
3035 if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
3043 HeapFree( GetProcessHeap(), 0, str );
3044 HeapFree( GetProcessHeap(), 0, wstr );
3049 /*************************************************************************
3050 * GetCharABCWidthsFloatW [GDI32.@]
3052 * Retrieves widths of a range of characters.
3055 * hdc [I] Handle to device context.
3056 * first [I] First character in range to query.
3057 * last [I] Last character in range to query.
3058 * abcf [O] Array of LPABCFLOAT structures.
3065 * Only works with TrueType fonts. It also doesn't return real
3066 * floats but converted integers because it's implemented on
3067 * top of GetCharABCWidthsW.
3069 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3072 unsigned int i, size = sizeof(ABC) * (last - first + 1);
3075 TRACE("%p, %d, %d, %p - partial stub\n", hdc, first, last, abcf);
3077 abc = HeapAlloc( GetProcessHeap(), 0, size );
3078 if (!abc) return FALSE;
3080 ret = GetCharABCWidthsW( hdc, first, last, abc );
3083 for (i = first; i <= last; i++, abc++, abcf++)
3085 abcf->abcfA = abc->abcA;
3086 abcf->abcfB = abc->abcB;
3087 abcf->abcfC = abc->abcC;
3090 HeapFree( GetProcessHeap(), 0, abc );
3094 /*************************************************************************
3095 * GetCharWidthFloatA [GDI32.@]
3097 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
3098 UINT iLastChar, PFLOAT pxBuffer)
3100 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3104 /*************************************************************************
3105 * GetCharWidthFloatW [GDI32.@]
3107 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
3108 UINT iLastChar, PFLOAT pxBuffer)
3110 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3115 /***********************************************************************
3117 * Font Resource API *
3119 ***********************************************************************/
3121 /***********************************************************************
3122 * AddFontResourceA (GDI32.@)
3124 INT WINAPI AddFontResourceA( LPCSTR str )
3126 return AddFontResourceExA( str, 0, NULL);
3129 /***********************************************************************
3130 * AddFontResourceW (GDI32.@)
3132 INT WINAPI AddFontResourceW( LPCWSTR str )
3134 return AddFontResourceExW(str, 0, NULL);
3138 /***********************************************************************
3139 * AddFontResourceExA (GDI32.@)
3141 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3143 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3144 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3147 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3148 ret = AddFontResourceExW(strW, fl, pdv);
3149 HeapFree(GetProcessHeap(), 0, strW);
3153 /***********************************************************************
3154 * AddFontResourceExW (GDI32.@)
3156 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3158 return WineEngAddFontResourceEx(str, fl, pdv);
3161 /***********************************************************************
3162 * RemoveFontResourceA (GDI32.@)
3164 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3166 return RemoveFontResourceExA(str, 0, 0);
3169 /***********************************************************************
3170 * RemoveFontResourceW (GDI32.@)
3172 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3174 return RemoveFontResourceExW(str, 0, 0);
3177 /***********************************************************************
3178 * AddFontMemResourceEx (GDI32.@)
3180 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3182 FIXME("(%p,%08x,%p,%p): stub\n", pbFont, cbFont, pdv, pcFonts);
3186 /***********************************************************************
3187 * RemoveFontResourceExA (GDI32.@)
3189 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3191 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3192 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3195 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3196 ret = RemoveFontResourceExW(strW, fl, pdv);
3197 HeapFree(GetProcessHeap(), 0, strW);
3201 /***********************************************************************
3202 * RemoveFontResourceExW (GDI32.@)
3204 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3206 return WineEngRemoveFontResourceEx(str, fl, pdv);
3209 /***********************************************************************
3210 * GetTextCharset (GDI32.@)
3212 UINT WINAPI GetTextCharset(HDC hdc)
3214 /* MSDN docs say this is equivalent */
3215 return GetTextCharsetInfo(hdc, NULL, 0);
3218 /***********************************************************************
3219 * GetTextCharsetInfo (GDI32.@)
3221 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3223 UINT ret = DEFAULT_CHARSET;
3224 DC *dc = DC_GetDCPtr(hdc);
3229 ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
3231 GDI_ReleaseObj(hdc);
3234 if (ret == DEFAULT_CHARSET && fs)
3235 memset(fs, 0, sizeof(FONTSIGNATURE));
3239 /***********************************************************************
3240 * GdiGetCharDimensions (GDI32.@)
3242 * Gets the average width of the characters in the English alphabet.
3245 * hdc [I] Handle to the device context to measure on.
3246 * lptm [O] Pointer to memory to store the text metrics into.
3247 * height [O] On exit, the maximum height of characters in the English alphabet.
3250 * The average width of characters in the English alphabet.
3253 * This function is used by the dialog manager to get the size of a dialog
3254 * unit. It should also be used by other pieces of code that need to know
3255 * the size of a dialog unit in logical units without having access to the
3256 * window handle of the dialog.
3257 * Windows caches the font metrics from this function, but we don't and
3258 * there doesn't appear to be an immediate advantage to do so.
3261 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3263 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3266 static const WCHAR alphabet[] = {
3267 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3268 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3269 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3271 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3273 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3275 if (height) *height = sz.cy;
3276 return (sz.cx / 26 + 1) / 2;
3279 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3281 FIXME("(%d): stub\n", fEnableEUDC);
3285 /***********************************************************************
3286 * GetCharWidthI (GDI32.@)
3288 * Retrieve widths of characters.
3291 * hdc [I] Handle to a device context.
3292 * first [I] First glyph in range to query.
3293 * count [I] Number of glyph indices to query.
3294 * glyphs [I] Array of glyphs to query.
3295 * buffer [O] Buffer to receive character widths.
3298 * Only works with TrueType fonts.
3304 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3309 TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3311 if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3314 if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3316 HeapFree(GetProcessHeap(), 0, abc);
3320 for (i = 0; i < count; i++)
3321 buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3323 HeapFree(GetProcessHeap(), 0, abc);
3327 /***********************************************************************
3328 * GetFontUnicodeRanges (GDI32.@)
3330 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3332 FIXME("(%p, %p): stub\n", hdc, lpgs);