4 * Copyright 1993 Alexandre Julliard
6 * Copyright 2002,2003 Shachar Shemesh
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "wine/port.h"
35 #include "gdi_private.h"
36 #include "wine/unicode.h"
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(font);
41 /* Device -> World size conversion */
43 /* Performs a device to world transformation on the specified width (which
44 * is in integer format).
46 static inline INT INTERNAL_XDSTOWS(DC *dc, INT width)
50 /* Perform operation with floating point */
51 floatWidth = (FLOAT)width * dc->xformVport2World.eM11;
52 /* Round to integers */
53 return GDI_ROUND(floatWidth);
56 /* Performs a device to world transformation on the specified size (which
57 * is in integer format).
59 static inline INT INTERNAL_YDSTOWS(DC *dc, INT height)
63 /* Perform operation with floating point */
64 floatHeight = (FLOAT)height * dc->xformVport2World.eM22;
65 /* Round to integers */
66 return GDI_ROUND(floatHeight);
69 static inline INT INTERNAL_XWSTODS(DC *dc, INT width)
72 pt[0].x = pt[0].y = 0;
75 LPtoDP(dc->hSelf, pt, 2);
76 return pt[1].x - pt[0].x;
79 static inline INT INTERNAL_YWSTODS(DC *dc, INT height)
82 pt[0].x = pt[0].y = 0;
85 LPtoDP(dc->hSelf, pt, 2);
86 return pt[1].y - pt[0].y;
89 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc );
90 static INT FONT_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(ULongToPtr(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, HDC hdc )
591 DC *dc = get_dc_ptr( hdc );
595 if (!GDI_inc_ref_count( handle ))
597 release_dc_ptr( dc );
601 if (dc->hFont != handle || dc->gdiFont == NULL)
603 if(GetDeviceCaps(dc->hSelf, TEXTCAPS) & TC_VA_ABLE)
605 FONTOBJ *font = GDI_GetObjPtr( handle, FONT_MAGIC ); /* to grab the GDI lock (FIXME) */
606 dc->gdiFont = WineEngCreateFontInstance(dc, handle);
607 if (font) GDI_ReleaseObj( handle );
611 if (dc->funcs->pSelectFont) ret = dc->funcs->pSelectFont( dc->physDev, handle, dc->gdiFont );
613 if (ret && dc->gdiFont) dc->gdiFont = 0;
615 if (ret == HGDI_ERROR)
617 GDI_dec_ref_count( handle );
618 ret = 0; /* SelectObject returns 0 on error */
624 GDI_dec_ref_count( ret );
626 release_dc_ptr( dc );
631 /***********************************************************************
634 static INT FONT_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
639 FONT_LogFontWTo16( &font->logfont, &lf16 );
641 if (count > sizeof(LOGFONT16)) count = sizeof(LOGFONT16);
642 memcpy( buffer, &lf16, count );
646 /***********************************************************************
649 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
656 FONT_LogFontWToA( &font->logfont, &lfA );
658 if (count > sizeof(lfA)) count = sizeof(lfA);
659 memcpy( buffer, &lfA, count );
663 /***********************************************************************
666 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
670 return sizeof(LOGFONTW);
671 if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
672 memcpy( buffer, &font->logfont, count );
677 /***********************************************************************
680 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj )
682 WineEngDestroyFontInstance( handle );
683 return GDI_FreeObject( handle, obj );
687 /***********************************************************************
688 * FONT_EnumInstance16
690 * Called by the device driver layer to pass font info
691 * down to the application.
693 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
694 * We have to use other types because of the FONTENUMPROCW definition.
696 static INT CALLBACK FONT_EnumInstance16( const LOGFONTW *plf, const TEXTMETRICW *ptm,
697 DWORD fType, LPARAM lp )
699 fontEnum16 *pfe = (fontEnum16*)lp;
703 if( pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
704 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet )
709 FONT_EnumLogFontExWTo16((const ENUMLOGFONTEXW *)plf, pfe->lpLogFont);
710 FONT_NewTextMetricExWTo16((const NEWTEXTMETRICEXW *)ptm, pfe->lpTextMetric);
711 pfe->dwFlags |= ENUM_CALLED;
712 DC_ReleaseDCPtr( pfe->dc ); /* release the GDI lock */
714 args[6] = SELECTOROF(pfe->segLogFont);
715 args[5] = OFFSETOF(pfe->segLogFont);
716 args[4] = SELECTOROF(pfe->segTextMetric);
717 args[3] = OFFSETOF(pfe->segTextMetric);
719 args[1] = HIWORD(pfe->lpData);
720 args[0] = LOWORD(pfe->lpData);
721 WOWCallback16Ex( (DWORD)pfe->lpEnumFunc, WCB16_PASCAL, sizeof(args), args, &result );
722 ret = LOWORD(result);
724 /* get the lock again and make sure the DC is still valid */
725 dc = DC_GetDCPtr( pfe->hdc );
726 if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
728 if (dc) DC_ReleaseDCPtr( dc );
729 pfe->hdc = 0; /* make sure we don't try to release it later on */
737 /***********************************************************************
740 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
741 * We have to use other types because of the FONTENUMPROCW definition.
743 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
744 DWORD fType, LPARAM lp )
746 fontEnum32 *pfe = (fontEnum32*)lp;
750 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
751 if((pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
752 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
753 (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
755 /* convert font metrics */
756 ENUMLOGFONTEXA logfont;
757 NEWTEXTMETRICEXA tmA;
759 pfe->dwFlags |= ENUM_CALLED;
760 if (!(pfe->dwFlags & ENUM_UNICODE))
762 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
763 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
764 plf = (LOGFONTW *)&logfont.elfLogFont;
765 ptm = (TEXTMETRICW *)&tmA;
767 DC_ReleaseDCPtr( pfe->dc ); /* release the GDI lock */
769 ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
771 /* get the lock again and make sure the DC is still valid */
772 dc = DC_GetDCPtr( pfe->hdc );
773 if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
775 if (dc) DC_ReleaseDCPtr( dc );
776 pfe->hdc = 0; /* make sure we don't try to release it later on */
784 /***********************************************************************
785 * EnumFontFamiliesEx (GDI.613)
787 INT16 WINAPI EnumFontFamiliesEx16( HDC16 hDC, LPLOGFONT16 plf,
788 FONTENUMPROC16 efproc, LPARAM lParam,
793 DC* dc = DC_GetDCPtr( HDC_32(hDC) );
794 NEWTEXTMETRICEX16 tm16;
795 ENUMLOGFONTEX16 lf16;
800 FONT_LogFont16ToW(plf, &lfW);
802 fe16.hdc = HDC_32(hDC);
804 fe16.physDev = dc->physDev;
805 fe16.lpLogFontParam = plf;
806 fe16.lpEnumFunc = efproc;
807 fe16.lpData = lParam;
808 fe16.lpTextMetric = &tm16;
809 fe16.lpLogFont = &lf16;
810 fe16.segTextMetric = MapLS( &tm16 );
811 fe16.segLogFont = MapLS( &lf16 );
814 enum_gdi_fonts = GetDeviceCaps(fe16.hdc, TEXTCAPS) & TC_VA_ABLE;
816 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
823 ret = WineEngEnumFonts( &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
824 fe16.dwFlags &= ~ENUM_CALLED;
825 if (ret && dc->funcs->pEnumDeviceFonts) {
826 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
827 if(fe16.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
831 UnMapLS( fe16.segTextMetric );
832 UnMapLS( fe16.segLogFont );
833 if (fe16.dc) DC_ReleaseDCPtr( fe16.dc );
837 /***********************************************************************
838 * FONT_EnumFontFamiliesEx
840 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf,
841 FONTENUMPROCW efproc,
842 LPARAM lParam, DWORD dwUnicode)
845 DC *dc = DC_GetDCPtr( hDC );
851 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName),
853 fe32.lpLogFontParam = plf;
854 fe32.lpEnumFunc = efproc;
855 fe32.lpData = lParam;
856 fe32.dwFlags = dwUnicode;
859 fe32.physDev = dc->physDev;
861 enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE;
863 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
870 ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
871 fe32.dwFlags &= ~ENUM_CALLED;
872 if (ret && dc->funcs->pEnumDeviceFonts) {
873 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, plf, FONT_EnumInstance, (LPARAM)&fe32 );
874 if(fe32.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
878 if (fe32.dc) DC_ReleaseDCPtr( fe32.dc );
882 /***********************************************************************
883 * EnumFontFamiliesExW (GDI32.@)
885 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
886 FONTENUMPROCW efproc,
887 LPARAM lParam, DWORD dwFlags )
889 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, ENUM_UNICODE );
892 /***********************************************************************
893 * EnumFontFamiliesExA (GDI32.@)
895 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
896 FONTENUMPROCA efproc,
897 LPARAM lParam, DWORD dwFlags)
900 FONT_LogFontAToW( plf, &lfW );
902 return FONT_EnumFontFamiliesEx( hDC, &lfW, (FONTENUMPROCW)efproc, lParam, 0);
905 /***********************************************************************
906 * EnumFontFamilies (GDI.330)
908 INT16 WINAPI EnumFontFamilies16( HDC16 hDC, LPCSTR lpFamily,
909 FONTENUMPROC16 efproc, LPARAM lpData )
913 lf.lfCharSet = DEFAULT_CHARSET;
916 if (!*lpFamily) return 1;
917 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
919 else lf.lfFaceName[0] = '\0';
921 return EnumFontFamiliesEx16( hDC, &lf, efproc, lpData, 0 );
924 /***********************************************************************
925 * EnumFontFamiliesA (GDI32.@)
927 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
928 FONTENUMPROCA efproc, LPARAM lpData )
932 lf.lfCharSet = DEFAULT_CHARSET;
935 if (!*lpFamily) return 1;
936 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
938 else lf.lfFaceName[0] = lf.lfFaceName[1] = '\0';
940 return EnumFontFamiliesExA( hDC, &lf, efproc, lpData, 0 );
943 /***********************************************************************
944 * EnumFontFamiliesW (GDI32.@)
946 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
947 FONTENUMPROCW efproc, LPARAM lpData )
951 lf.lfCharSet = DEFAULT_CHARSET;
954 if (!*lpFamily) return 1;
955 lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
957 else lf.lfFaceName[0] = 0;
959 return EnumFontFamiliesExW( hDC, &lf, efproc, lpData, 0 );
962 /***********************************************************************
965 INT16 WINAPI EnumFonts16( HDC16 hDC, LPCSTR lpName, FONTENUMPROC16 efproc,
968 return EnumFontFamilies16( hDC, lpName, efproc, lpData );
971 /***********************************************************************
972 * EnumFontsA (GDI32.@)
974 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
977 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
980 /***********************************************************************
981 * EnumFontsW (GDI32.@)
983 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
986 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
990 /***********************************************************************
991 * GetTextCharacterExtra (GDI32.@)
993 INT WINAPI GetTextCharacterExtra( HDC hdc )
996 DC *dc = DC_GetDCPtr( hdc );
997 if (!dc) return 0x80000000;
999 DC_ReleaseDCPtr( dc );
1004 /***********************************************************************
1005 * SetTextCharacterExtra (GDI32.@)
1007 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
1010 DC * dc = DC_GetDCPtr( hdc );
1011 if (!dc) return 0x80000000;
1012 if (dc->funcs->pSetTextCharacterExtra)
1013 prev = dc->funcs->pSetTextCharacterExtra( dc->physDev, extra );
1016 prev = dc->charExtra;
1017 dc->charExtra = extra;
1019 DC_ReleaseDCPtr( dc );
1024 /***********************************************************************
1025 * SetTextJustification (GDI32.@)
1027 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
1030 DC * dc = DC_GetDCPtr( hdc );
1031 if (!dc) return FALSE;
1032 if (dc->funcs->pSetTextJustification)
1033 ret = dc->funcs->pSetTextJustification( dc->physDev, extra, breaks );
1036 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
1037 if (!extra) breaks = 0;
1040 dc->breakExtra = extra / breaks;
1041 dc->breakRem = extra - (breaks * dc->breakExtra);
1049 DC_ReleaseDCPtr( dc );
1054 /***********************************************************************
1055 * GetTextFaceA (GDI32.@)
1057 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
1059 INT res = GetTextFaceW(hdc, 0, NULL);
1060 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
1061 GetTextFaceW( hdc, res, nameW );
1065 if (count && !WideCharToMultiByte( CP_ACP, 0, nameW, -1, name, count, NULL, NULL))
1070 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
1071 HeapFree( GetProcessHeap(), 0, nameW );
1075 /***********************************************************************
1076 * GetTextFaceW (GDI32.@)
1078 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
1083 DC * dc = DC_GetDCPtr( hdc );
1087 ret = WineEngGetTextFace(dc->gdiFont, count, name);
1088 else if ((font = (FONTOBJ *) GDI_GetObjPtr( dc->hFont, FONT_MAGIC )))
1092 lstrcpynW( name, font->logfont.lfFaceName, count );
1093 ret = strlenW(name);
1095 else ret = strlenW(font->logfont.lfFaceName) + 1;
1096 GDI_ReleaseObj( dc->hFont );
1098 DC_ReleaseDCPtr( dc );
1103 /***********************************************************************
1104 * GetTextExtentPoint32A (GDI32.@)
1106 * See GetTextExtentPoint32W.
1108 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
1113 LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1116 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
1117 HeapFree( GetProcessHeap(), 0, p );
1120 TRACE("(%p %s %d %p): returning %d x %d\n",
1121 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
1126 /***********************************************************************
1127 * GetTextExtentPoint32W [GDI32.@]
1129 * Computes width/height for a string.
1131 * Computes width and height of the specified string.
1137 BOOL WINAPI GetTextExtentPoint32W(
1138 HDC hdc, /* [in] Handle of device context */
1139 LPCWSTR str, /* [in] Address of text string */
1140 INT count, /* [in] Number of characters in string */
1141 LPSIZE size) /* [out] Address of structure for string size */
1143 return GetTextExtentExPointW(hdc, str, count, 0, NULL, NULL, size);
1146 /***********************************************************************
1147 * GetTextExtentPointI [GDI32.@]
1149 * Computes width and height of the array of glyph indices.
1155 BOOL WINAPI GetTextExtentPointI(
1156 HDC hdc, /* [in] Handle of device context */
1157 const WORD *indices, /* [in] Address of glyph index array */
1158 INT count, /* [in] Number of glyphs in array */
1159 LPSIZE size) /* [out] Address of structure for string size */
1162 DC * dc = DC_GetDCPtr( hdc );
1163 if (!dc) return FALSE;
1166 ret = WineEngGetTextExtentPointI(dc->gdiFont, indices, count, size);
1167 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1168 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1169 size->cx += count * dc->charExtra;
1171 else if(dc->funcs->pGetTextExtentExPoint) {
1172 FIXME("calling GetTextExtentExPoint\n");
1173 ret = dc->funcs->pGetTextExtentExPoint( dc->physDev, (LPCWSTR)indices,
1174 count, 0, NULL, NULL, size );
1177 DC_ReleaseDCPtr( dc );
1179 TRACE("(%p %p %d %p): returning %d x %d\n",
1180 hdc, indices, count, size, size->cx, size->cy );
1185 /***********************************************************************
1186 * GetTextExtentPointA (GDI32.@)
1188 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
1191 TRACE("not bug compatible.\n");
1192 return GetTextExtentPoint32A( hdc, str, count, size );
1195 /***********************************************************************
1196 * GetTextExtentPointW (GDI32.@)
1198 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1201 TRACE("not bug compatible.\n");
1202 return GetTextExtentPoint32W( hdc, str, count, size );
1206 /***********************************************************************
1207 * GetTextExtentExPointA (GDI32.@)
1209 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1210 INT maxExt, LPINT lpnFit,
1211 LPINT alpDx, LPSIZE size )
1219 NULL == (walpDx = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT))))
1222 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1223 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
1226 INT n = lpnFit ? *lpnFit : wlen;
1228 for(i = 0, j = 0; i < n; i++, j++)
1230 alpDx[j] = walpDx[i];
1231 if (IsDBCSLeadByte(str[j])) alpDx[++j] = walpDx[i];
1234 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1235 HeapFree( GetProcessHeap(), 0, p );
1236 HeapFree( GetProcessHeap(), 0, walpDx );
1241 /***********************************************************************
1242 * GetTextExtentExPointW (GDI32.@)
1244 * Return the size of the string as it would be if it was output properly by
1247 * This should include
1248 * - Intercharacter spacing
1249 * - justification spacing (not yet done)
1250 * - kerning? see below
1252 * Kerning. Since kerning would be carried out by the rendering code it should
1253 * be done by the driver. However they don't support it yet. Also I am not
1254 * yet persuaded that (certainly under Win95) any kerning is actually done.
1256 * str: According to MSDN this should be null-terminated. That is not true; a
1257 * null will not terminate it early.
1258 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1259 * than count. I have seen it be either the size of the full string or
1260 * 1 less than the size of the full string. I have not seen it bear any
1261 * resemblance to the portion that would fit.
1262 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1263 * trailing intercharacter spacing and any trailing justification.
1266 * Currently we do this by measuring each character etc. We should do it by
1267 * passing the request to the driver, perhaps by extending the
1268 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1269 * thinking about kerning issues and rounding issues in the justification.
1272 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1273 INT maxExt, LPINT lpnFit,
1274 LPINT alpDx, LPSIZE size )
1282 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1284 dc = DC_GetDCPtr(hdc);
1288 GetTextMetricsW(hdc, &tm);
1290 /* If we need to calculate nFit, then we need the partial extents even if
1291 the user hasn't provided us with an array. */
1294 dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]);
1297 DC_ReleaseDCPtr(dc);
1298 SetLastError(ERROR_OUTOFMEMORY);
1306 ret = WineEngGetTextExtentExPoint(dc->gdiFont, str, count,
1307 0, NULL, dxs, size);
1308 else if (dc->funcs->pGetTextExtentExPoint)
1309 ret = dc->funcs->pGetTextExtentExPoint(dc->physDev, str, count,
1310 0, NULL, dxs, size);
1312 /* Perform device size to world size transformations. */
1315 INT extra = dc->charExtra,
1316 breakExtra = dc->breakExtra,
1317 breakRem = dc->breakRem,
1322 for (i = 0; i < count; ++i)
1324 dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
1325 dxs[i] += (i+1) * extra;
1326 if (count > 1 && (breakExtra || breakRem) && str[i] == tm.tmBreakChar)
1328 dxs[i] += breakExtra;
1335 if (dxs[i] <= maxExt)
1338 breakRem = dc->breakRem;
1340 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1341 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1343 if (!dxs && count > 1 && (breakExtra || breakRem))
1345 for (i = 0; i < count; i++)
1347 if (str[i] == tm.tmBreakChar)
1349 size->cx += breakExtra;
1364 HeapFree(GetProcessHeap(), 0, dxs);
1366 DC_ReleaseDCPtr( dc );
1368 TRACE("returning %d %d x %d\n",nFit,size->cx,size->cy);
1372 /***********************************************************************
1373 * GetTextMetricsA (GDI32.@)
1375 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1379 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1380 FONT_TextMetricWToA( &tm32, metrics );
1384 /***********************************************************************
1385 * GetTextMetricsW (GDI32.@)
1387 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1390 DC * dc = DC_GetDCPtr( hdc );
1391 if (!dc) return FALSE;
1394 ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1395 else if (dc->funcs->pGetTextMetrics)
1396 ret = dc->funcs->pGetTextMetrics( dc->physDev, metrics );
1400 /* device layer returns values in device units
1401 * therefore we have to convert them to logical */
1403 metrics->tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1404 metrics->tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1406 #define WDPTOLP(x) ((x<0)? \
1407 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1408 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1409 #define HDPTOLP(y) ((y<0)? \
1410 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1411 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1413 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1414 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1415 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1416 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1417 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1418 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1419 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1420 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1424 TRACE("text metrics:\n"
1425 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1426 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1427 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1428 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1429 " PitchAndFamily = %02x\n"
1430 " --------------------\n"
1431 " InternalLeading = %i\n"
1435 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1436 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1437 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1438 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1439 metrics->tmPitchAndFamily,
1440 metrics->tmInternalLeading,
1443 metrics->tmHeight );
1445 DC_ReleaseDCPtr( dc );
1450 /***********************************************************************
1451 * GetOutlineTextMetrics [GDI.308] Gets metrics for TrueType fonts.
1454 * lpOTM should be LPOUTLINETEXTMETRIC
1457 * Success: Non-zero or size of required buffer
1460 UINT16 WINAPI GetOutlineTextMetrics16(
1461 HDC16 hdc, /* [in] Handle of device context */
1462 UINT16 cbData, /* [in] Size of metric data array */
1463 LPOUTLINETEXTMETRIC16 lpOTM) /* [out] Address of metric data array */
1465 FIXME("(%04x,%04x,%p): stub\n", hdc,cbData,lpOTM);
1470 /***********************************************************************
1471 * GetOutlineTextMetricsA (GDI32.@)
1472 * Gets metrics for TrueType fonts.
1475 * If the supplied buffer isn't big enough Windows partially fills it up to
1476 * its given length and returns that length.
1479 * Success: Non-zero or size of required buffer
1482 UINT WINAPI GetOutlineTextMetricsA(
1483 HDC hdc, /* [in] Handle of device context */
1484 UINT cbData, /* [in] Size of metric data array */
1485 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1487 char buf[512], *ptr;
1489 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1490 OUTLINETEXTMETRICA *output = lpOTM;
1493 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1495 if(ret > sizeof(buf))
1496 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1497 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1499 needed = sizeof(OUTLINETEXTMETRICA);
1500 if(lpOTMW->otmpFamilyName)
1501 needed += WideCharToMultiByte(CP_ACP, 0,
1502 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1503 NULL, 0, NULL, NULL);
1504 if(lpOTMW->otmpFaceName)
1505 needed += WideCharToMultiByte(CP_ACP, 0,
1506 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1507 NULL, 0, NULL, NULL);
1508 if(lpOTMW->otmpStyleName)
1509 needed += WideCharToMultiByte(CP_ACP, 0,
1510 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1511 NULL, 0, NULL, NULL);
1512 if(lpOTMW->otmpFullName)
1513 needed += WideCharToMultiByte(CP_ACP, 0,
1514 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1515 NULL, 0, NULL, NULL);
1522 TRACE("needed = %d\n", needed);
1524 /* Since the supplied buffer isn't big enough, we'll alloc one
1525 that is and memcpy the first cbData bytes into the lpOTM at
1527 output = HeapAlloc(GetProcessHeap(), 0, needed);
1529 ret = output->otmSize = min(needed, cbData);
1530 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1531 output->otmFiller = 0;
1532 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1533 output->otmfsSelection = lpOTMW->otmfsSelection;
1534 output->otmfsType = lpOTMW->otmfsType;
1535 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1536 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1537 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1538 output->otmEMSquare = lpOTMW->otmEMSquare;
1539 output->otmAscent = lpOTMW->otmAscent;
1540 output->otmDescent = lpOTMW->otmDescent;
1541 output->otmLineGap = lpOTMW->otmLineGap;
1542 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1543 output->otmsXHeight = lpOTMW->otmsXHeight;
1544 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1545 output->otmMacAscent = lpOTMW->otmMacAscent;
1546 output->otmMacDescent = lpOTMW->otmMacDescent;
1547 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1548 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1549 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1550 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1551 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1552 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1553 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1554 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1555 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1556 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1559 ptr = (char*)(output + 1);
1560 left = needed - sizeof(*output);
1562 if(lpOTMW->otmpFamilyName) {
1563 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1564 len = WideCharToMultiByte(CP_ACP, 0,
1565 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1566 ptr, left, NULL, NULL);
1570 output->otmpFamilyName = 0;
1572 if(lpOTMW->otmpFaceName) {
1573 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1574 len = WideCharToMultiByte(CP_ACP, 0,
1575 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1576 ptr, left, NULL, NULL);
1580 output->otmpFaceName = 0;
1582 if(lpOTMW->otmpStyleName) {
1583 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1584 len = WideCharToMultiByte(CP_ACP, 0,
1585 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1586 ptr, left, NULL, NULL);
1590 output->otmpStyleName = 0;
1592 if(lpOTMW->otmpFullName) {
1593 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1594 len = WideCharToMultiByte(CP_ACP, 0,
1595 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1596 ptr, left, NULL, NULL);
1599 output->otmpFullName = 0;
1603 if(output != lpOTM) {
1604 memcpy(lpOTM, output, cbData);
1605 HeapFree(GetProcessHeap(), 0, output);
1607 /* check if the string offsets really fit into the provided size */
1608 /* FIXME: should we check string length as well? */
1609 /* make sure that we don't read/write beyond the provided buffer */
1610 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(LPSTR))
1612 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1613 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1616 /* make sure that we don't read/write beyond the provided buffer */
1617 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(LPSTR))
1619 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1620 lpOTM->otmpFaceName = 0; /* doesn't fit */
1623 /* make sure that we don't read/write beyond the provided buffer */
1624 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(LPSTR))
1626 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1627 lpOTM->otmpStyleName = 0; /* doesn't fit */
1630 /* make sure that we don't read/write beyond the provided buffer */
1631 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(LPSTR))
1633 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1634 lpOTM->otmpFullName = 0; /* doesn't fit */
1639 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1640 HeapFree(GetProcessHeap(), 0, lpOTMW);
1646 /***********************************************************************
1647 * GetOutlineTextMetricsW [GDI32.@]
1649 UINT WINAPI GetOutlineTextMetricsW(
1650 HDC hdc, /* [in] Handle of device context */
1651 UINT cbData, /* [in] Size of metric data array */
1652 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1654 DC *dc = DC_GetDCPtr( hdc );
1655 OUTLINETEXTMETRICW *output = lpOTM;
1658 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1662 ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, output);
1665 output = HeapAlloc(GetProcessHeap(), 0, ret);
1666 WineEngGetOutlineTextMetrics(dc->gdiFont, ret, output);
1669 #define WDPTOLP(x) ((x<0)? \
1670 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1671 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1672 #define HDPTOLP(y) ((y<0)? \
1673 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1674 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1676 output->otmTextMetrics.tmHeight = HDPTOLP(output->otmTextMetrics.tmHeight);
1677 output->otmTextMetrics.tmAscent = HDPTOLP(output->otmTextMetrics.tmAscent);
1678 output->otmTextMetrics.tmDescent = HDPTOLP(output->otmTextMetrics.tmDescent);
1679 output->otmTextMetrics.tmInternalLeading = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1680 output->otmTextMetrics.tmExternalLeading = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1681 output->otmTextMetrics.tmAveCharWidth = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1682 output->otmTextMetrics.tmMaxCharWidth = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1683 output->otmTextMetrics.tmOverhang = WDPTOLP(output->otmTextMetrics.tmOverhang);
1684 output->otmAscent = HDPTOLP(output->otmAscent);
1685 output->otmDescent = HDPTOLP(output->otmDescent);
1686 output->otmLineGap = HDPTOLP(output->otmLineGap);
1687 output->otmsCapEmHeight = HDPTOLP(output->otmsCapEmHeight);
1688 output->otmsXHeight = HDPTOLP(output->otmsXHeight);
1689 output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1690 output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1691 output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1692 output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1693 output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1694 output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1695 output->otmMacLineGap = HDPTOLP(output->otmMacLineGap);
1696 output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1697 output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1698 output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1699 output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1700 output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1701 output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1702 output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1703 output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1704 output->otmsStrikeoutSize = HDPTOLP(output->otmsStrikeoutSize);
1705 output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1706 output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1707 output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1710 if(output != lpOTM) {
1711 memcpy(lpOTM, output, cbData);
1712 HeapFree(GetProcessHeap(), 0, output);
1718 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1719 but really this should just be a return 0. */
1721 ret = sizeof(*lpOTM);
1726 memset(lpOTM, 0, ret);
1727 lpOTM->otmSize = sizeof(*lpOTM);
1728 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1730 Further fill of the structure not implemented,
1731 Needs real values for the structure members
1736 DC_ReleaseDCPtr(dc);
1741 /***********************************************************************
1742 * GetCharWidthW (GDI32.@)
1743 * GetCharWidth32W (GDI32.@)
1745 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1750 DC * dc = DC_GetDCPtr( hdc );
1751 if (!dc) return FALSE;
1754 ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1755 else if (dc->funcs->pGetCharWidth)
1756 ret = dc->funcs->pGetCharWidth( dc->physDev, firstChar, lastChar, buffer);
1760 /* convert device units to logical */
1761 for( i = firstChar; i <= lastChar; i++, buffer++ )
1762 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1765 DC_ReleaseDCPtr( dc );
1770 /***********************************************************************
1771 * GetCharWidthA (GDI32.@)
1772 * GetCharWidth32A (GDI32.@)
1774 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1777 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1782 if(count <= 0) return FALSE;
1784 str = HeapAlloc(GetProcessHeap(), 0, count);
1785 for(i = 0; i < count; i++)
1786 str[i] = (BYTE)(firstChar + i);
1788 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1790 for(i = 0; i < wlen; i++)
1792 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1800 HeapFree(GetProcessHeap(), 0, str);
1801 HeapFree(GetProcessHeap(), 0, wstr);
1807 /***********************************************************************
1808 * ExtTextOutA (GDI32.@)
1812 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1813 const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1821 if (flags & ETO_GLYPH_INDEX)
1822 return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
1824 p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
1827 unsigned int i = 0, j = 0;
1829 lpDxW = HeapAlloc( GetProcessHeap(), 0, wlen*sizeof(INT));
1831 if(IsDBCSLeadByteEx(codepage, str[i])) {
1832 lpDxW[j++] = lpDx[i] + lpDx[i+1];
1835 lpDxW[j++] = lpDx[i];
1841 ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1843 HeapFree( GetProcessHeap(), 0, p );
1844 HeapFree( GetProcessHeap(), 0, lpDxW );
1849 /***********************************************************************
1850 * ExtTextOutW (GDI32.@)
1852 * Draws text using the currently selected font, background color, and text color.
1856 * x,y [I] coordinates of string
1858 * ETO_GRAYED - undocumented on MSDN
1859 * ETO_OPAQUE - use background color for fill the rectangle
1860 * ETO_CLIPPED - clipping text to the rectangle
1861 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1862 * than encoded characters. Implies ETO_IGNORELANGUAGE
1863 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1864 * Affects BiDi ordering
1865 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1866 * ETO_PDY - unimplemented
1867 * ETO_NUMERICSLATIN - unimplemented always assumed -
1868 * do not translate numbers into locale representations
1869 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1870 * lprect [I] dimensions for clipping or/and opaquing
1871 * str [I] text string
1872 * count [I] number of symbols in string
1873 * lpDx [I] optional parameter with distance between drawing characters
1879 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1880 const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1883 LPWSTR reordered_str = (LPWSTR)str;
1884 WORD *glyphs = NULL;
1885 UINT align = GetTextAlign( hdc );
1889 double cosEsc, sinEsc;
1890 INT *deltas = NULL, char_extra;
1893 BOOL done_extents = FALSE;
1894 INT width = 0, xwidth = 0, ywidth = 0;
1896 DC * dc = get_dc_ptr( hdc );
1899 if (!dc) return FALSE;
1901 breakRem = dc->breakRem;
1903 if (flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY))
1904 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY unimplemented\n");
1906 if (!dc->funcs->pExtTextOut && !PATH_IsPathOpen(dc->path))
1908 release_dc_ptr( dc );
1913 type = GetObjectType(hdc);
1914 if(type == OBJ_METADC || type == OBJ_ENHMETADC)
1916 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, flags, lprect, str, count, lpDx);
1917 release_dc_ptr( dc );
1922 flags &= ~ETO_CLIPPED;
1924 if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && count > 0 )
1926 reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1928 BIDI_Reorder( str, count, GCP_REORDER,
1929 ((flags&ETO_RTLREADING)!=0 || (GetTextAlign(hdc)&TA_RTLREADING)!=0)?
1930 WINE_GCPW_FORCE_RTL:WINE_GCPW_FORCE_LTR,
1931 reordered_str, count, NULL );
1933 flags |= ETO_IGNORELANGUAGE;
1936 TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc, x, y, flags,
1937 lprect, debugstr_wn(str, count), count, lpDx);
1939 if(flags & ETO_GLYPH_INDEX)
1940 glyphs = reordered_str;
1943 TRACE("rect: %d,%d - %d,%d\n", lprect->left, lprect->top, lprect->right,
1945 TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
1947 if(align & TA_UPDATECP)
1949 GetCurrentPositionEx( hdc, &pt );
1954 GetTextMetricsW(hdc, &tm);
1955 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1957 if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
1958 lf.lfEscapement = 0;
1960 if(lf.lfEscapement != 0)
1962 cosEsc = cos(lf.lfEscapement * M_PI / 1800);
1963 sinEsc = sin(lf.lfEscapement * M_PI / 1800);
1971 if(flags & (ETO_CLIPPED | ETO_OPAQUE))
1975 if(flags & ETO_GLYPH_INDEX)
1976 GetTextExtentPointI(hdc, glyphs, count, &sz);
1978 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1980 done_extents = TRUE;
1983 rc.right = x + sz.cx;
1984 rc.bottom = y + sz.cy;
1991 LPtoDP(hdc, (POINT*)&rc, 2);
1993 if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
1994 if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
1997 if ((flags & ETO_OPAQUE) && !PATH_IsPathOpen(dc->path))
1998 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
2008 LPtoDP(hdc, &pt, 1);
2012 char_extra = GetTextCharacterExtra(hdc);
2013 if(char_extra || dc->breakExtra || breakRem || lpDx || lf.lfEscapement != 0)
2017 deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT));
2018 for(i = 0; i < count; i++)
2020 if(lpDx && (flags & ETO_PDY))
2021 deltas[i] = lpDx[i*2] + char_extra;
2023 deltas[i] = lpDx[i] + char_extra;
2026 if(flags & ETO_GLYPH_INDEX)
2027 GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
2029 GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
2031 deltas[i] = tmpsz.cx;
2034 if (!(flags & ETO_GLYPH_INDEX) && (dc->breakExtra || breakRem) && reordered_str[i] == tm.tmBreakChar)
2036 deltas[i] = deltas[i] + dc->breakExtra;
2043 deltas[i] = INTERNAL_XWSTODS(dc, deltas[i]);
2051 if(flags & ETO_GLYPH_INDEX)
2052 GetTextExtentPointI(hdc, glyphs, count, &sz);
2054 GetTextExtentPointW(hdc, reordered_str, count, &sz);
2055 done_extents = TRUE;
2057 width = INTERNAL_XWSTODS(dc, sz.cx);
2059 xwidth = width * cosEsc;
2060 ywidth = width * sinEsc;
2062 tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
2063 tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
2064 switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
2067 if (align & TA_UPDATECP)
2071 DPtoLP(hdc, &pt, 1);
2072 MoveToEx(hdc, pt.x, pt.y, NULL);
2084 if (align & TA_UPDATECP)
2088 DPtoLP(hdc, &pt, 1);
2089 MoveToEx(hdc, pt.x, pt.y, NULL);
2094 switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
2097 y += tm.tmAscent * cosEsc;
2098 x += tm.tmAscent * sinEsc;
2102 y -= tm.tmDescent * cosEsc;
2103 x -= tm.tmDescent * sinEsc;
2110 if (GetBkMode(hdc) != TRANSPARENT && !PATH_IsPathOpen(dc->path))
2112 if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
2114 if(!(flags & ETO_OPAQUE) || x < rc.left || x + width >= rc.right ||
2115 y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
2119 rc.right = x + width;
2120 rc.top = y - tm.tmAscent;
2121 rc.bottom = y + tm.tmDescent;
2122 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
2127 if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
2129 HFONT orig_font = dc->hFont, cur_font;
2131 INT span = 0, *offsets = NULL, i;
2133 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2134 for(i = 0; i < count; i++)
2136 WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
2137 if(cur_font != dc->hFont)
2142 offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
2147 for(j = 1; j < count; j++)
2149 GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
2150 offsets[j] = offsets[j-1] + INTERNAL_XWSTODS(dc, tmpsz.cx);
2155 for(j = 1; j < count; j++)
2156 offsets[j] = offsets[j-1] + deltas[j];
2161 if (PATH_IsPathOpen(dc->path))
2162 ret = PATH_ExtTextOut(dc, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
2163 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2164 glyphs, span, deltas ? deltas + i - span : NULL);
2166 dc->funcs->pExtTextOut(dc->physDev, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
2167 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2168 glyphs, span, deltas ? deltas + i - span : NULL);
2171 SelectObject(hdc, cur_font);
2173 glyphs[span++] = glyph;
2177 if (PATH_IsPathOpen(dc->path))
2178 ret = PATH_ExtTextOut(dc, x + (offsets ? offsets[count - span] * cosEsc : 0),
2179 y - (offsets ? offsets[count - span] * sinEsc : 0),
2180 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2181 glyphs, span, deltas ? deltas + count - span : NULL);
2183 ret = dc->funcs->pExtTextOut(dc->physDev, x + (offsets ? offsets[count - span] * cosEsc : 0),
2184 y - (offsets ? offsets[count - span] * sinEsc : 0),
2185 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2186 glyphs, span, deltas ? deltas + count - span : NULL);
2187 SelectObject(hdc, orig_font);
2188 HeapFree(GetProcessHeap(), 0, offsets);
2194 if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
2196 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2197 GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
2198 flags |= ETO_GLYPH_INDEX;
2201 if (PATH_IsPathOpen(dc->path))
2202 ret = PATH_ExtTextOut(dc, x, y, (flags & ~ETO_OPAQUE), &rc,
2203 glyphs ? glyphs : reordered_str, count, deltas);
2205 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, (flags & ~ETO_OPAQUE), &rc,
2206 glyphs ? glyphs : reordered_str, count, deltas);
2210 HeapFree(GetProcessHeap(), 0, deltas);
2211 if(glyphs != reordered_str)
2212 HeapFree(GetProcessHeap(), 0, glyphs);
2213 if(reordered_str != str)
2214 HeapFree(GetProcessHeap(), 0, reordered_str);
2216 release_dc_ptr( dc );
2218 if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2220 int underlinePos, strikeoutPos;
2221 int underlineWidth, strikeoutWidth;
2222 UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2223 OUTLINETEXTMETRICW* otm = NULL;
2228 underlineWidth = tm.tmAscent / 20 + 1;
2229 strikeoutPos = tm.tmAscent / 2;
2230 strikeoutWidth = underlineWidth;
2234 otm = HeapAlloc(GetProcessHeap(), 0, size);
2235 GetOutlineTextMetricsW(hdc, size, otm);
2236 underlinePos = otm->otmsUnderscorePosition;
2237 underlineWidth = otm->otmsUnderscoreSize;
2238 strikeoutPos = otm->otmsStrikeoutPosition;
2239 strikeoutWidth = otm->otmsStrikeoutSize;
2240 HeapFree(GetProcessHeap(), 0, otm);
2243 if (PATH_IsPathOpen(dc->path))
2247 HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2249 hbrush = SelectObject(hdc, hbrush);
2250 hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2254 pts[0].x = x - underlinePos * sinEsc;
2255 pts[0].y = y - underlinePos * cosEsc;
2256 pts[1].x = x + xwidth - underlinePos * sinEsc;
2257 pts[1].y = y - ywidth - underlinePos * cosEsc;
2258 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2259 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2260 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2261 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2262 pts[4].x = pts[0].x;
2263 pts[4].y = pts[0].y;
2264 DPtoLP(hdc, pts, 5);
2265 Polygon(hdc, pts, 5);
2270 pts[0].x = x - strikeoutPos * sinEsc;
2271 pts[0].y = y - strikeoutPos * cosEsc;
2272 pts[1].x = x + xwidth - strikeoutPos * sinEsc;
2273 pts[1].y = y - ywidth - strikeoutPos * cosEsc;
2274 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2275 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2276 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2277 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2278 pts[4].x = pts[0].x;
2279 pts[4].y = pts[0].y;
2280 DPtoLP(hdc, pts, 5);
2281 Polygon(hdc, pts, 5);
2284 SelectObject(hdc, hpen);
2285 hbrush = SelectObject(hdc, hbrush);
2286 DeleteObject(hbrush);
2290 POINT pts[2], oldpt;
2295 hpen = CreatePen(PS_SOLID, underlineWidth, GetTextColor(hdc));
2296 hpen = SelectObject(hdc, hpen);
2299 pts[1].x = x + xwidth;
2300 pts[1].y = y - ywidth;
2301 DPtoLP(hdc, pts, 2);
2302 MoveToEx(hdc, pts[0].x - underlinePos * sinEsc, pts[0].y - underlinePos * cosEsc, &oldpt);
2303 LineTo(hdc, pts[1].x - underlinePos * sinEsc, pts[1].y - underlinePos * cosEsc);
2304 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2305 DeleteObject(SelectObject(hdc, hpen));
2310 hpen = CreatePen(PS_SOLID, strikeoutWidth, GetTextColor(hdc));
2311 hpen = SelectObject(hdc, hpen);
2314 pts[1].x = x + xwidth;
2315 pts[1].y = y - ywidth;
2316 DPtoLP(hdc, pts, 2);
2317 MoveToEx(hdc, pts[0].x - strikeoutPos * sinEsc, pts[0].y - strikeoutPos * cosEsc, &oldpt);
2318 LineTo(hdc, pts[1].x - strikeoutPos * sinEsc, pts[1].y - strikeoutPos * cosEsc);
2319 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2320 DeleteObject(SelectObject(hdc, hpen));
2329 /***********************************************************************
2330 * TextOutA (GDI32.@)
2332 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2334 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2338 /***********************************************************************
2339 * TextOutW (GDI32.@)
2341 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2343 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2347 /***********************************************************************
2348 * PolyTextOutA (GDI32.@)
2352 BOOL WINAPI PolyTextOutA( HDC hdc, const POLYTEXTA *pptxt, INT cStrings )
2354 for (; cStrings>0; cStrings--, pptxt++)
2355 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2362 /***********************************************************************
2363 * PolyTextOutW (GDI32.@)
2365 * Draw several Strings
2371 BOOL WINAPI PolyTextOutW( HDC hdc, const POLYTEXTW *pptxt, INT cStrings )
2373 for (; cStrings>0; cStrings--, pptxt++)
2374 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2380 /* FIXME: all following APIs ******************************************/
2383 /***********************************************************************
2384 * SetMapperFlags (GDI32.@)
2386 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
2388 DC *dc = DC_GetDCPtr( hDC );
2391 if(dc->funcs->pSetMapperFlags)
2393 ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
2394 /* FIXME: ret is just a success flag, we should return a proper value */
2397 FIXME("(%p, 0x%08x): stub - harmless\n", hDC, dwFlag);
2398 DC_ReleaseDCPtr( dc );
2402 /***********************************************************************
2403 * GetAspectRatioFilterEx (GDI.486)
2405 BOOL16 WINAPI GetAspectRatioFilterEx16( HDC16 hdc, LPSIZE16 pAspectRatio )
2407 FIXME("(%04x, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2411 /***********************************************************************
2412 * GetAspectRatioFilterEx (GDI32.@)
2414 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2416 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2421 /***********************************************************************
2422 * GetCharABCWidthsA (GDI32.@)
2424 * See GetCharABCWidthsW.
2426 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2429 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
2434 if(count <= 0) return FALSE;
2436 str = HeapAlloc(GetProcessHeap(), 0, count);
2437 for(i = 0; i < count; i++)
2438 str[i] = (BYTE)(firstChar + i);
2440 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
2442 for(i = 0; i < wlen; i++)
2444 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2452 HeapFree(GetProcessHeap(), 0, str);
2453 HeapFree(GetProcessHeap(), 0, wstr);
2459 /******************************************************************************
2460 * GetCharABCWidthsW [GDI32.@]
2462 * Retrieves widths of characters in range.
2465 * hdc [I] Handle of device context
2466 * firstChar [I] First character in range to query
2467 * lastChar [I] Last character in range to query
2468 * abc [O] Address of character-width structure
2471 * Only works with TrueType fonts
2477 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2480 DC *dc = DC_GetDCPtr(hdc);
2484 if (!dc) return FALSE;
2487 ret = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
2493 /* convert device units to logical */
2494 for( i = firstChar; i <= lastChar; i++, abc++ ) {
2495 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2496 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2497 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2502 DC_ReleaseDCPtr( dc );
2507 /******************************************************************************
2508 * GetCharABCWidthsI [GDI32.@]
2510 * Retrieves widths of characters in range.
2513 * hdc [I] Handle of device context
2514 * firstChar [I] First glyphs in range to query
2515 * count [I] Last glyphs in range to query
2516 * pgi [i] Array of glyphs to query
2517 * abc [O] Address of character-width structure
2520 * Only works with TrueType fonts
2526 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2527 LPWORD pgi, LPABC abc)
2529 DC *dc = DC_GetDCPtr(hdc);
2533 if (!dc) return FALSE;
2536 ret = WineEngGetCharABCWidthsI( dc->gdiFont, firstChar, count, pgi, abc );
2542 /* convert device units to logical */
2543 for( i = 0; i < count; i++, abc++ ) {
2544 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2545 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2546 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2551 DC_ReleaseDCPtr( dc );
2556 /***********************************************************************
2557 * GetGlyphOutlineA (GDI32.@)
2559 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2560 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2561 LPVOID lpBuffer, const MAT2 *lpmat2 )
2567 if(!(fuFormat & GGO_GLYPH_INDEX)) {
2570 if(uChar > 0xff) { /* but, 2 bytes character only */
2572 mbchs[0] = (uChar & 0xff00) >> 8;
2573 mbchs[1] = (uChar & 0xff);
2576 mbchs[0] = (uChar & 0xff);
2578 p = FONT_mbtowc(hdc, mbchs, len, NULL, NULL);
2582 ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
2584 HeapFree(GetProcessHeap(), 0, p);
2588 /***********************************************************************
2589 * GetGlyphOutlineW (GDI32.@)
2591 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2592 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2593 LPVOID lpBuffer, const MAT2 *lpmat2 )
2595 DC *dc = DC_GetDCPtr(hdc);
2598 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2599 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2601 if(!dc) return GDI_ERROR;
2604 ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
2605 cbBuffer, lpBuffer, lpmat2);
2609 DC_ReleaseDCPtr( dc );
2614 /***********************************************************************
2615 * CreateScalableFontResourceA (GDI32.@)
2617 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2618 LPCSTR lpszResourceFile,
2619 LPCSTR lpszFontFile,
2620 LPCSTR lpszCurrentPath )
2624 /* fHidden=1 - only visible for the calling app, read-only, not
2625 * enumbered with EnumFonts/EnumFontFamilies
2626 * lpszCurrentPath can be NULL
2628 FIXME("(%d,%s,%s,%s): stub\n",
2629 fHidden, debugstr_a(lpszResourceFile), debugstr_a(lpszFontFile),
2630 debugstr_a(lpszCurrentPath) );
2632 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2633 if ((f = CreateFileA(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2635 SetLastError(ERROR_FILE_EXISTS);
2638 return FALSE; /* create failed */
2641 /***********************************************************************
2642 * CreateScalableFontResourceW (GDI32.@)
2644 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2645 LPCWSTR lpszResourceFile,
2646 LPCWSTR lpszFontFile,
2647 LPCWSTR lpszCurrentPath )
2649 FIXME("(%d,%p,%p,%p): stub\n",
2650 fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
2651 return FALSE; /* create failed */
2654 /*************************************************************************
2655 * GetKerningPairsA (GDI32.@)
2657 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2658 LPKERNINGPAIR kern_pairA )
2663 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2664 KERNINGPAIR *kern_pairW;
2666 if (!cPairs && kern_pairA)
2668 SetLastError(ERROR_INVALID_PARAMETER);
2672 charset = GetTextCharset(hDC);
2673 if (!TranslateCharsetInfo(ULongToPtr(charset), &csi, TCI_SRCCHARSET))
2675 FIXME("Can't find codepage for charset %d\n", charset);
2678 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2679 * to fail on an invalid character for CP_SYMBOL.
2681 cpi.DefaultChar[0] = 0;
2682 if (csi.ciACP != CP_SYMBOL && !GetCPInfo(csi.ciACP, &cpi))
2684 FIXME("Can't find codepage %u info\n", csi.ciACP);
2687 TRACE("charset %d => codepage %u\n", charset, csi.ciACP);
2689 total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2690 if (!total_kern_pairs) return 0;
2692 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2693 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2695 for (i = 0; i < total_kern_pairs; i++)
2699 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2702 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2705 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2710 if (kern_pairs_copied >= cPairs) break;
2712 kern_pairA->wFirst = (BYTE)first;
2713 kern_pairA->wSecond = (BYTE)second;
2714 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2717 kern_pairs_copied++;
2720 HeapFree(GetProcessHeap(), 0, kern_pairW);
2722 return kern_pairs_copied;
2725 /*************************************************************************
2726 * GetKerningPairsW (GDI32.@)
2728 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2729 LPKERNINGPAIR lpKerningPairs )
2734 TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2736 if (!cPairs && lpKerningPairs)
2738 SetLastError(ERROR_INVALID_PARAMETER);
2742 dc = DC_GetDCPtr(hDC);
2746 ret = WineEngGetKerningPairs(dc->gdiFont, cPairs, lpKerningPairs);
2748 DC_ReleaseDCPtr( dc );
2752 /*************************************************************************
2753 * TranslateCharsetInfo [GDI32.@]
2755 * Fills a CHARSETINFO structure for a character set, code page, or
2756 * font. This allows making the correspondance between different labelings
2757 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2758 * of the same encoding.
2760 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2761 * only one codepage should be set in *lpSrc.
2764 * TRUE on success, FALSE on failure.
2767 BOOL WINAPI TranslateCharsetInfo(
2768 LPDWORD lpSrc, /* [in]
2769 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2770 if flags == TCI_SRCCHARSET: a character set value
2771 if flags == TCI_SRCCODEPAGE: a code page value
2773 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2774 DWORD flags /* [in] determines interpretation of lpSrc */)
2778 case TCI_SRCFONTSIG:
2779 while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
2781 case TCI_SRCCODEPAGE:
2782 while (PtrToUlong(lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
2784 case TCI_SRCCHARSET:
2785 while (PtrToUlong(lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
2790 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2791 memcpy(lpCs, &FONT_tci[index], sizeof(CHARSETINFO));
2795 /*************************************************************************
2796 * GetFontLanguageInfo (GDI32.@)
2798 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2800 FONTSIGNATURE fontsig;
2801 static const DWORD GCP_DBCS_MASK=0x003F0000,
2802 GCP_DIACRITIC_MASK=0x00000000,
2803 FLI_GLYPHS_MASK=0x00000000,
2804 GCP_GLYPHSHAPE_MASK=0x00000040,
2805 GCP_KASHIDA_MASK=0x00000000,
2806 GCP_LIGATE_MASK=0x00000000,
2807 GCP_USEKERNING_MASK=0x00000000,
2808 GCP_REORDER_MASK=0x00000060;
2812 GetTextCharsetInfo( hdc, &fontsig, 0 );
2813 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2815 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2818 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2819 result|=GCP_DIACRITIC;
2821 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2824 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2825 result|=GCP_GLYPHSHAPE;
2827 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2828 result|=GCP_KASHIDA;
2830 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2833 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2834 result|=GCP_USEKERNING;
2836 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2837 if( GetTextAlign( hdc) & TA_RTLREADING )
2838 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2839 result|=GCP_REORDER;
2845 /*************************************************************************
2846 * GetFontData [GDI32.@]
2848 * Retrieve data for TrueType font.
2852 * success: Number of bytes returned
2853 * failure: GDI_ERROR
2857 * Calls SetLastError()
2860 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2861 LPVOID buffer, DWORD length)
2863 DC *dc = DC_GetDCPtr(hdc);
2864 DWORD ret = GDI_ERROR;
2866 if(!dc) return GDI_ERROR;
2869 ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2871 DC_ReleaseDCPtr( dc );
2875 /*************************************************************************
2876 * GetGlyphIndicesA [GDI32.@]
2878 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2879 LPWORD pgi, DWORD flags)
2885 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2886 hdc, debugstr_an(lpstr, count), count, pgi, flags);
2888 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2889 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2890 HeapFree(GetProcessHeap(), 0, lpstrW);
2895 /*************************************************************************
2896 * GetGlyphIndicesW [GDI32.@]
2898 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2899 LPWORD pgi, DWORD flags)
2901 DC *dc = DC_GetDCPtr(hdc);
2902 DWORD ret = GDI_ERROR;
2904 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2905 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2907 if(!dc) return GDI_ERROR;
2910 ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2912 DC_ReleaseDCPtr( dc );
2916 /*************************************************************************
2917 * GetCharacterPlacementA [GDI32.@]
2919 * See GetCharacterPlacementW.
2922 * the web browser control of ie4 calls this with dwFlags=0
2925 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2926 INT nMaxExtent, GCP_RESULTSA *lpResults,
2931 GCP_RESULTSW resultsW;
2935 TRACE("%s, %d, %d, 0x%08x\n",
2936 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2938 /* both structs are equal in size */
2939 memcpy(&resultsW, lpResults, sizeof(resultsW));
2941 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2942 if(lpResults->lpOutString)
2943 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2945 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2947 lpResults->nGlyphs = resultsW.nGlyphs;
2948 lpResults->nMaxFit = resultsW.nMaxFit;
2950 if(lpResults->lpOutString) {
2951 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2952 lpResults->lpOutString, uCount, NULL, NULL );
2955 HeapFree(GetProcessHeap(), 0, lpStringW);
2956 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2961 /*************************************************************************
2962 * GetCharacterPlacementW [GDI32.@]
2964 * Retrieve information about a string. This includes the width, reordering,
2965 * Glyphing and so on.
2969 * The width and height of the string if successful, 0 if failed.
2973 * All flags except GCP_REORDER are not yet implemented.
2974 * Reordering is not 100% complient to the Windows BiDi method.
2975 * Caret positioning is not yet implemented for BiDi.
2976 * Classes are not yet implemented.
2980 GetCharacterPlacementW(
2981 HDC hdc, /* [in] Device context for which the rendering is to be done */
2982 LPCWSTR lpString, /* [in] The string for which information is to be returned */
2983 INT uCount, /* [in] Number of WORDS in string. */
2984 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
2985 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2986 DWORD dwFlags /* [in] Flags specifying how to process the string */
2993 TRACE("%s, %d, %d, 0x%08x\n",
2994 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2996 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2997 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2998 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2999 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
3000 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
3002 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08x ignored\n", dwFlags);
3003 if(lpResults->lpClass) FIXME("classes not implemented\n");
3004 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
3005 FIXME("Caret positions for complex scripts not implemented\n");
3007 nSet = (UINT)uCount;
3008 if(nSet > lpResults->nGlyphs)
3009 nSet = lpResults->nGlyphs;
3011 /* return number of initialized fields */
3012 lpResults->nGlyphs = nSet;
3014 if((dwFlags&GCP_REORDER)==0 )
3016 /* Treat the case where no special handling was requested in a fastpath way */
3017 /* copy will do if the GCP_REORDER flag is not set */
3018 if(lpResults->lpOutString)
3019 memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
3021 if(lpResults->lpOrder)
3023 for(i = 0; i < nSet; i++)
3024 lpResults->lpOrder[i] = i;
3028 BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
3029 nSet, lpResults->lpOrder );
3032 /* FIXME: Will use the placement chars */
3033 if (lpResults->lpDx)
3036 for (i = 0; i < nSet; i++)
3038 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
3039 lpResults->lpDx[i]= c;
3043 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
3047 lpResults->lpCaretPos[0] = 0;
3048 for (i = 1; i < nSet; i++)
3049 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
3050 lpResults->lpCaretPos[i] = (pos += size.cx);
3053 if(lpResults->lpGlyphs)
3054 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
3056 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
3057 ret = MAKELONG(size.cx, size.cy);
3062 /*************************************************************************
3063 * GetCharABCWidthsFloatA [GDI32.@]
3065 * See GetCharABCWidthsFloatW.
3067 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3069 INT i, wlen, count = (INT)(last - first + 1);
3074 if (count <= 0) return FALSE;
3076 str = HeapAlloc(GetProcessHeap(), 0, count);
3078 for(i = 0; i < count; i++)
3079 str[i] = (BYTE)(first + i);
3081 wstr = FONT_mbtowc( hdc, str, count, &wlen, NULL );
3083 for (i = 0; i < wlen; i++)
3085 if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
3093 HeapFree( GetProcessHeap(), 0, str );
3094 HeapFree( GetProcessHeap(), 0, wstr );
3099 /*************************************************************************
3100 * GetCharABCWidthsFloatW [GDI32.@]
3102 * Retrieves widths of a range of characters.
3105 * hdc [I] Handle to device context.
3106 * first [I] First character in range to query.
3107 * last [I] Last character in range to query.
3108 * abcf [O] Array of LPABCFLOAT structures.
3115 * Only works with TrueType fonts. It also doesn't return real
3116 * floats but converted integers because it's implemented on
3117 * top of GetCharABCWidthsW.
3119 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3122 unsigned int i, size = sizeof(ABC) * (last - first + 1);
3125 TRACE("%p, %d, %d, %p - partial stub\n", hdc, first, last, abcf);
3127 abc = HeapAlloc( GetProcessHeap(), 0, size );
3128 if (!abc) return FALSE;
3130 ret = GetCharABCWidthsW( hdc, first, last, abc );
3133 for (i = first; i <= last; i++, abc++, abcf++)
3135 abcf->abcfA = abc->abcA;
3136 abcf->abcfB = abc->abcB;
3137 abcf->abcfC = abc->abcC;
3140 HeapFree( GetProcessHeap(), 0, abc );
3144 /*************************************************************************
3145 * GetCharWidthFloatA [GDI32.@]
3147 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
3148 UINT iLastChar, PFLOAT pxBuffer)
3150 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3154 /*************************************************************************
3155 * GetCharWidthFloatW [GDI32.@]
3157 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
3158 UINT iLastChar, PFLOAT pxBuffer)
3160 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3165 /***********************************************************************
3167 * Font Resource API *
3169 ***********************************************************************/
3171 /***********************************************************************
3172 * AddFontResourceA (GDI32.@)
3174 INT WINAPI AddFontResourceA( LPCSTR str )
3176 return AddFontResourceExA( str, 0, NULL);
3179 /***********************************************************************
3180 * AddFontResourceW (GDI32.@)
3182 INT WINAPI AddFontResourceW( LPCWSTR str )
3184 return AddFontResourceExW(str, 0, NULL);
3188 /***********************************************************************
3189 * AddFontResourceExA (GDI32.@)
3191 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3193 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3194 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3197 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3198 ret = AddFontResourceExW(strW, fl, pdv);
3199 HeapFree(GetProcessHeap(), 0, strW);
3203 static BOOL CALLBACK load_enumed_resource(HMODULE hModule, LPCWSTR type, LPWSTR name, LONG_PTR lParam)
3205 HRSRC rsrc = FindResourceW(hModule, name, type);
3206 HGLOBAL hMem = LoadResource(hModule, rsrc);
3207 LPVOID *pMem = LockResource(hMem);
3208 int *num_total = (int *)lParam;
3211 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type));
3212 if (!AddFontMemResourceEx(pMem, SizeofResource(hModule, rsrc), NULL, &num_in_res))
3214 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule, hMem);
3218 *num_total += num_in_res;
3222 /***********************************************************************
3223 * AddFontResourceExW (GDI32.@)
3225 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3227 int ret = WineEngAddFontResourceEx(str, fl, pdv);
3230 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3231 HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
3232 if (hModule != NULL)
3234 int num_resources = 0;
3235 LPWSTR rt_font = (LPWSTR)((ULONG_PTR)8); /* we don't want to include winuser.h */
3237 TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3238 wine_dbgstr_w(str));
3239 if (EnumResourceNamesW(hModule, rt_font, load_enumed_resource, (LONG_PTR)&num_resources))
3240 ret = num_resources;
3241 FreeLibrary(hModule);
3247 /***********************************************************************
3248 * RemoveFontResourceA (GDI32.@)
3250 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3252 return RemoveFontResourceExA(str, 0, 0);
3255 /***********************************************************************
3256 * RemoveFontResourceW (GDI32.@)
3258 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3260 return RemoveFontResourceExW(str, 0, 0);
3263 /***********************************************************************
3264 * AddFontMemResourceEx (GDI32.@)
3266 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3268 return WineEngAddFontMemResourceEx(pbFont, cbFont, pdv, pcFonts);
3271 /***********************************************************************
3272 * RemoveFontResourceExA (GDI32.@)
3274 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3276 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3277 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3280 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3281 ret = RemoveFontResourceExW(strW, fl, pdv);
3282 HeapFree(GetProcessHeap(), 0, strW);
3286 /***********************************************************************
3287 * RemoveFontResourceExW (GDI32.@)
3289 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3291 return WineEngRemoveFontResourceEx(str, fl, pdv);
3294 /***********************************************************************
3295 * GetTextCharset (GDI32.@)
3297 UINT WINAPI GetTextCharset(HDC hdc)
3299 /* MSDN docs say this is equivalent */
3300 return GetTextCharsetInfo(hdc, NULL, 0);
3303 /***********************************************************************
3304 * GetTextCharsetInfo (GDI32.@)
3306 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3308 UINT ret = DEFAULT_CHARSET;
3309 DC *dc = DC_GetDCPtr(hdc);
3314 ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
3316 DC_ReleaseDCPtr( dc );
3319 if (ret == DEFAULT_CHARSET && fs)
3320 memset(fs, 0, sizeof(FONTSIGNATURE));
3324 /***********************************************************************
3325 * GdiGetCharDimensions (GDI32.@)
3327 * Gets the average width of the characters in the English alphabet.
3330 * hdc [I] Handle to the device context to measure on.
3331 * lptm [O] Pointer to memory to store the text metrics into.
3332 * height [O] On exit, the maximum height of characters in the English alphabet.
3335 * The average width of characters in the English alphabet.
3338 * This function is used by the dialog manager to get the size of a dialog
3339 * unit. It should also be used by other pieces of code that need to know
3340 * the size of a dialog unit in logical units without having access to the
3341 * window handle of the dialog.
3342 * Windows caches the font metrics from this function, but we don't and
3343 * there doesn't appear to be an immediate advantage to do so.
3346 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3348 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3351 static const WCHAR alphabet[] = {
3352 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3353 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3354 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3356 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3358 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3360 if (height) *height = sz.cy;
3361 return (sz.cx / 26 + 1) / 2;
3364 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3366 FIXME("(%d): stub\n", fEnableEUDC);
3370 /***********************************************************************
3371 * GetCharWidthI (GDI32.@)
3373 * Retrieve widths of characters.
3376 * hdc [I] Handle to a device context.
3377 * first [I] First glyph in range to query.
3378 * count [I] Number of glyph indices to query.
3379 * glyphs [I] Array of glyphs to query.
3380 * buffer [O] Buffer to receive character widths.
3383 * Only works with TrueType fonts.
3389 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3394 TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3396 if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3399 if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3401 HeapFree(GetProcessHeap(), 0, abc);
3405 for (i = 0; i < count; i++)
3406 buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3408 HeapFree(GetProcessHeap(), 0, abc);
3412 /***********************************************************************
3413 * GetFontUnicodeRanges (GDI32.@)
3415 * Retrieve a list of supported Unicode characters in a font.
3418 * hdc [I] Handle to a device context.
3419 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3422 * Success: Number of bytes written to the buffer pointed to by lpgs.
3426 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3429 DC *dc = DC_GetDCPtr(hdc);
3431 TRACE("(%p, %p)\n", hdc, lpgs);
3435 if (dc->gdiFont) ret = WineEngGetFontUnicodeRanges(dc->gdiFont, lpgs);
3436 DC_ReleaseDCPtr(dc);
3441 /*************************************************************
3442 * FontIsLinked (GDI32.@)
3444 BOOL WINAPI FontIsLinked(HDC hdc)
3446 DC *dc = DC_GetDCPtr(hdc);
3449 if (!dc) return FALSE;
3450 if (dc->gdiFont) ret = WineEngFontIsLinked(dc->gdiFont);
3451 DC_ReleaseDCPtr(dc);
3452 TRACE("returning %d\n", ret);