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 = min(ptmW->tmFirstChar, 255);
291 if (ptmW->tmCharSet == SYMBOL_CHARSET)
293 UINT last_char = ptmW->tmLastChar;
294 if (last_char > 0xf000) last_char -= 0xf000;
295 ptmA->tmLastChar = min(last_char, 255);
298 ptmA->tmLastChar = min(ptmW->tmLastChar, 255);
299 ptmA->tmDefaultChar = min(ptmW->tmDefaultChar, 255);
300 ptmA->tmBreakChar = min(ptmW->tmBreakChar, 255);
301 ptmA->tmItalic = ptmW->tmItalic;
302 ptmA->tmUnderlined = ptmW->tmUnderlined;
303 ptmA->tmStruckOut = ptmW->tmStruckOut;
304 ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
305 ptmA->tmCharSet = ptmW->tmCharSet;
309 static void FONT_NewTextMetricExWTo16(const NEWTEXTMETRICEXW *ptmW, LPNEWTEXTMETRICEX16 ptm16 )
311 ptm16->ntmTm.tmHeight = ptmW->ntmTm.tmHeight;
312 ptm16->ntmTm.tmAscent = ptmW->ntmTm.tmAscent;
313 ptm16->ntmTm.tmDescent = ptmW->ntmTm.tmDescent;
314 ptm16->ntmTm.tmInternalLeading = ptmW->ntmTm.tmInternalLeading;
315 ptm16->ntmTm.tmExternalLeading = ptmW->ntmTm.tmExternalLeading;
316 ptm16->ntmTm.tmAveCharWidth = ptmW->ntmTm.tmAveCharWidth;
317 ptm16->ntmTm.tmMaxCharWidth = ptmW->ntmTm.tmMaxCharWidth;
318 ptm16->ntmTm.tmWeight = ptmW->ntmTm.tmWeight;
319 ptm16->ntmTm.tmOverhang = ptmW->ntmTm.tmOverhang;
320 ptm16->ntmTm.tmDigitizedAspectX = ptmW->ntmTm.tmDigitizedAspectX;
321 ptm16->ntmTm.tmDigitizedAspectY = ptmW->ntmTm.tmDigitizedAspectY;
322 ptm16->ntmTm.tmFirstChar = ptmW->ntmTm.tmFirstChar > 255 ? 255 : ptmW->ntmTm.tmFirstChar;
323 ptm16->ntmTm.tmLastChar = ptmW->ntmTm.tmLastChar > 255 ? 255 : ptmW->ntmTm.tmLastChar;
324 ptm16->ntmTm.tmDefaultChar = ptmW->ntmTm.tmDefaultChar > 255 ? 255 : ptmW->ntmTm.tmDefaultChar;
325 ptm16->ntmTm.tmBreakChar = ptmW->ntmTm.tmBreakChar > 255 ? 255 : ptmW->ntmTm.tmBreakChar;
326 ptm16->ntmTm.tmItalic = ptmW->ntmTm.tmItalic;
327 ptm16->ntmTm.tmUnderlined = ptmW->ntmTm.tmUnderlined;
328 ptm16->ntmTm.tmStruckOut = ptmW->ntmTm.tmStruckOut;
329 ptm16->ntmTm.tmPitchAndFamily = ptmW->ntmTm.tmPitchAndFamily;
330 ptm16->ntmTm.tmCharSet = ptmW->ntmTm.tmCharSet;
331 ptm16->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
332 ptm16->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
333 ptm16->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
334 ptm16->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
335 memcpy(&ptm16->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
338 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW *ptmW, NEWTEXTMETRICEXA *ptmA )
340 FONT_TextMetricWToA((const TEXTMETRICW *)ptmW, (LPTEXTMETRICA)ptmA);
341 ptmA->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
342 ptmA->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
343 ptmA->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
344 ptmA->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
345 memcpy(&ptmA->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
349 /***********************************************************************
350 * GdiGetCodePage (GDI32.@)
352 DWORD WINAPI GdiGetCodePage( HDC hdc )
356 int charset = GetTextCharset(hdc);
358 /* Hmm, nicely designed api this one! */
359 if(TranslateCharsetInfo((DWORD*)charset, &csi, TCI_SRCCHARSET))
366 case DEFAULT_CHARSET:
377 /* FIXME: These have no place here, but because x11drv
378 enumerates fonts with these (made up) charsets some apps
379 might use them and then the FIXME below would become
380 annoying. Now we could pick the intended codepage for
381 each of these, but since it's broken anyway we'll just
382 use CP_ACP and hope it'll go away...
388 FIXME("Can't find codepage for charset %d\n", charset);
393 TRACE("charset %d => cp %d\n", charset, cp);
397 /***********************************************************************
400 * Returns a Unicode translation of str using the charset of the
401 * currently selected font in hdc. If count is -1 then str is assumed
402 * to be '\0' terminated, otherwise it contains the number of bytes to
403 * convert. If plenW is non-NULL, on return it will point to the
404 * number of WCHARs that have been written. If pCP is non-NULL, on
405 * return it will point to the codepage used in the conversion. The
406 * caller should free the returned LPWSTR from the process heap
409 static LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
415 cp = GdiGetCodePage( hdc );
417 if(count == -1) count = strlen(str);
418 lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
419 strW = HeapAlloc(GetProcessHeap(), 0, lenW*sizeof(WCHAR));
420 MultiByteToWideChar(cp, 0, str, count, strW, lenW);
421 TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW));
422 if(plenW) *plenW = lenW;
428 /***********************************************************************
429 * CreateFontIndirectA (GDI32.@)
431 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *plfA )
436 FONT_LogFontAToW( plfA, &lfW );
437 return CreateFontIndirectW( &lfW );
439 return CreateFontIndirectW( NULL );
443 /***********************************************************************
444 * CreateFontIndirectW (GDI32.@)
446 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
453 if ((fontPtr = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC,
454 (HGDIOBJ *)&hFont, &font_funcs )))
456 static const WCHAR ItalicW[] = {' ','I','t','a','l','i','c','\0'};
457 static const WCHAR BoldW[] = {' ','B','o','l','d','\0'};
458 WCHAR *pFaceNameItalicSuffix, *pFaceNameBoldSuffix;
459 WCHAR* pFaceNameSuffix = NULL;
461 memcpy( &fontPtr->logfont, plf, sizeof(LOGFONTW) );
463 TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
464 plf->lfHeight, plf->lfWidth,
465 plf->lfEscapement, plf->lfOrientation,
466 plf->lfPitchAndFamily,
467 plf->lfOutPrecision, plf->lfClipPrecision,
468 plf->lfQuality, plf->lfCharSet,
469 debugstr_w(plf->lfFaceName),
470 plf->lfWeight > 400 ? "Bold" : "",
471 plf->lfItalic ? "Italic" : "",
472 plf->lfUnderline ? "Underline" : "", hFont);
474 if (plf->lfEscapement != plf->lfOrientation) {
475 /* this should really depend on whether GM_ADVANCED is set */
476 fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
477 WARN("orientation angle %f set to "
478 "escapement angle %f for new font %p\n",
479 plf->lfOrientation/10., plf->lfEscapement/10., hFont);
482 pFaceNameItalicSuffix = strstrW(fontPtr->logfont.lfFaceName, ItalicW);
483 if (pFaceNameItalicSuffix) {
484 fontPtr->logfont.lfItalic = TRUE;
485 pFaceNameSuffix = pFaceNameItalicSuffix;
488 pFaceNameBoldSuffix = strstrW(fontPtr->logfont.lfFaceName, BoldW);
489 if (pFaceNameBoldSuffix) {
490 if (fontPtr->logfont.lfWeight < FW_BOLD) {
491 fontPtr->logfont.lfWeight = FW_BOLD;
493 if (!pFaceNameSuffix ||
494 (pFaceNameBoldSuffix < pFaceNameSuffix)) {
495 pFaceNameSuffix = pFaceNameBoldSuffix;
499 if (pFaceNameSuffix) *pFaceNameSuffix = 0;
501 GDI_ReleaseObj( hFont );
504 else WARN("(NULL) => NULL\n");
509 /*************************************************************************
510 * CreateFontA (GDI32.@)
512 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
513 INT orient, INT weight, DWORD italic,
514 DWORD underline, DWORD strikeout, DWORD charset,
515 DWORD outpres, DWORD clippres, DWORD quality,
516 DWORD pitch, LPCSTR name )
520 logfont.lfHeight = height;
521 logfont.lfWidth = width;
522 logfont.lfEscapement = esc;
523 logfont.lfOrientation = orient;
524 logfont.lfWeight = weight;
525 logfont.lfItalic = italic;
526 logfont.lfUnderline = underline;
527 logfont.lfStrikeOut = strikeout;
528 logfont.lfCharSet = charset;
529 logfont.lfOutPrecision = outpres;
530 logfont.lfClipPrecision = clippres;
531 logfont.lfQuality = quality;
532 logfont.lfPitchAndFamily = pitch;
535 lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
537 logfont.lfFaceName[0] = '\0';
539 return CreateFontIndirectA( &logfont );
542 /*************************************************************************
543 * CreateFontW (GDI32.@)
545 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
546 INT orient, INT weight, DWORD italic,
547 DWORD underline, DWORD strikeout, DWORD charset,
548 DWORD outpres, DWORD clippres, DWORD quality,
549 DWORD pitch, LPCWSTR name )
553 logfont.lfHeight = height;
554 logfont.lfWidth = width;
555 logfont.lfEscapement = esc;
556 logfont.lfOrientation = orient;
557 logfont.lfWeight = weight;
558 logfont.lfItalic = italic;
559 logfont.lfUnderline = underline;
560 logfont.lfStrikeOut = strikeout;
561 logfont.lfCharSet = charset;
562 logfont.lfOutPrecision = outpres;
563 logfont.lfClipPrecision = clippres;
564 logfont.lfQuality = quality;
565 logfont.lfPitchAndFamily = pitch;
568 lstrcpynW(logfont.lfFaceName, name,
569 sizeof(logfont.lfFaceName) / sizeof(WCHAR));
571 logfont.lfFaceName[0] = '\0';
573 return CreateFontIndirectW( &logfont );
577 /***********************************************************************
580 * If the driver supports vector fonts we create a gdi font first and
581 * then call the driver to give it a chance to supply its own device
582 * font. If the driver wants to do this it returns TRUE and we can
583 * delete the gdi font, if the driver wants to use the gdi font it
584 * should return FALSE, to signal an error return GDI_ERROR. For
585 * drivers that don't support vector fonts they must supply their own
588 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, void *obj, HDC hdc )
591 DC *dc = DC_GetDCPtr( hdc );
595 if (dc->hFont != handle || dc->gdiFont == NULL)
597 if(GetDeviceCaps(dc->hSelf, TEXTCAPS) & TC_VA_ABLE)
598 dc->gdiFont = WineEngCreateFontInstance(dc, handle);
601 if (dc->funcs->pSelectFont) ret = dc->funcs->pSelectFont( dc->physDev, handle, dc->gdiFont );
603 if (ret && dc->gdiFont) dc->gdiFont = 0;
605 if (ret == HGDI_ERROR)
606 ret = 0; /* SelectObject returns 0 on error */
612 GDI_ReleaseObj( hdc );
617 /***********************************************************************
620 static INT FONT_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
625 FONT_LogFontWTo16( &font->logfont, &lf16 );
627 if (count > sizeof(LOGFONT16)) count = sizeof(LOGFONT16);
628 memcpy( buffer, &lf16, count );
632 /***********************************************************************
635 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
642 FONT_LogFontWToA( &font->logfont, &lfA );
644 if (count > sizeof(lfA)) count = sizeof(lfA);
645 memcpy( buffer, &lfA, count );
649 /***********************************************************************
652 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
656 return sizeof(LOGFONTW);
657 if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
658 memcpy( buffer, &font->logfont, count );
663 /***********************************************************************
666 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj )
668 WineEngDestroyFontInstance( handle );
669 return GDI_FreeObject( handle, obj );
673 /***********************************************************************
674 * FONT_EnumInstance16
676 * Called by the device driver layer to pass font info
677 * down to the application.
679 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
680 * We have to use other types because of the FONTENUMPROCW definition.
682 static INT CALLBACK FONT_EnumInstance16( const LOGFONTW *plf, const TEXTMETRICW *ptm,
683 DWORD fType, LPARAM lp )
685 fontEnum16 *pfe = (fontEnum16*)lp;
689 if( pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
690 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet )
695 FONT_EnumLogFontExWTo16((const ENUMLOGFONTEXW *)plf, pfe->lpLogFont);
696 FONT_NewTextMetricExWTo16((const NEWTEXTMETRICEXW *)ptm, pfe->lpTextMetric);
697 pfe->dwFlags |= ENUM_CALLED;
698 GDI_ReleaseObj( pfe->hdc ); /* release the GDI lock */
700 args[6] = SELECTOROF(pfe->segLogFont);
701 args[5] = OFFSETOF(pfe->segLogFont);
702 args[4] = SELECTOROF(pfe->segTextMetric);
703 args[3] = OFFSETOF(pfe->segTextMetric);
705 args[1] = HIWORD(pfe->lpData);
706 args[0] = LOWORD(pfe->lpData);
707 WOWCallback16Ex( (DWORD)pfe->lpEnumFunc, WCB16_PASCAL, sizeof(args), args, &result );
708 ret = LOWORD(result);
710 /* get the lock again and make sure the DC is still valid */
711 dc = DC_GetDCPtr( pfe->hdc );
712 if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
714 if (dc) GDI_ReleaseObj( pfe->hdc );
715 pfe->hdc = 0; /* make sure we don't try to release it later on */
722 /***********************************************************************
725 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
726 * We have to use other types because of the FONTENUMPROCW definition.
728 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
729 DWORD fType, LPARAM lp )
731 fontEnum32 *pfe = (fontEnum32*)lp;
735 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
736 if((pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
737 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
738 (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
740 /* convert font metrics */
741 ENUMLOGFONTEXA logfont;
742 NEWTEXTMETRICEXA tmA;
744 pfe->dwFlags |= ENUM_CALLED;
745 if (!(pfe->dwFlags & ENUM_UNICODE))
747 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
748 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
749 plf = (LOGFONTW *)&logfont.elfLogFont;
750 ptm = (TEXTMETRICW *)&tmA;
752 GDI_ReleaseObj( pfe->hdc ); /* release the GDI lock */
754 ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
756 /* get the lock again and make sure the DC is still valid */
757 dc = DC_GetDCPtr( pfe->hdc );
758 if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
760 if (dc) GDI_ReleaseObj( pfe->hdc );
761 pfe->hdc = 0; /* make sure we don't try to release it later on */
768 /***********************************************************************
769 * EnumFontFamiliesEx (GDI.613)
771 INT16 WINAPI EnumFontFamiliesEx16( HDC16 hDC, LPLOGFONT16 plf,
772 FONTENUMPROC16 efproc, LPARAM lParam,
777 DC* dc = DC_GetDCPtr( HDC_32(hDC) );
778 NEWTEXTMETRICEX16 tm16;
779 ENUMLOGFONTEX16 lf16;
784 FONT_LogFont16ToW(plf, &lfW);
786 fe16.hdc = HDC_32(hDC);
788 fe16.physDev = dc->physDev;
789 fe16.lpLogFontParam = plf;
790 fe16.lpEnumFunc = efproc;
791 fe16.lpData = lParam;
792 fe16.lpTextMetric = &tm16;
793 fe16.lpLogFont = &lf16;
794 fe16.segTextMetric = MapLS( &tm16 );
795 fe16.segLogFont = MapLS( &lf16 );
798 enum_gdi_fonts = GetDeviceCaps(fe16.hdc, TEXTCAPS) & TC_VA_ABLE;
800 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
807 ret = WineEngEnumFonts( &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
808 fe16.dwFlags &= ~ENUM_CALLED;
809 if (ret && dc->funcs->pEnumDeviceFonts) {
810 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
811 if(fe16.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
815 UnMapLS( fe16.segTextMetric );
816 UnMapLS( fe16.segLogFont );
817 if (fe16.hdc) GDI_ReleaseObj( fe16.hdc );
821 /***********************************************************************
822 * FONT_EnumFontFamiliesEx
824 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf,
825 FONTENUMPROCW efproc,
826 LPARAM lParam, DWORD dwUnicode)
829 DC *dc = DC_GetDCPtr( hDC );
835 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName),
837 fe32.lpLogFontParam = plf;
838 fe32.lpEnumFunc = efproc;
839 fe32.lpData = lParam;
840 fe32.dwFlags = dwUnicode;
843 fe32.physDev = dc->physDev;
845 enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE;
847 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
854 ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
855 fe32.dwFlags &= ~ENUM_CALLED;
856 if (ret && dc->funcs->pEnumDeviceFonts) {
857 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, plf, FONT_EnumInstance, (LPARAM)&fe32 );
858 if(fe32.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
862 if (fe32.hdc) GDI_ReleaseObj( fe32.hdc );
866 /***********************************************************************
867 * EnumFontFamiliesExW (GDI32.@)
869 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
870 FONTENUMPROCW efproc,
871 LPARAM lParam, DWORD dwFlags )
873 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, ENUM_UNICODE );
876 /***********************************************************************
877 * EnumFontFamiliesExA (GDI32.@)
879 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
880 FONTENUMPROCA efproc,
881 LPARAM lParam, DWORD dwFlags)
884 FONT_LogFontAToW( plf, &lfW );
886 return FONT_EnumFontFamiliesEx( hDC, &lfW, (FONTENUMPROCW)efproc, lParam, 0);
889 /***********************************************************************
890 * EnumFontFamilies (GDI.330)
892 INT16 WINAPI EnumFontFamilies16( HDC16 hDC, LPCSTR lpFamily,
893 FONTENUMPROC16 efproc, LPARAM lpData )
897 lf.lfCharSet = DEFAULT_CHARSET;
900 if (!*lpFamily) return 1;
901 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
903 else lf.lfFaceName[0] = '\0';
905 return EnumFontFamiliesEx16( hDC, &lf, efproc, lpData, 0 );
908 /***********************************************************************
909 * EnumFontFamiliesA (GDI32.@)
911 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
912 FONTENUMPROCA efproc, LPARAM lpData )
916 lf.lfCharSet = DEFAULT_CHARSET;
919 if (!*lpFamily) return 1;
920 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
922 else lf.lfFaceName[0] = lf.lfFaceName[1] = '\0';
924 return EnumFontFamiliesExA( hDC, &lf, efproc, lpData, 0 );
927 /***********************************************************************
928 * EnumFontFamiliesW (GDI32.@)
930 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
931 FONTENUMPROCW efproc, LPARAM lpData )
935 lf.lfCharSet = DEFAULT_CHARSET;
938 if (!*lpFamily) return 1;
939 lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
941 else lf.lfFaceName[0] = 0;
943 return EnumFontFamiliesExW( hDC, &lf, efproc, lpData, 0 );
946 /***********************************************************************
949 INT16 WINAPI EnumFonts16( HDC16 hDC, LPCSTR lpName, FONTENUMPROC16 efproc,
952 return EnumFontFamilies16( hDC, lpName, efproc, lpData );
955 /***********************************************************************
956 * EnumFontsA (GDI32.@)
958 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
961 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
964 /***********************************************************************
965 * EnumFontsW (GDI32.@)
967 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
970 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
974 /***********************************************************************
975 * GetTextCharacterExtra (GDI32.@)
977 INT WINAPI GetTextCharacterExtra( HDC hdc )
980 DC *dc = DC_GetDCPtr( hdc );
981 if (!dc) return 0x80000000;
983 GDI_ReleaseObj( hdc );
988 /***********************************************************************
989 * SetTextCharacterExtra (GDI32.@)
991 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
994 DC * dc = DC_GetDCPtr( hdc );
995 if (!dc) return 0x80000000;
996 if (dc->funcs->pSetTextCharacterExtra)
997 prev = dc->funcs->pSetTextCharacterExtra( dc->physDev, extra );
1000 prev = dc->charExtra;
1001 dc->charExtra = extra;
1003 GDI_ReleaseObj( hdc );
1008 /***********************************************************************
1009 * SetTextJustification (GDI32.@)
1011 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
1014 DC * dc = DC_GetDCPtr( hdc );
1015 if (!dc) return FALSE;
1016 if (dc->funcs->pSetTextJustification)
1017 ret = dc->funcs->pSetTextJustification( dc->physDev, extra, breaks );
1020 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
1021 if (!extra) breaks = 0;
1024 dc->breakExtra = extra / breaks;
1025 dc->breakRem = extra - (breaks * dc->breakExtra);
1033 GDI_ReleaseObj( hdc );
1038 /***********************************************************************
1039 * GetTextFaceA (GDI32.@)
1041 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
1043 INT res = GetTextFaceW(hdc, 0, NULL);
1044 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
1045 GetTextFaceW( hdc, res, nameW );
1049 if (count && !WideCharToMultiByte( CP_ACP, 0, nameW, -1, name, count, NULL, NULL))
1054 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
1055 HeapFree( GetProcessHeap(), 0, nameW );
1059 /***********************************************************************
1060 * GetTextFaceW (GDI32.@)
1062 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
1067 DC * dc = DC_GetDCPtr( hdc );
1071 ret = WineEngGetTextFace(dc->gdiFont, count, name);
1072 else if ((font = (FONTOBJ *) GDI_GetObjPtr( dc->hFont, FONT_MAGIC )))
1076 lstrcpynW( name, font->logfont.lfFaceName, count );
1077 ret = strlenW(name);
1079 else ret = strlenW(font->logfont.lfFaceName) + 1;
1080 GDI_ReleaseObj( dc->hFont );
1082 GDI_ReleaseObj( hdc );
1087 /***********************************************************************
1088 * GetTextExtentPoint32A (GDI32.@)
1090 * See GetTextExtentPoint32W.
1092 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
1097 LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1100 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
1101 HeapFree( GetProcessHeap(), 0, p );
1104 TRACE("(%p %s %d %p): returning %d x %d\n",
1105 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
1110 /***********************************************************************
1111 * GetTextExtentPoint32W [GDI32.@]
1113 * Computes width/height for a string.
1115 * Computes width and height of the specified string.
1121 BOOL WINAPI GetTextExtentPoint32W(
1122 HDC hdc, /* [in] Handle of device context */
1123 LPCWSTR str, /* [in] Address of text string */
1124 INT count, /* [in] Number of characters in string */
1125 LPSIZE size) /* [out] Address of structure for string size */
1127 return GetTextExtentExPointW(hdc, str, count, 0, NULL, NULL, size);
1130 /***********************************************************************
1131 * GetTextExtentPointI [GDI32.@]
1133 * Computes width and height of the array of glyph indices.
1139 BOOL WINAPI GetTextExtentPointI(
1140 HDC hdc, /* [in] Handle of device context */
1141 const WORD *indices, /* [in] Address of glyph index array */
1142 INT count, /* [in] Number of glyphs in array */
1143 LPSIZE size) /* [out] Address of structure for string size */
1146 DC * dc = DC_GetDCPtr( hdc );
1147 if (!dc) return FALSE;
1150 ret = WineEngGetTextExtentPointI(dc->gdiFont, indices, count, size);
1151 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1152 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1153 size->cx += count * dc->charExtra;
1155 else if(dc->funcs->pGetTextExtentExPoint) {
1156 FIXME("calling GetTextExtentExPoint\n");
1157 ret = dc->funcs->pGetTextExtentExPoint( dc->physDev, (LPCWSTR)indices,
1158 count, 0, NULL, NULL, size );
1161 GDI_ReleaseObj( hdc );
1163 TRACE("(%p %p %d %p): returning %d x %d\n",
1164 hdc, indices, count, size, size->cx, size->cy );
1169 /***********************************************************************
1170 * GetTextExtentPointA (GDI32.@)
1172 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
1175 TRACE("not bug compatible.\n");
1176 return GetTextExtentPoint32A( hdc, str, count, size );
1179 /***********************************************************************
1180 * GetTextExtentPointW (GDI32.@)
1182 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1185 TRACE("not bug compatible.\n");
1186 return GetTextExtentPoint32W( hdc, str, count, size );
1190 /***********************************************************************
1191 * GetTextExtentExPointA (GDI32.@)
1193 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1194 INT maxExt, LPINT lpnFit,
1195 LPINT alpDx, LPSIZE size )
1203 NULL == (walpDx = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT))))
1206 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1207 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
1210 INT n = lpnFit ? *lpnFit : wlen;
1212 for(i = 0, j = 0; i < n; i++, j++)
1214 alpDx[j] = walpDx[i];
1215 if (IsDBCSLeadByte(str[j])) alpDx[++j] = walpDx[i];
1218 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1219 HeapFree( GetProcessHeap(), 0, p );
1220 HeapFree( GetProcessHeap(), 0, walpDx );
1225 /***********************************************************************
1226 * GetTextExtentExPointW (GDI32.@)
1228 * Return the size of the string as it would be if it was output properly by
1231 * This should include
1232 * - Intercharacter spacing
1233 * - justification spacing (not yet done)
1234 * - kerning? see below
1236 * Kerning. Since kerning would be carried out by the rendering code it should
1237 * be done by the driver. However they don't support it yet. Also I am not
1238 * yet persuaded that (certainly under Win95) any kerning is actually done.
1240 * str: According to MSDN this should be null-terminated. That is not true; a
1241 * null will not terminate it early.
1242 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1243 * than count. I have seen it be either the size of the full string or
1244 * 1 less than the size of the full string. I have not seen it bear any
1245 * resemblance to the portion that would fit.
1246 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1247 * trailing intercharacter spacing and any trailing justification.
1250 * Currently we do this by measuring each character etc. We should do it by
1251 * passing the request to the driver, perhaps by extending the
1252 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1253 * thinking about kerning issues and rounding issues in the justification.
1256 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1257 INT maxExt, LPINT lpnFit,
1258 LPINT alpDx, LPSIZE size )
1266 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1268 dc = DC_GetDCPtr(hdc);
1272 GetTextMetricsW(hdc, &tm);
1274 /* If we need to calculate nFit, then we need the partial extents even if
1275 the user hasn't provided us with an array. */
1278 dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]);
1281 GDI_ReleaseObj(hdc);
1282 SetLastError(ERROR_OUTOFMEMORY);
1290 ret = WineEngGetTextExtentExPoint(dc->gdiFont, str, count,
1291 0, NULL, dxs, size);
1292 else if (dc->funcs->pGetTextExtentExPoint)
1293 ret = dc->funcs->pGetTextExtentExPoint(dc->physDev, str, count,
1294 0, NULL, dxs, size);
1296 /* Perform device size to world size transformations. */
1299 INT extra = dc->charExtra,
1300 breakExtra = dc->breakExtra,
1301 breakRem = dc->breakRem,
1306 for (i = 0; i < count; ++i)
1308 dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
1309 dxs[i] += (i+1) * extra;
1310 if (count > 1 && (breakExtra || breakRem) && str[i] == tm.tmBreakChar)
1312 dxs[i] += breakExtra;
1319 if (dxs[i] <= maxExt)
1322 breakRem = dc->breakRem;
1324 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1325 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1327 if (!dxs && count > 1 && (breakExtra || breakRem))
1329 for (i = 0; i < count; i++)
1331 if (str[i] == tm.tmBreakChar)
1333 size->cx += breakExtra;
1348 HeapFree(GetProcessHeap(), 0, dxs);
1350 GDI_ReleaseObj( hdc );
1352 TRACE("returning %d %d x %d\n",nFit,size->cx,size->cy);
1356 /***********************************************************************
1357 * GetTextMetricsA (GDI32.@)
1359 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1363 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1364 FONT_TextMetricWToA( &tm32, metrics );
1368 /***********************************************************************
1369 * GetTextMetricsW (GDI32.@)
1371 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1374 DC * dc = DC_GetDCPtr( hdc );
1375 if (!dc) return FALSE;
1378 ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1379 else if (dc->funcs->pGetTextMetrics)
1380 ret = dc->funcs->pGetTextMetrics( dc->physDev, metrics );
1384 /* device layer returns values in device units
1385 * therefore we have to convert them to logical */
1387 metrics->tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1388 metrics->tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1390 #define WDPTOLP(x) ((x<0)? \
1391 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1392 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1393 #define HDPTOLP(y) ((y<0)? \
1394 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1395 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1397 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1398 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1399 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1400 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1401 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1402 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1403 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1404 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1408 TRACE("text metrics:\n"
1409 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1410 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1411 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1412 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1413 " PitchAndFamily = %02x\n"
1414 " --------------------\n"
1415 " InternalLeading = %i\n"
1419 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1420 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1421 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1422 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1423 metrics->tmPitchAndFamily,
1424 metrics->tmInternalLeading,
1427 metrics->tmHeight );
1429 GDI_ReleaseObj( hdc );
1434 /***********************************************************************
1435 * GetOutlineTextMetrics [GDI.308] Gets metrics for TrueType fonts.
1438 * lpOTM should be LPOUTLINETEXTMETRIC
1441 * Success: Non-zero or size of required buffer
1444 UINT16 WINAPI GetOutlineTextMetrics16(
1445 HDC16 hdc, /* [in] Handle of device context */
1446 UINT16 cbData, /* [in] Size of metric data array */
1447 LPOUTLINETEXTMETRIC16 lpOTM) /* [out] Address of metric data array */
1449 FIXME("(%04x,%04x,%p): stub\n", hdc,cbData,lpOTM);
1454 /***********************************************************************
1455 * GetOutlineTextMetricsA (GDI32.@)
1456 * Gets metrics for TrueType fonts.
1459 * If the supplied buffer isn't big enough Windows partially fills it up to
1460 * its given length and returns that length.
1463 * Success: Non-zero or size of required buffer
1466 UINT WINAPI GetOutlineTextMetricsA(
1467 HDC hdc, /* [in] Handle of device context */
1468 UINT cbData, /* [in] Size of metric data array */
1469 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1471 char buf[512], *ptr;
1473 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1474 OUTLINETEXTMETRICA *output = lpOTM;
1477 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1479 if(ret > sizeof(buf))
1480 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1481 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1483 needed = sizeof(OUTLINETEXTMETRICA);
1484 if(lpOTMW->otmpFamilyName)
1485 needed += WideCharToMultiByte(CP_ACP, 0,
1486 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1487 NULL, 0, NULL, NULL);
1488 if(lpOTMW->otmpFaceName)
1489 needed += WideCharToMultiByte(CP_ACP, 0,
1490 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1491 NULL, 0, NULL, NULL);
1492 if(lpOTMW->otmpStyleName)
1493 needed += WideCharToMultiByte(CP_ACP, 0,
1494 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1495 NULL, 0, NULL, NULL);
1496 if(lpOTMW->otmpFullName)
1497 needed += WideCharToMultiByte(CP_ACP, 0,
1498 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1499 NULL, 0, NULL, NULL);
1506 TRACE("needed = %d\n", needed);
1508 /* Since the supplied buffer isn't big enough, we'll alloc one
1509 that is and memcpy the first cbData bytes into the lpOTM at
1511 output = HeapAlloc(GetProcessHeap(), 0, needed);
1513 ret = output->otmSize = min(needed, cbData);
1514 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1515 output->otmFiller = 0;
1516 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1517 output->otmfsSelection = lpOTMW->otmfsSelection;
1518 output->otmfsType = lpOTMW->otmfsType;
1519 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1520 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1521 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1522 output->otmEMSquare = lpOTMW->otmEMSquare;
1523 output->otmAscent = lpOTMW->otmAscent;
1524 output->otmDescent = lpOTMW->otmDescent;
1525 output->otmLineGap = lpOTMW->otmLineGap;
1526 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1527 output->otmsXHeight = lpOTMW->otmsXHeight;
1528 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1529 output->otmMacAscent = lpOTMW->otmMacAscent;
1530 output->otmMacDescent = lpOTMW->otmMacDescent;
1531 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1532 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1533 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1534 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1535 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1536 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1537 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1538 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1539 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1540 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1543 ptr = (char*)(output + 1);
1544 left = needed - sizeof(*output);
1546 if(lpOTMW->otmpFamilyName) {
1547 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1548 len = WideCharToMultiByte(CP_ACP, 0,
1549 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1550 ptr, left, NULL, NULL);
1554 output->otmpFamilyName = 0;
1556 if(lpOTMW->otmpFaceName) {
1557 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1558 len = WideCharToMultiByte(CP_ACP, 0,
1559 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1560 ptr, left, NULL, NULL);
1564 output->otmpFaceName = 0;
1566 if(lpOTMW->otmpStyleName) {
1567 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1568 len = WideCharToMultiByte(CP_ACP, 0,
1569 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1570 ptr, left, NULL, NULL);
1574 output->otmpStyleName = 0;
1576 if(lpOTMW->otmpFullName) {
1577 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1578 len = WideCharToMultiByte(CP_ACP, 0,
1579 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1580 ptr, left, NULL, NULL);
1583 output->otmpFullName = 0;
1587 if(output != lpOTM) {
1588 memcpy(lpOTM, output, cbData);
1589 HeapFree(GetProcessHeap(), 0, output);
1591 /* check if the string offsets really fit into the provided size */
1592 /* FIXME: should we check string length as well? */
1593 /* make sure that we don't read/write beyond the provided buffer */
1594 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(LPSTR))
1596 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1597 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1600 /* make sure that we don't read/write beyond the provided buffer */
1601 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(LPSTR))
1603 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1604 lpOTM->otmpFaceName = 0; /* doesn't fit */
1607 /* make sure that we don't read/write beyond the provided buffer */
1608 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(LPSTR))
1610 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1611 lpOTM->otmpStyleName = 0; /* doesn't fit */
1614 /* make sure that we don't read/write beyond the provided buffer */
1615 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(LPSTR))
1617 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1618 lpOTM->otmpFullName = 0; /* doesn't fit */
1623 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1624 HeapFree(GetProcessHeap(), 0, lpOTMW);
1630 /***********************************************************************
1631 * GetOutlineTextMetricsW [GDI32.@]
1633 UINT WINAPI GetOutlineTextMetricsW(
1634 HDC hdc, /* [in] Handle of device context */
1635 UINT cbData, /* [in] Size of metric data array */
1636 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1638 DC *dc = DC_GetDCPtr( hdc );
1639 OUTLINETEXTMETRICW *output = lpOTM;
1642 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1646 ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, output);
1649 output = HeapAlloc(GetProcessHeap(), 0, ret);
1650 WineEngGetOutlineTextMetrics(dc->gdiFont, ret, output);
1653 #define WDPTOLP(x) ((x<0)? \
1654 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1655 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1656 #define HDPTOLP(y) ((y<0)? \
1657 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1658 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1660 output->otmTextMetrics.tmHeight = HDPTOLP(output->otmTextMetrics.tmHeight);
1661 output->otmTextMetrics.tmAscent = HDPTOLP(output->otmTextMetrics.tmAscent);
1662 output->otmTextMetrics.tmDescent = HDPTOLP(output->otmTextMetrics.tmDescent);
1663 output->otmTextMetrics.tmInternalLeading = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1664 output->otmTextMetrics.tmExternalLeading = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1665 output->otmTextMetrics.tmAveCharWidth = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1666 output->otmTextMetrics.tmMaxCharWidth = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1667 output->otmTextMetrics.tmOverhang = WDPTOLP(output->otmTextMetrics.tmOverhang);
1668 output->otmAscent = HDPTOLP(output->otmAscent);
1669 output->otmDescent = HDPTOLP(output->otmDescent);
1670 output->otmLineGap = HDPTOLP(output->otmLineGap);
1671 output->otmsCapEmHeight = HDPTOLP(output->otmsCapEmHeight);
1672 output->otmsXHeight = HDPTOLP(output->otmsXHeight);
1673 output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1674 output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1675 output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1676 output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1677 output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1678 output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1679 output->otmMacLineGap = HDPTOLP(output->otmMacLineGap);
1680 output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1681 output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1682 output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1683 output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1684 output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1685 output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1686 output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1687 output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1688 output->otmsStrikeoutSize = HDPTOLP(output->otmsStrikeoutSize);
1689 output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1690 output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1691 output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1694 if(output != lpOTM) {
1695 memcpy(lpOTM, output, cbData);
1696 HeapFree(GetProcessHeap(), 0, output);
1702 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1703 but really this should just be a return 0. */
1705 ret = sizeof(*lpOTM);
1710 memset(lpOTM, 0, ret);
1711 lpOTM->otmSize = sizeof(*lpOTM);
1712 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1714 Further fill of the structure not implemented,
1715 Needs real values for the structure members
1720 GDI_ReleaseObj(hdc);
1725 /***********************************************************************
1726 * GetCharWidthW (GDI32.@)
1727 * GetCharWidth32W (GDI32.@)
1729 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1734 DC * dc = DC_GetDCPtr( hdc );
1735 if (!dc) return FALSE;
1738 ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1739 else if (dc->funcs->pGetCharWidth)
1740 ret = dc->funcs->pGetCharWidth( dc->physDev, firstChar, lastChar, buffer);
1744 /* convert device units to logical */
1745 for( i = firstChar; i <= lastChar; i++, buffer++ )
1746 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1749 GDI_ReleaseObj( hdc );
1754 /***********************************************************************
1755 * GetCharWidthA (GDI32.@)
1756 * GetCharWidth32A (GDI32.@)
1758 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1761 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1766 if(count <= 0) return FALSE;
1768 str = HeapAlloc(GetProcessHeap(), 0, count);
1769 for(i = 0; i < count; i++)
1770 str[i] = (BYTE)(firstChar + i);
1772 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1774 for(i = 0; i < wlen; i++)
1776 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1784 HeapFree(GetProcessHeap(), 0, str);
1785 HeapFree(GetProcessHeap(), 0, wstr);
1791 /***********************************************************************
1792 * ExtTextOutA (GDI32.@)
1796 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1797 const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1805 if (flags & ETO_GLYPH_INDEX)
1806 return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
1808 p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
1811 unsigned int i = 0, j = 0;
1813 lpDxW = HeapAlloc( GetProcessHeap(), 0, wlen*sizeof(INT));
1815 if(IsDBCSLeadByteEx(codepage, str[i])) {
1816 lpDxW[j++] = lpDx[i] + lpDx[i+1];
1819 lpDxW[j++] = lpDx[i];
1825 ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1827 HeapFree( GetProcessHeap(), 0, p );
1828 HeapFree( GetProcessHeap(), 0, lpDxW );
1833 /***********************************************************************
1834 * ExtTextOutW (GDI32.@)
1836 * Draws text using the currently selected font, background color, and text color.
1840 * x,y [I] coordinates of string
1842 * ETO_GRAYED - undocumented on MSDN
1843 * ETO_OPAQUE - use background color for fill the rectangle
1844 * ETO_CLIPPED - clipping text to the rectangle
1845 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1846 * than encoded characters. Implies ETO_IGNORELANGUAGE
1847 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1848 * Affects BiDi ordering
1849 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1850 * ETO_PDY - unimplemented
1851 * ETO_NUMERICSLATIN - unimplemented always assumed -
1852 * do not translate numbers into locale representations
1853 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1854 * lprect [I] dimensions for clipping or/and opaquing
1855 * str [I] text string
1856 * count [I] number of symbols in string
1857 * lpDx [I] optional parameter with distance between drawing characters
1863 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1864 const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1867 LPWSTR reordered_str = (LPWSTR)str;
1868 WORD *glyphs = NULL;
1869 UINT align = GetTextAlign( hdc );
1873 double cosEsc, sinEsc;
1874 INT *deltas = NULL, char_extra;
1877 BOOL done_extents = FALSE;
1878 INT width = 0, xwidth = 0, ywidth = 0;
1880 DC * dc = DC_GetDCUpdate( hdc );
1883 if (!dc) return FALSE;
1885 breakRem = dc->breakRem;
1887 if (flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY))
1888 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY unimplemented\n");
1890 if (!dc->funcs->pExtTextOut && !PATH_IsPathOpen(dc->path))
1892 GDI_ReleaseObj( hdc );
1896 type = GetObjectType(hdc);
1897 if(type == OBJ_METADC || type == OBJ_ENHMETADC)
1899 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, flags, lprect, str, count, lpDx);
1900 GDI_ReleaseObj( hdc );
1905 flags &= ~ETO_CLIPPED;
1907 if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && BidiAvail && count > 0 )
1909 reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1911 BIDI_Reorder( str, count, GCP_REORDER,
1912 ((flags&ETO_RTLREADING)!=0 || (GetTextAlign(hdc)&TA_RTLREADING)!=0)?
1913 WINE_GCPW_FORCE_RTL:WINE_GCPW_FORCE_LTR,
1914 reordered_str, count, NULL );
1916 flags |= ETO_IGNORELANGUAGE;
1919 TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc, x, y, flags,
1920 lprect, debugstr_wn(str, count), count, lpDx);
1922 if(flags & ETO_GLYPH_INDEX)
1923 glyphs = reordered_str;
1926 TRACE("rect: %d,%d - %d,%d\n", lprect->left, lprect->top, lprect->right,
1928 TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
1930 if(align & TA_UPDATECP)
1932 GetCurrentPositionEx( hdc, &pt );
1937 GetTextMetricsW(hdc, &tm);
1938 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1940 if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
1941 lf.lfEscapement = 0;
1943 if(lf.lfEscapement != 0)
1945 cosEsc = cos(lf.lfEscapement * M_PI / 1800);
1946 sinEsc = sin(lf.lfEscapement * M_PI / 1800);
1954 if(flags & (ETO_CLIPPED | ETO_OPAQUE))
1958 if(flags & ETO_GLYPH_INDEX)
1959 GetTextExtentPointI(hdc, glyphs, count, &sz);
1961 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1963 done_extents = TRUE;
1966 rc.right = x + sz.cx;
1967 rc.bottom = y + sz.cy;
1974 LPtoDP(hdc, (POINT*)&rc, 2);
1976 if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
1977 if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
1980 if ((flags & ETO_OPAQUE) && !PATH_IsPathOpen(dc->path))
1981 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1991 LPtoDP(hdc, &pt, 1);
1995 char_extra = GetTextCharacterExtra(hdc);
1996 if(char_extra || dc->breakExtra || breakRem || lpDx)
2000 deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT));
2001 for(i = 0; i < count; i++)
2003 if(lpDx && (flags & ETO_PDY))
2004 deltas[i] = lpDx[i*2] + char_extra;
2006 deltas[i] = lpDx[i] + char_extra;
2009 if(flags & ETO_GLYPH_INDEX)
2010 GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
2012 GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
2014 deltas[i] = tmpsz.cx;
2017 if (!(flags & ETO_GLYPH_INDEX) && (dc->breakExtra || breakRem) && reordered_str[i] == tm.tmBreakChar)
2019 deltas[i] = deltas[i] + dc->breakExtra;
2026 deltas[i] = INTERNAL_XWSTODS(dc, deltas[i]);
2034 if(flags & ETO_GLYPH_INDEX)
2035 GetTextExtentPointI(hdc, glyphs, count, &sz);
2037 GetTextExtentPointW(hdc, reordered_str, count, &sz);
2038 done_extents = TRUE;
2040 width = INTERNAL_XWSTODS(dc, sz.cx);
2042 xwidth = width * cosEsc;
2043 ywidth = width * sinEsc;
2045 tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
2046 tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
2047 switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
2050 if (align & TA_UPDATECP)
2054 DPtoLP(hdc, &pt, 1);
2055 MoveToEx(hdc, pt.x, pt.y, NULL);
2067 if (align & TA_UPDATECP)
2071 DPtoLP(hdc, &pt, 1);
2072 MoveToEx(hdc, pt.x, pt.y, NULL);
2077 switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
2080 y += tm.tmAscent * cosEsc;
2081 x += tm.tmAscent * sinEsc;
2085 y -= tm.tmDescent * cosEsc;
2086 x -= tm.tmDescent * sinEsc;
2093 if (GetBkMode(hdc) != TRANSPARENT && !PATH_IsPathOpen(dc->path))
2095 if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
2097 if(!(flags & ETO_OPAQUE) || x < rc.left || x + width >= rc.right ||
2098 y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
2102 rc.right = x + width;
2103 rc.top = y - tm.tmAscent;
2104 rc.bottom = y + tm.tmDescent;
2105 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
2110 if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
2112 HFONT orig_font = dc->hFont, cur_font;
2114 INT span = 0, *offsets = NULL, i;
2116 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2117 for(i = 0; i < count; i++)
2119 WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
2120 if(cur_font != dc->hFont)
2125 offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
2130 for(j = 1; j < count; j++)
2132 GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
2133 offsets[j] = offsets[j-1] + INTERNAL_XWSTODS(dc, tmpsz.cx);
2138 for(j = 1; j < count; j++)
2139 offsets[j] = offsets[j-1] + deltas[j];
2144 if (PATH_IsPathOpen(dc->path))
2145 ret = PATH_ExtTextOut(dc, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
2146 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2147 glyphs, span, deltas ? deltas + i - span : NULL);
2149 dc->funcs->pExtTextOut(dc->physDev, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
2150 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2151 glyphs, span, deltas ? deltas + i - span : NULL);
2154 SelectObject(hdc, cur_font);
2156 glyphs[span++] = glyph;
2160 if (PATH_IsPathOpen(dc->path))
2161 ret = PATH_ExtTextOut(dc, x + (offsets ? offsets[count - span] * cosEsc : 0),
2162 y - (offsets ? offsets[count - span] * sinEsc : 0),
2163 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2164 glyphs, span, deltas ? deltas + count - span : NULL);
2166 ret = dc->funcs->pExtTextOut(dc->physDev, x + (offsets ? offsets[count - span] * cosEsc : 0),
2167 y - (offsets ? offsets[count - span] * sinEsc : 0),
2168 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2169 glyphs, span, deltas ? deltas + count - span : NULL);
2170 SelectObject(hdc, orig_font);
2171 HeapFree(GetProcessHeap(), 0, offsets);
2177 if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
2179 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2180 GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
2181 flags |= ETO_GLYPH_INDEX;
2184 if (PATH_IsPathOpen(dc->path))
2185 ret = PATH_ExtTextOut(dc, x, y, (flags & ~ETO_OPAQUE), &rc,
2186 glyphs ? glyphs : reordered_str, count, deltas);
2188 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, (flags & ~ETO_OPAQUE), &rc,
2189 glyphs ? glyphs : reordered_str, count, deltas);
2193 HeapFree(GetProcessHeap(), 0, deltas);
2194 if(glyphs != reordered_str)
2195 HeapFree(GetProcessHeap(), 0, glyphs);
2196 if(reordered_str != str)
2197 HeapFree(GetProcessHeap(), 0, reordered_str);
2199 GDI_ReleaseObj( hdc );
2201 if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2203 int underlinePos, strikeoutPos;
2204 int underlineWidth, strikeoutWidth;
2205 UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2206 OUTLINETEXTMETRICW* otm = NULL;
2211 underlineWidth = tm.tmAscent / 20 + 1;
2212 strikeoutPos = tm.tmAscent / 2;
2213 strikeoutWidth = underlineWidth;
2217 otm = HeapAlloc(GetProcessHeap(), 0, size);
2218 GetOutlineTextMetricsW(hdc, size, otm);
2219 underlinePos = otm->otmsUnderscorePosition;
2220 underlineWidth = otm->otmsUnderscoreSize;
2221 strikeoutPos = otm->otmsStrikeoutPosition;
2222 strikeoutWidth = otm->otmsStrikeoutSize;
2223 HeapFree(GetProcessHeap(), 0, otm);
2226 if (PATH_IsPathOpen(dc->path))
2230 HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2232 hbrush = SelectObject(hdc, hbrush);
2233 hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2237 pts[0].x = x - underlinePos * sinEsc;
2238 pts[0].y = y - underlinePos * cosEsc;
2239 pts[1].x = x + xwidth - underlinePos * sinEsc;
2240 pts[1].y = y - ywidth - underlinePos * cosEsc;
2241 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2242 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2243 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2244 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2245 pts[4].x = pts[0].x;
2246 pts[4].y = pts[0].y;
2247 DPtoLP(hdc, pts, 5);
2248 Polygon(hdc, pts, 5);
2253 pts[0].x = x - strikeoutPos * sinEsc;
2254 pts[0].y = y - strikeoutPos * cosEsc;
2255 pts[1].x = x + xwidth - strikeoutPos * sinEsc;
2256 pts[1].y = y - ywidth - strikeoutPos * cosEsc;
2257 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2258 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2259 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2260 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2261 pts[4].x = pts[0].x;
2262 pts[4].y = pts[0].y;
2263 DPtoLP(hdc, pts, 5);
2264 Polygon(hdc, pts, 5);
2267 SelectObject(hdc, hpen);
2268 hbrush = SelectObject(hdc, hbrush);
2269 DeleteObject(hbrush);
2273 POINT pts[2], oldpt;
2278 hpen = CreatePen(PS_SOLID, underlineWidth, GetTextColor(hdc));
2279 hpen = SelectObject(hdc, hpen);
2282 pts[1].x = x + xwidth;
2283 pts[1].y = y - ywidth;
2284 DPtoLP(hdc, pts, 2);
2285 MoveToEx(hdc, pts[0].x - underlinePos * sinEsc, pts[0].y - underlinePos * cosEsc, &oldpt);
2286 LineTo(hdc, pts[1].x - underlinePos * sinEsc, pts[1].y - underlinePos * cosEsc);
2287 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2288 DeleteObject(SelectObject(hdc, hpen));
2293 hpen = CreatePen(PS_SOLID, strikeoutWidth, GetTextColor(hdc));
2294 hpen = SelectObject(hdc, hpen);
2297 pts[1].x = x + xwidth;
2298 pts[1].y = y - ywidth;
2299 DPtoLP(hdc, pts, 2);
2300 MoveToEx(hdc, pts[0].x - strikeoutPos * sinEsc, pts[0].y - strikeoutPos * cosEsc, &oldpt);
2301 LineTo(hdc, pts[1].x - strikeoutPos * sinEsc, pts[1].y - strikeoutPos * cosEsc);
2302 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2303 DeleteObject(SelectObject(hdc, hpen));
2312 /***********************************************************************
2313 * TextOutA (GDI32.@)
2315 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2317 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2321 /***********************************************************************
2322 * TextOutW (GDI32.@)
2324 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2326 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2330 /***********************************************************************
2331 * PolyTextOutA (GDI32.@)
2335 BOOL WINAPI PolyTextOutA ( HDC hdc, /* [in] Handle to device context */
2336 PPOLYTEXTA pptxt, /* [in] Array of strings */
2337 INT cStrings ) /* [in] Number of strings in array */
2339 for (; cStrings>0; cStrings--, pptxt++)
2340 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2347 /***********************************************************************
2348 * PolyTextOutW (GDI32.@)
2350 * Draw several Strings
2356 BOOL WINAPI PolyTextOutW ( HDC hdc, /* [in] Handle to device context */
2357 PPOLYTEXTW pptxt, /* [in] Array of strings */
2358 INT cStrings ) /* [in] Number of strings in array */
2360 for (; cStrings>0; cStrings--, pptxt++)
2361 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2367 /* FIXME: all following APIs ******************************************/
2370 /***********************************************************************
2371 * SetMapperFlags (GDI32.@)
2373 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
2375 DC *dc = DC_GetDCPtr( hDC );
2378 if(dc->funcs->pSetMapperFlags)
2380 ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
2381 /* FIXME: ret is just a success flag, we should return a proper value */
2384 FIXME("(%p, 0x%08x): stub - harmless\n", hDC, dwFlag);
2385 GDI_ReleaseObj( hDC );
2389 /***********************************************************************
2390 * GetAspectRatioFilterEx (GDI.486)
2392 BOOL16 WINAPI GetAspectRatioFilterEx16( HDC16 hdc, LPSIZE16 pAspectRatio )
2394 FIXME("(%04x, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2398 /***********************************************************************
2399 * GetAspectRatioFilterEx (GDI32.@)
2401 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2403 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2408 /***********************************************************************
2409 * GetCharABCWidthsA (GDI32.@)
2411 * See GetCharABCWidthsW.
2413 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2416 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
2421 if(count <= 0) return FALSE;
2423 str = HeapAlloc(GetProcessHeap(), 0, count);
2424 for(i = 0; i < count; i++)
2425 str[i] = (BYTE)(firstChar + i);
2427 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
2429 for(i = 0; i < wlen; i++)
2431 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2439 HeapFree(GetProcessHeap(), 0, str);
2440 HeapFree(GetProcessHeap(), 0, wstr);
2446 /******************************************************************************
2447 * GetCharABCWidthsW [GDI32.@]
2449 * Retrieves widths of characters in range.
2452 * hdc [I] Handle of device context
2453 * firstChar [I] First character in range to query
2454 * lastChar [I] Last character in range to query
2455 * abc [O] Address of character-width structure
2458 * Only works with TrueType fonts
2464 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2467 DC *dc = DC_GetDCPtr(hdc);
2471 if (!dc) return FALSE;
2474 ret = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
2480 /* convert device units to logical */
2481 for( i = firstChar; i <= lastChar; i++, abc++ ) {
2482 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2483 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2484 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2489 GDI_ReleaseObj(hdc);
2494 /******************************************************************************
2495 * GetCharABCWidthsI [GDI32.@]
2497 * Retrieves widths of characters in range.
2500 * hdc [I] Handle of device context
2501 * firstChar [I] First glyphs in range to query
2502 * count [I] Last glyphs in range to query
2503 * pgi [i] Array of glyphs to query
2504 * abc [O] Address of character-width structure
2507 * Only works with TrueType fonts
2513 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2514 LPWORD pgi, LPABC abc)
2516 DC *dc = DC_GetDCPtr(hdc);
2520 if (!dc) return FALSE;
2523 ret = WineEngGetCharABCWidthsI( dc->gdiFont, firstChar, count, pgi, abc );
2529 /* convert device units to logical */
2530 for( i = 0; i < count; i++, abc++ ) {
2531 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2532 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2533 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2538 GDI_ReleaseObj(hdc);
2543 /***********************************************************************
2544 * GetGlyphOutlineA (GDI32.@)
2546 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2547 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2548 LPVOID lpBuffer, const MAT2 *lpmat2 )
2554 if(!(fuFormat & GGO_GLYPH_INDEX)) {
2557 if(uChar > 0xff) { /* but, 2 bytes character only */
2559 mbchs[0] = (uChar & 0xff00) >> 8;
2560 mbchs[1] = (uChar & 0xff);
2563 mbchs[0] = (uChar & 0xff);
2565 p = FONT_mbtowc(hdc, mbchs, len, NULL, NULL);
2569 ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
2571 HeapFree(GetProcessHeap(), 0, p);
2575 /***********************************************************************
2576 * GetGlyphOutlineW (GDI32.@)
2578 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2579 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2580 LPVOID lpBuffer, const MAT2 *lpmat2 )
2582 DC *dc = DC_GetDCPtr(hdc);
2585 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2586 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2588 if(!dc) return GDI_ERROR;
2591 ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
2592 cbBuffer, lpBuffer, lpmat2);
2596 GDI_ReleaseObj(hdc);
2601 /***********************************************************************
2602 * CreateScalableFontResourceA (GDI32.@)
2604 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2605 LPCSTR lpszResourceFile,
2606 LPCSTR lpszFontFile,
2607 LPCSTR lpszCurrentPath )
2611 /* fHidden=1 - only visible for the calling app, read-only, not
2612 * enumbered with EnumFonts/EnumFontFamilies
2613 * lpszCurrentPath can be NULL
2615 FIXME("(%d,%s,%s,%s): stub\n",
2616 fHidden, debugstr_a(lpszResourceFile), debugstr_a(lpszFontFile),
2617 debugstr_a(lpszCurrentPath) );
2619 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2620 if ((f = CreateFileA(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2622 SetLastError(ERROR_FILE_EXISTS);
2625 return FALSE; /* create failed */
2628 /***********************************************************************
2629 * CreateScalableFontResourceW (GDI32.@)
2631 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2632 LPCWSTR lpszResourceFile,
2633 LPCWSTR lpszFontFile,
2634 LPCWSTR lpszCurrentPath )
2636 FIXME("(%d,%p,%p,%p): stub\n",
2637 fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
2638 return FALSE; /* create failed */
2641 /*************************************************************************
2642 * GetKerningPairsA (GDI32.@)
2644 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2645 LPKERNINGPAIR kern_pairA )
2650 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2651 KERNINGPAIR *kern_pairW;
2653 if (!cPairs && kern_pairA)
2655 SetLastError(ERROR_INVALID_PARAMETER);
2659 charset = GetTextCharset(hDC);
2660 if (!TranslateCharsetInfo((DWORD *)charset, &csi, TCI_SRCCHARSET))
2662 FIXME("Can't find codepage for charset %d\n", charset);
2665 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2666 * to fail on an invalid character for CP_SYMBOL.
2668 cpi.DefaultChar[0] = 0;
2669 if (csi.ciACP != CP_SYMBOL && !GetCPInfo(csi.ciACP, &cpi))
2671 FIXME("Can't find codepage %u info\n", csi.ciACP);
2674 TRACE("charset %d => codepage %u\n", charset, csi.ciACP);
2676 total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2677 if (!total_kern_pairs) return 0;
2679 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2680 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2682 for (i = 0; i < total_kern_pairs; i++)
2686 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2689 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2692 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2697 if (kern_pairs_copied >= cPairs) break;
2699 kern_pairA->wFirst = (BYTE)first;
2700 kern_pairA->wSecond = (BYTE)second;
2701 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2704 kern_pairs_copied++;
2707 HeapFree(GetProcessHeap(), 0, kern_pairW);
2709 return kern_pairs_copied;
2712 /*************************************************************************
2713 * GetKerningPairsW (GDI32.@)
2715 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2716 LPKERNINGPAIR lpKerningPairs )
2721 TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2723 if (!cPairs && lpKerningPairs)
2725 SetLastError(ERROR_INVALID_PARAMETER);
2729 dc = DC_GetDCPtr(hDC);
2733 ret = WineEngGetKerningPairs(dc->gdiFont, cPairs, lpKerningPairs);
2735 GDI_ReleaseObj(hDC);
2739 /*************************************************************************
2740 * TranslateCharsetInfo [GDI32.@]
2742 * Fills a CHARSETINFO structure for a character set, code page, or
2743 * font. This allows making the correspondance between different labelings
2744 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2745 * of the same encoding.
2747 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2748 * only one codepage should be set in *lpSrc.
2751 * TRUE on success, FALSE on failure.
2754 BOOL WINAPI TranslateCharsetInfo(
2755 LPDWORD lpSrc, /* [in]
2756 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2757 if flags == TCI_SRCCHARSET: a character set value
2758 if flags == TCI_SRCCODEPAGE: a code page value
2760 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2761 DWORD flags /* [in] determines interpretation of lpSrc */)
2765 case TCI_SRCFONTSIG:
2766 while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
2768 case TCI_SRCCODEPAGE:
2769 while ((UINT) (lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
2771 case TCI_SRCCHARSET:
2772 while ((UINT) (lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
2777 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2778 memcpy(lpCs, &FONT_tci[index], sizeof(CHARSETINFO));
2782 /*************************************************************************
2783 * GetFontLanguageInfo (GDI32.@)
2785 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2787 FONTSIGNATURE fontsig;
2788 static const DWORD GCP_DBCS_MASK=0x003F0000,
2789 GCP_DIACRITIC_MASK=0x00000000,
2790 FLI_GLYPHS_MASK=0x00000000,
2791 GCP_GLYPHSHAPE_MASK=0x00000040,
2792 GCP_KASHIDA_MASK=0x00000000,
2793 GCP_LIGATE_MASK=0x00000000,
2794 GCP_USEKERNING_MASK=0x00000000,
2795 GCP_REORDER_MASK=0x00000060;
2799 GetTextCharsetInfo( hdc, &fontsig, 0 );
2800 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2802 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2805 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2806 result|=GCP_DIACRITIC;
2808 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2811 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2812 result|=GCP_GLYPHSHAPE;
2814 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2815 result|=GCP_KASHIDA;
2817 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2820 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2821 result|=GCP_USEKERNING;
2823 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2824 if( GetTextAlign( hdc) & TA_RTLREADING )
2825 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2826 result|=GCP_REORDER;
2832 /*************************************************************************
2833 * GetFontData [GDI32.@]
2835 * Retrieve data for TrueType font.
2839 * success: Number of bytes returned
2840 * failure: GDI_ERROR
2844 * Calls SetLastError()
2847 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2848 LPVOID buffer, DWORD length)
2850 DC *dc = DC_GetDCPtr(hdc);
2851 DWORD ret = GDI_ERROR;
2853 if(!dc) return GDI_ERROR;
2856 ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2858 GDI_ReleaseObj(hdc);
2862 /*************************************************************************
2863 * GetGlyphIndicesA [GDI32.@]
2865 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2866 LPWORD pgi, DWORD flags)
2872 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2873 hdc, debugstr_an(lpstr, count), count, pgi, flags);
2875 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2876 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2877 HeapFree(GetProcessHeap(), 0, lpstrW);
2882 /*************************************************************************
2883 * GetGlyphIndicesW [GDI32.@]
2885 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2886 LPWORD pgi, DWORD flags)
2888 DC *dc = DC_GetDCPtr(hdc);
2889 DWORD ret = GDI_ERROR;
2891 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2892 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2894 if(!dc) return GDI_ERROR;
2897 ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2899 GDI_ReleaseObj(hdc);
2903 /*************************************************************************
2904 * GetCharacterPlacementA [GDI32.@]
2906 * See GetCharacterPlacementW.
2909 * the web browser control of ie4 calls this with dwFlags=0
2912 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2913 INT nMaxExtent, GCP_RESULTSA *lpResults,
2918 GCP_RESULTSW resultsW;
2922 TRACE("%s, %d, %d, 0x%08x\n",
2923 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2925 /* both structs are equal in size */
2926 memcpy(&resultsW, lpResults, sizeof(resultsW));
2928 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2929 if(lpResults->lpOutString)
2930 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2932 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2934 lpResults->nGlyphs = resultsW.nGlyphs;
2935 lpResults->nMaxFit = resultsW.nMaxFit;
2937 if(lpResults->lpOutString) {
2938 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2939 lpResults->lpOutString, uCount, NULL, NULL );
2942 HeapFree(GetProcessHeap(), 0, lpStringW);
2943 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2948 /*************************************************************************
2949 * GetCharacterPlacementW [GDI32.@]
2951 * Retrieve information about a string. This includes the width, reordering,
2952 * Glyphing and so on.
2956 * The width and height of the string if successful, 0 if failed.
2960 * All flags except GCP_REORDER are not yet implemented.
2961 * Reordering is not 100% complient to the Windows BiDi method.
2962 * Caret positioning is not yet implemented for BiDi.
2963 * Classes are not yet implemented.
2967 GetCharacterPlacementW(
2968 HDC hdc, /* [in] Device context for which the rendering is to be done */
2969 LPCWSTR lpString, /* [in] The string for which information is to be returned */
2970 INT uCount, /* [in] Number of WORDS in string. */
2971 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
2972 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2973 DWORD dwFlags /* [in] Flags specifying how to process the string */
2980 TRACE("%s, %d, %d, 0x%08x\n",
2981 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2983 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2984 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2985 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2986 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2987 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2989 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08x ignored\n", dwFlags);
2990 if(lpResults->lpClass) FIXME("classes not implemented\n");
2991 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2992 FIXME("Caret positions for complex scripts not implemented\n");
2994 nSet = (UINT)uCount;
2995 if(nSet > lpResults->nGlyphs)
2996 nSet = lpResults->nGlyphs;
2998 /* return number of initialized fields */
2999 lpResults->nGlyphs = nSet;
3001 if((dwFlags&GCP_REORDER)==0 || !BidiAvail)
3003 /* Treat the case where no special handling was requested in a fastpath way */
3004 /* copy will do if the GCP_REORDER flag is not set */
3005 if(lpResults->lpOutString)
3006 memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
3008 if(lpResults->lpOrder)
3010 for(i = 0; i < nSet; i++)
3011 lpResults->lpOrder[i] = i;
3015 BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
3016 nSet, lpResults->lpOrder );
3019 /* FIXME: Will use the placement chars */
3020 if (lpResults->lpDx)
3023 for (i = 0; i < nSet; i++)
3025 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
3026 lpResults->lpDx[i]= c;
3030 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
3034 lpResults->lpCaretPos[0] = 0;
3035 for (i = 1; i < nSet; i++)
3036 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
3037 lpResults->lpCaretPos[i] = (pos += size.cx);
3040 if(lpResults->lpGlyphs)
3041 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
3043 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
3044 ret = MAKELONG(size.cx, size.cy);
3049 /*************************************************************************
3050 * GetCharABCWidthsFloatA [GDI32.@]
3052 * See GetCharABCWidthsFloatW.
3054 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3056 INT i, wlen, count = (INT)(last - first + 1);
3061 if (count <= 0) return FALSE;
3063 str = HeapAlloc(GetProcessHeap(), 0, count);
3065 for(i = 0; i < count; i++)
3066 str[i] = (BYTE)(first + i);
3068 wstr = FONT_mbtowc( hdc, str, count, &wlen, NULL );
3070 for (i = 0; i < wlen; i++)
3072 if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
3080 HeapFree( GetProcessHeap(), 0, str );
3081 HeapFree( GetProcessHeap(), 0, wstr );
3086 /*************************************************************************
3087 * GetCharABCWidthsFloatW [GDI32.@]
3089 * Retrieves widths of a range of characters.
3092 * hdc [I] Handle to device context.
3093 * first [I] First character in range to query.
3094 * last [I] Last character in range to query.
3095 * abcf [O] Array of LPABCFLOAT structures.
3102 * Only works with TrueType fonts. It also doesn't return real
3103 * floats but converted integers because it's implemented on
3104 * top of GetCharABCWidthsW.
3106 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3109 unsigned int i, size = sizeof(ABC) * (last - first + 1);
3112 TRACE("%p, %d, %d, %p - partial stub\n", hdc, first, last, abcf);
3114 abc = HeapAlloc( GetProcessHeap(), 0, size );
3115 if (!abc) return FALSE;
3117 ret = GetCharABCWidthsW( hdc, first, last, abc );
3120 for (i = first; i <= last; i++, abc++, abcf++)
3122 abcf->abcfA = abc->abcA;
3123 abcf->abcfB = abc->abcB;
3124 abcf->abcfC = abc->abcC;
3127 HeapFree( GetProcessHeap(), 0, abc );
3131 /*************************************************************************
3132 * GetCharWidthFloatA [GDI32.@]
3134 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
3135 UINT iLastChar, PFLOAT pxBuffer)
3137 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3141 /*************************************************************************
3142 * GetCharWidthFloatW [GDI32.@]
3144 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
3145 UINT iLastChar, PFLOAT pxBuffer)
3147 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3152 /***********************************************************************
3154 * Font Resource API *
3156 ***********************************************************************/
3158 /***********************************************************************
3159 * AddFontResourceA (GDI32.@)
3161 INT WINAPI AddFontResourceA( LPCSTR str )
3163 return AddFontResourceExA( str, 0, NULL);
3166 /***********************************************************************
3167 * AddFontResourceW (GDI32.@)
3169 INT WINAPI AddFontResourceW( LPCWSTR str )
3171 return AddFontResourceExW(str, 0, NULL);
3175 /***********************************************************************
3176 * AddFontResourceExA (GDI32.@)
3178 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3180 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3181 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3184 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3185 ret = AddFontResourceExW(strW, fl, pdv);
3186 HeapFree(GetProcessHeap(), 0, strW);
3190 /***********************************************************************
3191 * AddFontResourceExW (GDI32.@)
3193 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3195 return WineEngAddFontResourceEx(str, fl, pdv);
3198 /***********************************************************************
3199 * RemoveFontResourceA (GDI32.@)
3201 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3203 return RemoveFontResourceExA(str, 0, 0);
3206 /***********************************************************************
3207 * RemoveFontResourceW (GDI32.@)
3209 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3211 return RemoveFontResourceExW(str, 0, 0);
3214 /***********************************************************************
3215 * AddFontMemResourceEx (GDI32.@)
3217 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3219 FIXME("(%p,%08x,%p,%p): stub\n", pbFont, cbFont, pdv, pcFonts);
3223 /***********************************************************************
3224 * RemoveFontResourceExA (GDI32.@)
3226 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3228 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3229 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3232 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3233 ret = RemoveFontResourceExW(strW, fl, pdv);
3234 HeapFree(GetProcessHeap(), 0, strW);
3238 /***********************************************************************
3239 * RemoveFontResourceExW (GDI32.@)
3241 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3243 return WineEngRemoveFontResourceEx(str, fl, pdv);
3246 /***********************************************************************
3247 * GetTextCharset (GDI32.@)
3249 UINT WINAPI GetTextCharset(HDC hdc)
3251 /* MSDN docs say this is equivalent */
3252 return GetTextCharsetInfo(hdc, NULL, 0);
3255 /***********************************************************************
3256 * GetTextCharsetInfo (GDI32.@)
3258 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3260 UINT ret = DEFAULT_CHARSET;
3261 DC *dc = DC_GetDCPtr(hdc);
3266 ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
3268 GDI_ReleaseObj(hdc);
3271 if (ret == DEFAULT_CHARSET && fs)
3272 memset(fs, 0, sizeof(FONTSIGNATURE));
3276 /***********************************************************************
3277 * GdiGetCharDimensions (GDI32.@)
3279 * Gets the average width of the characters in the English alphabet.
3282 * hdc [I] Handle to the device context to measure on.
3283 * lptm [O] Pointer to memory to store the text metrics into.
3284 * height [O] On exit, the maximum height of characters in the English alphabet.
3287 * The average width of characters in the English alphabet.
3290 * This function is used by the dialog manager to get the size of a dialog
3291 * unit. It should also be used by other pieces of code that need to know
3292 * the size of a dialog unit in logical units without having access to the
3293 * window handle of the dialog.
3294 * Windows caches the font metrics from this function, but we don't and
3295 * there doesn't appear to be an immediate advantage to do so.
3298 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3300 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3303 static const WCHAR alphabet[] = {
3304 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3305 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3306 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3308 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3310 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3312 if (height) *height = sz.cy;
3313 return (sz.cx / 26 + 1) / 2;
3316 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3318 FIXME("(%d): stub\n", fEnableEUDC);
3322 /***********************************************************************
3323 * GetCharWidthI (GDI32.@)
3325 * Retrieve widths of characters.
3328 * hdc [I] Handle to a device context.
3329 * first [I] First glyph in range to query.
3330 * count [I] Number of glyph indices to query.
3331 * glyphs [I] Array of glyphs to query.
3332 * buffer [O] Buffer to receive character widths.
3335 * Only works with TrueType fonts.
3341 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3346 TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3348 if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3351 if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3353 HeapFree(GetProcessHeap(), 0, abc);
3357 for (i = 0; i < count; i++)
3358 buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3360 HeapFree(GetProcessHeap(), 0, abc);
3364 /***********************************************************************
3365 * GetFontUnicodeRanges (GDI32.@)
3367 * Retrieve a list of supported Unicode characters in a font.
3370 * hdc [I] Handle to a device context.
3371 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3374 * Success: Number of bytes written to the buffer pointed to by lpgs.
3378 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3380 return WineEngGetFontUnicodeRanges(hdc, lpgs);