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 * GetTextExtentExPointI [GDI32.@]
1149 * Computes width and height of the array of glyph indices.
1152 * hdc [I] Handle of device context.
1153 * indices [I] Glyph index array.
1154 * count [I] Number of glyphs in array.
1155 * max_ext [I] Maximum width in glyphs.
1156 * nfit [O] Maximum number of characters.
1157 * dxs [O] Partial string widths.
1158 * size [O] Returned string size.
1164 BOOL WINAPI GetTextExtentExPointI( HDC hdc, const WORD *indices, INT count, INT max_ext,
1165 LPINT nfit, LPINT dxs, LPSIZE size )
1168 DC * dc = DC_GetDCPtr( hdc );
1169 if (!dc) return FALSE;
1172 ret = WineEngGetTextExtentExPointI(dc->gdiFont, indices, count, max_ext, nfit, dxs, size);
1173 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1174 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1175 size->cx += count * dc->charExtra;
1177 else if(dc->funcs->pGetTextExtentExPoint) {
1178 FIXME("calling GetTextExtentExPoint\n");
1179 ret = dc->funcs->pGetTextExtentExPoint( dc->physDev, (LPCWSTR)indices,
1180 count, max_ext, nfit, dxs, size );
1183 DC_ReleaseDCPtr( dc );
1185 TRACE("(%p %p %d %p): returning %d x %d\n",
1186 hdc, indices, count, size, size->cx, size->cy );
1190 /***********************************************************************
1191 * GetTextExtentPointI [GDI32.@]
1193 * Computes width and height of the array of glyph indices.
1196 * hdc [I] Handle of device context.
1197 * indices [I] Glyph index array.
1198 * count [I] Number of glyphs in array.
1199 * size [O] Returned string size.
1205 BOOL WINAPI GetTextExtentPointI( HDC hdc, const WORD *indices, INT count, LPSIZE size )
1207 return GetTextExtentExPointI( hdc, indices, count, 0, NULL, NULL, size );
1211 /***********************************************************************
1212 * GetTextExtentPointA (GDI32.@)
1214 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
1217 TRACE("not bug compatible.\n");
1218 return GetTextExtentPoint32A( hdc, str, count, size );
1221 /***********************************************************************
1222 * GetTextExtentPointW (GDI32.@)
1224 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1227 TRACE("not bug compatible.\n");
1228 return GetTextExtentPoint32W( hdc, str, count, size );
1232 /***********************************************************************
1233 * GetTextExtentExPointA (GDI32.@)
1235 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1236 INT maxExt, LPINT lpnFit,
1237 LPINT alpDx, LPSIZE size )
1245 NULL == (walpDx = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT))))
1248 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1249 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
1252 INT n = lpnFit ? *lpnFit : wlen;
1254 for(i = 0, j = 0; i < n; i++, j++)
1256 alpDx[j] = walpDx[i];
1257 if (IsDBCSLeadByte(str[j])) alpDx[++j] = walpDx[i];
1260 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1261 HeapFree( GetProcessHeap(), 0, p );
1262 HeapFree( GetProcessHeap(), 0, walpDx );
1267 /***********************************************************************
1268 * GetTextExtentExPointW (GDI32.@)
1270 * Return the size of the string as it would be if it was output properly by
1273 * This should include
1274 * - Intercharacter spacing
1275 * - justification spacing (not yet done)
1276 * - kerning? see below
1278 * Kerning. Since kerning would be carried out by the rendering code it should
1279 * be done by the driver. However they don't support it yet. Also I am not
1280 * yet persuaded that (certainly under Win95) any kerning is actually done.
1282 * str: According to MSDN this should be null-terminated. That is not true; a
1283 * null will not terminate it early.
1284 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1285 * than count. I have seen it be either the size of the full string or
1286 * 1 less than the size of the full string. I have not seen it bear any
1287 * resemblance to the portion that would fit.
1288 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1289 * trailing intercharacter spacing and any trailing justification.
1292 * Currently we do this by measuring each character etc. We should do it by
1293 * passing the request to the driver, perhaps by extending the
1294 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1295 * thinking about kerning issues and rounding issues in the justification.
1298 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1299 INT maxExt, LPINT lpnFit,
1300 LPINT alpDx, LPSIZE size )
1308 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1310 dc = DC_GetDCPtr(hdc);
1314 GetTextMetricsW(hdc, &tm);
1316 /* If we need to calculate nFit, then we need the partial extents even if
1317 the user hasn't provided us with an array. */
1320 dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]);
1323 DC_ReleaseDCPtr(dc);
1324 SetLastError(ERROR_OUTOFMEMORY);
1332 ret = WineEngGetTextExtentExPoint(dc->gdiFont, str, count,
1333 0, NULL, dxs, size);
1334 else if (dc->funcs->pGetTextExtentExPoint)
1335 ret = dc->funcs->pGetTextExtentExPoint(dc->physDev, str, count,
1336 0, NULL, dxs, size);
1338 /* Perform device size to world size transformations. */
1341 INT extra = dc->charExtra,
1342 breakExtra = dc->breakExtra,
1343 breakRem = dc->breakRem,
1348 for (i = 0; i < count; ++i)
1350 dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
1351 dxs[i] += (i+1) * extra;
1352 if (count > 1 && (breakExtra || breakRem) && str[i] == tm.tmBreakChar)
1354 dxs[i] += breakExtra;
1361 if (dxs[i] <= maxExt)
1364 breakRem = dc->breakRem;
1366 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1367 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1369 if (!dxs && count > 1 && (breakExtra || breakRem))
1371 for (i = 0; i < count; i++)
1373 if (str[i] == tm.tmBreakChar)
1375 size->cx += breakExtra;
1390 HeapFree(GetProcessHeap(), 0, dxs);
1392 DC_ReleaseDCPtr( dc );
1394 TRACE("returning %d %d x %d\n",nFit,size->cx,size->cy);
1398 /***********************************************************************
1399 * GetTextMetricsA (GDI32.@)
1401 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1405 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1406 FONT_TextMetricWToA( &tm32, metrics );
1410 /***********************************************************************
1411 * GetTextMetricsW (GDI32.@)
1413 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1416 DC * dc = DC_GetDCPtr( hdc );
1417 if (!dc) return FALSE;
1420 ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1421 else if (dc->funcs->pGetTextMetrics)
1422 ret = dc->funcs->pGetTextMetrics( dc->physDev, metrics );
1426 /* device layer returns values in device units
1427 * therefore we have to convert them to logical */
1429 metrics->tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1430 metrics->tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1432 #define WDPTOLP(x) ((x<0)? \
1433 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1434 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1435 #define HDPTOLP(y) ((y<0)? \
1436 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1437 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1439 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1440 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1441 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1442 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1443 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1444 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1445 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1446 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1450 TRACE("text metrics:\n"
1451 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1452 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1453 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1454 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1455 " PitchAndFamily = %02x\n"
1456 " --------------------\n"
1457 " InternalLeading = %i\n"
1461 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1462 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1463 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1464 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1465 metrics->tmPitchAndFamily,
1466 metrics->tmInternalLeading,
1469 metrics->tmHeight );
1471 DC_ReleaseDCPtr( dc );
1476 /***********************************************************************
1477 * GetOutlineTextMetrics [GDI.308] Gets metrics for TrueType fonts.
1480 * lpOTM should be LPOUTLINETEXTMETRIC
1483 * Success: Non-zero or size of required buffer
1486 UINT16 WINAPI GetOutlineTextMetrics16(
1487 HDC16 hdc, /* [in] Handle of device context */
1488 UINT16 cbData, /* [in] Size of metric data array */
1489 LPOUTLINETEXTMETRIC16 lpOTM) /* [out] Address of metric data array */
1491 FIXME("(%04x,%04x,%p): stub\n", hdc,cbData,lpOTM);
1496 /***********************************************************************
1497 * GetOutlineTextMetricsA (GDI32.@)
1498 * Gets metrics for TrueType fonts.
1501 * If the supplied buffer isn't big enough Windows partially fills it up to
1502 * its given length and returns that length.
1505 * Success: Non-zero or size of required buffer
1508 UINT WINAPI GetOutlineTextMetricsA(
1509 HDC hdc, /* [in] Handle of device context */
1510 UINT cbData, /* [in] Size of metric data array */
1511 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1513 char buf[512], *ptr;
1515 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1516 OUTLINETEXTMETRICA *output = lpOTM;
1519 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1521 if(ret > sizeof(buf))
1522 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1523 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1525 needed = sizeof(OUTLINETEXTMETRICA);
1526 if(lpOTMW->otmpFamilyName)
1527 needed += WideCharToMultiByte(CP_ACP, 0,
1528 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1529 NULL, 0, NULL, NULL);
1530 if(lpOTMW->otmpFaceName)
1531 needed += WideCharToMultiByte(CP_ACP, 0,
1532 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1533 NULL, 0, NULL, NULL);
1534 if(lpOTMW->otmpStyleName)
1535 needed += WideCharToMultiByte(CP_ACP, 0,
1536 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1537 NULL, 0, NULL, NULL);
1538 if(lpOTMW->otmpFullName)
1539 needed += WideCharToMultiByte(CP_ACP, 0,
1540 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1541 NULL, 0, NULL, NULL);
1548 TRACE("needed = %d\n", needed);
1550 /* Since the supplied buffer isn't big enough, we'll alloc one
1551 that is and memcpy the first cbData bytes into the lpOTM at
1553 output = HeapAlloc(GetProcessHeap(), 0, needed);
1555 ret = output->otmSize = min(needed, cbData);
1556 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1557 output->otmFiller = 0;
1558 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1559 output->otmfsSelection = lpOTMW->otmfsSelection;
1560 output->otmfsType = lpOTMW->otmfsType;
1561 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1562 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1563 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1564 output->otmEMSquare = lpOTMW->otmEMSquare;
1565 output->otmAscent = lpOTMW->otmAscent;
1566 output->otmDescent = lpOTMW->otmDescent;
1567 output->otmLineGap = lpOTMW->otmLineGap;
1568 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1569 output->otmsXHeight = lpOTMW->otmsXHeight;
1570 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1571 output->otmMacAscent = lpOTMW->otmMacAscent;
1572 output->otmMacDescent = lpOTMW->otmMacDescent;
1573 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1574 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1575 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1576 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1577 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1578 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1579 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1580 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1581 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1582 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1585 ptr = (char*)(output + 1);
1586 left = needed - sizeof(*output);
1588 if(lpOTMW->otmpFamilyName) {
1589 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1590 len = WideCharToMultiByte(CP_ACP, 0,
1591 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1592 ptr, left, NULL, NULL);
1596 output->otmpFamilyName = 0;
1598 if(lpOTMW->otmpFaceName) {
1599 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1600 len = WideCharToMultiByte(CP_ACP, 0,
1601 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1602 ptr, left, NULL, NULL);
1606 output->otmpFaceName = 0;
1608 if(lpOTMW->otmpStyleName) {
1609 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1610 len = WideCharToMultiByte(CP_ACP, 0,
1611 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1612 ptr, left, NULL, NULL);
1616 output->otmpStyleName = 0;
1618 if(lpOTMW->otmpFullName) {
1619 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1620 len = WideCharToMultiByte(CP_ACP, 0,
1621 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1622 ptr, left, NULL, NULL);
1625 output->otmpFullName = 0;
1629 if(output != lpOTM) {
1630 memcpy(lpOTM, output, cbData);
1631 HeapFree(GetProcessHeap(), 0, output);
1633 /* check if the string offsets really fit into the provided size */
1634 /* FIXME: should we check string length as well? */
1635 /* make sure that we don't read/write beyond the provided buffer */
1636 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(LPSTR))
1638 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1639 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1642 /* make sure that we don't read/write beyond the provided buffer */
1643 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(LPSTR))
1645 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1646 lpOTM->otmpFaceName = 0; /* doesn't fit */
1649 /* make sure that we don't read/write beyond the provided buffer */
1650 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(LPSTR))
1652 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1653 lpOTM->otmpStyleName = 0; /* doesn't fit */
1656 /* make sure that we don't read/write beyond the provided buffer */
1657 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(LPSTR))
1659 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1660 lpOTM->otmpFullName = 0; /* doesn't fit */
1665 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1666 HeapFree(GetProcessHeap(), 0, lpOTMW);
1672 /***********************************************************************
1673 * GetOutlineTextMetricsW [GDI32.@]
1675 UINT WINAPI GetOutlineTextMetricsW(
1676 HDC hdc, /* [in] Handle of device context */
1677 UINT cbData, /* [in] Size of metric data array */
1678 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1680 DC *dc = DC_GetDCPtr( hdc );
1681 OUTLINETEXTMETRICW *output = lpOTM;
1684 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1688 ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, output);
1691 output = HeapAlloc(GetProcessHeap(), 0, ret);
1692 WineEngGetOutlineTextMetrics(dc->gdiFont, ret, output);
1695 #define WDPTOLP(x) ((x<0)? \
1696 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1697 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1698 #define HDPTOLP(y) ((y<0)? \
1699 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1700 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1702 output->otmTextMetrics.tmHeight = HDPTOLP(output->otmTextMetrics.tmHeight);
1703 output->otmTextMetrics.tmAscent = HDPTOLP(output->otmTextMetrics.tmAscent);
1704 output->otmTextMetrics.tmDescent = HDPTOLP(output->otmTextMetrics.tmDescent);
1705 output->otmTextMetrics.tmInternalLeading = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1706 output->otmTextMetrics.tmExternalLeading = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1707 output->otmTextMetrics.tmAveCharWidth = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1708 output->otmTextMetrics.tmMaxCharWidth = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1709 output->otmTextMetrics.tmOverhang = WDPTOLP(output->otmTextMetrics.tmOverhang);
1710 output->otmAscent = HDPTOLP(output->otmAscent);
1711 output->otmDescent = HDPTOLP(output->otmDescent);
1712 output->otmLineGap = HDPTOLP(output->otmLineGap);
1713 output->otmsCapEmHeight = HDPTOLP(output->otmsCapEmHeight);
1714 output->otmsXHeight = HDPTOLP(output->otmsXHeight);
1715 output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1716 output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1717 output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1718 output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1719 output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1720 output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1721 output->otmMacLineGap = HDPTOLP(output->otmMacLineGap);
1722 output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1723 output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1724 output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1725 output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1726 output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1727 output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1728 output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1729 output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1730 output->otmsStrikeoutSize = HDPTOLP(output->otmsStrikeoutSize);
1731 output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1732 output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1733 output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1736 if(output != lpOTM) {
1737 memcpy(lpOTM, output, cbData);
1738 HeapFree(GetProcessHeap(), 0, output);
1744 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1745 but really this should just be a return 0. */
1747 ret = sizeof(*lpOTM);
1752 memset(lpOTM, 0, ret);
1753 lpOTM->otmSize = sizeof(*lpOTM);
1754 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1756 Further fill of the structure not implemented,
1757 Needs real values for the structure members
1762 DC_ReleaseDCPtr(dc);
1767 /***********************************************************************
1768 * GetCharWidthW (GDI32.@)
1769 * GetCharWidth32W (GDI32.@)
1771 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1776 DC * dc = DC_GetDCPtr( hdc );
1777 if (!dc) return FALSE;
1780 ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1781 else if (dc->funcs->pGetCharWidth)
1782 ret = dc->funcs->pGetCharWidth( dc->physDev, firstChar, lastChar, buffer);
1786 /* convert device units to logical */
1787 for( i = firstChar; i <= lastChar; i++, buffer++ )
1788 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1791 DC_ReleaseDCPtr( dc );
1796 /***********************************************************************
1797 * GetCharWidthA (GDI32.@)
1798 * GetCharWidth32A (GDI32.@)
1800 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1803 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1808 if(count <= 0) return FALSE;
1810 str = HeapAlloc(GetProcessHeap(), 0, count);
1811 for(i = 0; i < count; i++)
1812 str[i] = (BYTE)(firstChar + i);
1814 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1816 for(i = 0; i < wlen; i++)
1818 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1826 HeapFree(GetProcessHeap(), 0, str);
1827 HeapFree(GetProcessHeap(), 0, wstr);
1833 /***********************************************************************
1834 * ExtTextOutA (GDI32.@)
1838 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1839 const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1847 if (flags & ETO_GLYPH_INDEX)
1848 return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
1850 p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
1853 unsigned int i = 0, j = 0;
1855 lpDxW = HeapAlloc( GetProcessHeap(), 0, wlen*sizeof(INT));
1857 if(IsDBCSLeadByteEx(codepage, str[i])) {
1858 lpDxW[j++] = lpDx[i] + lpDx[i+1];
1861 lpDxW[j++] = lpDx[i];
1867 ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1869 HeapFree( GetProcessHeap(), 0, p );
1870 HeapFree( GetProcessHeap(), 0, lpDxW );
1875 /***********************************************************************
1876 * ExtTextOutW (GDI32.@)
1878 * Draws text using the currently selected font, background color, and text color.
1882 * x,y [I] coordinates of string
1884 * ETO_GRAYED - undocumented on MSDN
1885 * ETO_OPAQUE - use background color for fill the rectangle
1886 * ETO_CLIPPED - clipping text to the rectangle
1887 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1888 * than encoded characters. Implies ETO_IGNORELANGUAGE
1889 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1890 * Affects BiDi ordering
1891 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1892 * ETO_PDY - unimplemented
1893 * ETO_NUMERICSLATIN - unimplemented always assumed -
1894 * do not translate numbers into locale representations
1895 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1896 * lprect [I] dimensions for clipping or/and opaquing
1897 * str [I] text string
1898 * count [I] number of symbols in string
1899 * lpDx [I] optional parameter with distance between drawing characters
1905 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1906 const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1909 LPWSTR reordered_str = (LPWSTR)str;
1910 WORD *glyphs = NULL;
1911 UINT align = GetTextAlign( hdc );
1915 double cosEsc, sinEsc;
1916 INT *deltas = NULL, char_extra;
1919 BOOL done_extents = FALSE;
1920 INT width = 0, xwidth = 0, ywidth = 0;
1922 DC * dc = get_dc_ptr( hdc );
1925 if (!dc) return FALSE;
1927 breakRem = dc->breakRem;
1929 if (flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY))
1930 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY unimplemented\n");
1932 if (!dc->funcs->pExtTextOut && !PATH_IsPathOpen(dc->path))
1934 release_dc_ptr( dc );
1939 type = GetObjectType(hdc);
1940 if(type == OBJ_METADC || type == OBJ_ENHMETADC)
1942 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, flags, lprect, str, count, lpDx);
1943 release_dc_ptr( dc );
1948 flags &= ~ETO_CLIPPED;
1950 if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && count > 0 )
1952 reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1954 BIDI_Reorder( str, count, GCP_REORDER,
1955 ((flags&ETO_RTLREADING)!=0 || (GetTextAlign(hdc)&TA_RTLREADING)!=0)?
1956 WINE_GCPW_FORCE_RTL:WINE_GCPW_FORCE_LTR,
1957 reordered_str, count, NULL );
1959 flags |= ETO_IGNORELANGUAGE;
1962 TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc, x, y, flags,
1963 lprect, debugstr_wn(str, count), count, lpDx);
1965 if(flags & ETO_GLYPH_INDEX)
1966 glyphs = reordered_str;
1969 TRACE("rect: %d,%d - %d,%d\n", lprect->left, lprect->top, lprect->right,
1971 TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
1973 if(align & TA_UPDATECP)
1975 GetCurrentPositionEx( hdc, &pt );
1980 GetTextMetricsW(hdc, &tm);
1981 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1983 if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
1984 lf.lfEscapement = 0;
1986 if(lf.lfEscapement != 0)
1988 cosEsc = cos(lf.lfEscapement * M_PI / 1800);
1989 sinEsc = sin(lf.lfEscapement * M_PI / 1800);
1997 if(flags & (ETO_CLIPPED | ETO_OPAQUE))
2001 if(flags & ETO_GLYPH_INDEX)
2002 GetTextExtentPointI(hdc, glyphs, count, &sz);
2004 GetTextExtentPointW(hdc, reordered_str, count, &sz);
2006 done_extents = TRUE;
2009 rc.right = x + sz.cx;
2010 rc.bottom = y + sz.cy;
2017 LPtoDP(hdc, (POINT*)&rc, 2);
2019 if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
2020 if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
2023 if ((flags & ETO_OPAQUE) && !PATH_IsPathOpen(dc->path))
2024 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
2034 LPtoDP(hdc, &pt, 1);
2038 char_extra = GetTextCharacterExtra(hdc);
2039 if(char_extra || dc->breakExtra || breakRem || lpDx || lf.lfEscapement != 0)
2043 deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT));
2044 for(i = 0; i < count; i++)
2046 if(lpDx && (flags & ETO_PDY))
2047 deltas[i] = lpDx[i*2] + char_extra;
2049 deltas[i] = lpDx[i] + char_extra;
2052 if(flags & ETO_GLYPH_INDEX)
2053 GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
2055 GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
2057 deltas[i] = tmpsz.cx;
2060 if (!(flags & ETO_GLYPH_INDEX) && (dc->breakExtra || breakRem) && reordered_str[i] == tm.tmBreakChar)
2062 deltas[i] = deltas[i] + dc->breakExtra;
2069 deltas[i] = INTERNAL_XWSTODS(dc, deltas[i]);
2077 if(flags & ETO_GLYPH_INDEX)
2078 GetTextExtentPointI(hdc, glyphs, count, &sz);
2080 GetTextExtentPointW(hdc, reordered_str, count, &sz);
2081 done_extents = TRUE;
2083 width = INTERNAL_XWSTODS(dc, sz.cx);
2085 xwidth = width * cosEsc;
2086 ywidth = width * sinEsc;
2088 tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
2089 tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
2090 switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
2093 if (align & TA_UPDATECP)
2097 DPtoLP(hdc, &pt, 1);
2098 MoveToEx(hdc, pt.x, pt.y, NULL);
2110 if (align & TA_UPDATECP)
2114 DPtoLP(hdc, &pt, 1);
2115 MoveToEx(hdc, pt.x, pt.y, NULL);
2120 switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
2123 y += tm.tmAscent * cosEsc;
2124 x += tm.tmAscent * sinEsc;
2128 y -= tm.tmDescent * cosEsc;
2129 x -= tm.tmDescent * sinEsc;
2136 if (GetBkMode(hdc) != TRANSPARENT && !PATH_IsPathOpen(dc->path))
2138 if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
2140 if(!(flags & ETO_OPAQUE) || x < rc.left || x + width >= rc.right ||
2141 y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
2145 rc.right = x + width;
2146 rc.top = y - tm.tmAscent;
2147 rc.bottom = y + tm.tmDescent;
2148 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
2153 if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
2155 HFONT orig_font = dc->hFont, cur_font;
2157 INT span = 0, *offsets = NULL;
2160 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2161 for(i = 0; i < count; i++)
2163 WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
2164 if(cur_font != dc->hFont)
2169 offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
2174 for(j = 1; j < count; j++)
2176 GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
2177 offsets[j] = offsets[j-1] + INTERNAL_XWSTODS(dc, tmpsz.cx);
2182 for(j = 1; j < count; j++)
2183 offsets[j] = offsets[j-1] + deltas[j];
2188 if (PATH_IsPathOpen(dc->path))
2189 ret = PATH_ExtTextOut(dc, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
2190 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2191 glyphs, span, deltas ? deltas + i - span : NULL);
2193 dc->funcs->pExtTextOut(dc->physDev, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
2194 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2195 glyphs, span, deltas ? deltas + i - span : NULL);
2198 SelectObject(hdc, cur_font);
2200 glyphs[span++] = glyph;
2204 if (PATH_IsPathOpen(dc->path))
2205 ret = PATH_ExtTextOut(dc, x + (offsets ? offsets[count - span] * cosEsc : 0),
2206 y - (offsets ? offsets[count - span] * sinEsc : 0),
2207 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2208 glyphs, span, deltas ? deltas + count - span : NULL);
2210 ret = dc->funcs->pExtTextOut(dc->physDev, x + (offsets ? offsets[count - span] * cosEsc : 0),
2211 y - (offsets ? offsets[count - span] * sinEsc : 0),
2212 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2213 glyphs, span, deltas ? deltas + count - span : NULL);
2214 SelectObject(hdc, orig_font);
2215 HeapFree(GetProcessHeap(), 0, offsets);
2221 if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
2223 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2224 GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
2225 flags |= ETO_GLYPH_INDEX;
2228 if (PATH_IsPathOpen(dc->path))
2229 ret = PATH_ExtTextOut(dc, x, y, (flags & ~ETO_OPAQUE), &rc,
2230 glyphs ? glyphs : reordered_str, count, deltas);
2232 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, (flags & ~ETO_OPAQUE), &rc,
2233 glyphs ? glyphs : reordered_str, count, deltas);
2237 HeapFree(GetProcessHeap(), 0, deltas);
2238 if(glyphs != reordered_str)
2239 HeapFree(GetProcessHeap(), 0, glyphs);
2240 if(reordered_str != str)
2241 HeapFree(GetProcessHeap(), 0, reordered_str);
2243 release_dc_ptr( dc );
2245 if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2247 int underlinePos, strikeoutPos;
2248 int underlineWidth, strikeoutWidth;
2249 UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2250 OUTLINETEXTMETRICW* otm = NULL;
2255 underlineWidth = tm.tmAscent / 20 + 1;
2256 strikeoutPos = tm.tmAscent / 2;
2257 strikeoutWidth = underlineWidth;
2261 otm = HeapAlloc(GetProcessHeap(), 0, size);
2262 GetOutlineTextMetricsW(hdc, size, otm);
2263 underlinePos = otm->otmsUnderscorePosition;
2264 underlineWidth = otm->otmsUnderscoreSize;
2265 strikeoutPos = otm->otmsStrikeoutPosition;
2266 strikeoutWidth = otm->otmsStrikeoutSize;
2267 HeapFree(GetProcessHeap(), 0, otm);
2270 if (PATH_IsPathOpen(dc->path))
2274 HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2276 hbrush = SelectObject(hdc, hbrush);
2277 hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2281 pts[0].x = x - underlinePos * sinEsc;
2282 pts[0].y = y - underlinePos * cosEsc;
2283 pts[1].x = x + xwidth - underlinePos * sinEsc;
2284 pts[1].y = y - ywidth - underlinePos * cosEsc;
2285 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2286 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2287 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2288 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2289 pts[4].x = pts[0].x;
2290 pts[4].y = pts[0].y;
2291 DPtoLP(hdc, pts, 5);
2292 Polygon(hdc, pts, 5);
2297 pts[0].x = x - strikeoutPos * sinEsc;
2298 pts[0].y = y - strikeoutPos * cosEsc;
2299 pts[1].x = x + xwidth - strikeoutPos * sinEsc;
2300 pts[1].y = y - ywidth - strikeoutPos * cosEsc;
2301 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2302 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2303 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2304 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2305 pts[4].x = pts[0].x;
2306 pts[4].y = pts[0].y;
2307 DPtoLP(hdc, pts, 5);
2308 Polygon(hdc, pts, 5);
2311 SelectObject(hdc, hpen);
2312 hbrush = SelectObject(hdc, hbrush);
2313 DeleteObject(hbrush);
2317 POINT pts[2], oldpt;
2322 hpen = CreatePen(PS_SOLID, underlineWidth, GetTextColor(hdc));
2323 hpen = SelectObject(hdc, hpen);
2326 pts[1].x = x + xwidth;
2327 pts[1].y = y - ywidth;
2328 DPtoLP(hdc, pts, 2);
2329 MoveToEx(hdc, pts[0].x - underlinePos * sinEsc, pts[0].y - underlinePos * cosEsc, &oldpt);
2330 LineTo(hdc, pts[1].x - underlinePos * sinEsc, pts[1].y - underlinePos * cosEsc);
2331 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2332 DeleteObject(SelectObject(hdc, hpen));
2337 hpen = CreatePen(PS_SOLID, strikeoutWidth, GetTextColor(hdc));
2338 hpen = SelectObject(hdc, hpen);
2341 pts[1].x = x + xwidth;
2342 pts[1].y = y - ywidth;
2343 DPtoLP(hdc, pts, 2);
2344 MoveToEx(hdc, pts[0].x - strikeoutPos * sinEsc, pts[0].y - strikeoutPos * cosEsc, &oldpt);
2345 LineTo(hdc, pts[1].x - strikeoutPos * sinEsc, pts[1].y - strikeoutPos * cosEsc);
2346 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2347 DeleteObject(SelectObject(hdc, hpen));
2356 /***********************************************************************
2357 * TextOutA (GDI32.@)
2359 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2361 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2365 /***********************************************************************
2366 * TextOutW (GDI32.@)
2368 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2370 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2374 /***********************************************************************
2375 * PolyTextOutA (GDI32.@)
2379 BOOL WINAPI PolyTextOutA( HDC hdc, const POLYTEXTA *pptxt, INT cStrings )
2381 for (; cStrings>0; cStrings--, pptxt++)
2382 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2389 /***********************************************************************
2390 * PolyTextOutW (GDI32.@)
2392 * Draw several Strings
2398 BOOL WINAPI PolyTextOutW( HDC hdc, const POLYTEXTW *pptxt, INT cStrings )
2400 for (; cStrings>0; cStrings--, pptxt++)
2401 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2407 /* FIXME: all following APIs ******************************************/
2410 /***********************************************************************
2411 * SetMapperFlags (GDI32.@)
2413 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
2415 DC *dc = DC_GetDCPtr( hDC );
2418 if(dc->funcs->pSetMapperFlags)
2420 ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
2421 /* FIXME: ret is just a success flag, we should return a proper value */
2424 FIXME("(%p, 0x%08x): stub - harmless\n", hDC, dwFlag);
2425 DC_ReleaseDCPtr( dc );
2429 /***********************************************************************
2430 * GetAspectRatioFilterEx (GDI.486)
2432 BOOL16 WINAPI GetAspectRatioFilterEx16( HDC16 hdc, LPSIZE16 pAspectRatio )
2434 FIXME("(%04x, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2438 /***********************************************************************
2439 * GetAspectRatioFilterEx (GDI32.@)
2441 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2443 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2448 /***********************************************************************
2449 * GetCharABCWidthsA (GDI32.@)
2451 * See GetCharABCWidthsW.
2453 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2456 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
2461 if(count <= 0) return FALSE;
2463 str = HeapAlloc(GetProcessHeap(), 0, count);
2464 for(i = 0; i < count; i++)
2465 str[i] = (BYTE)(firstChar + i);
2467 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
2469 for(i = 0; i < wlen; i++)
2471 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2479 HeapFree(GetProcessHeap(), 0, str);
2480 HeapFree(GetProcessHeap(), 0, wstr);
2486 /******************************************************************************
2487 * GetCharABCWidthsW [GDI32.@]
2489 * Retrieves widths of characters in range.
2492 * hdc [I] Handle of device context
2493 * firstChar [I] First character in range to query
2494 * lastChar [I] Last character in range to query
2495 * abc [O] Address of character-width structure
2498 * Only works with TrueType fonts
2504 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2507 DC *dc = DC_GetDCPtr(hdc);
2511 if (!dc) return FALSE;
2514 ret = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
2520 /* convert device units to logical */
2521 for( i = firstChar; i <= lastChar; i++, abc++ ) {
2522 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2523 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2524 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2529 DC_ReleaseDCPtr( dc );
2534 /******************************************************************************
2535 * GetCharABCWidthsI [GDI32.@]
2537 * Retrieves widths of characters in range.
2540 * hdc [I] Handle of device context
2541 * firstChar [I] First glyphs in range to query
2542 * count [I] Last glyphs in range to query
2543 * pgi [i] Array of glyphs to query
2544 * abc [O] Address of character-width structure
2547 * Only works with TrueType fonts
2553 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2554 LPWORD pgi, LPABC abc)
2556 DC *dc = DC_GetDCPtr(hdc);
2560 if (!dc) return FALSE;
2563 ret = WineEngGetCharABCWidthsI( dc->gdiFont, firstChar, count, pgi, abc );
2569 /* convert device units to logical */
2570 for( i = 0; i < count; i++, abc++ ) {
2571 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2572 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2573 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2578 DC_ReleaseDCPtr( dc );
2583 /***********************************************************************
2584 * GetGlyphOutlineA (GDI32.@)
2586 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2587 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2588 LPVOID lpBuffer, const MAT2 *lpmat2 )
2594 if(!(fuFormat & GGO_GLYPH_INDEX)) {
2597 if(uChar > 0xff) { /* but, 2 bytes character only */
2599 mbchs[0] = (uChar & 0xff00) >> 8;
2600 mbchs[1] = (uChar & 0xff);
2603 mbchs[0] = (uChar & 0xff);
2605 p = FONT_mbtowc(hdc, mbchs, len, NULL, NULL);
2609 ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
2611 HeapFree(GetProcessHeap(), 0, p);
2615 /***********************************************************************
2616 * GetGlyphOutlineW (GDI32.@)
2618 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2619 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2620 LPVOID lpBuffer, const MAT2 *lpmat2 )
2622 DC *dc = DC_GetDCPtr(hdc);
2625 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2626 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2628 if(!dc) return GDI_ERROR;
2631 ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
2632 cbBuffer, lpBuffer, lpmat2);
2636 DC_ReleaseDCPtr( dc );
2641 /***********************************************************************
2642 * CreateScalableFontResourceA (GDI32.@)
2644 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2645 LPCSTR lpszResourceFile,
2646 LPCSTR lpszFontFile,
2647 LPCSTR lpszCurrentPath )
2651 /* fHidden=1 - only visible for the calling app, read-only, not
2652 * enumbered with EnumFonts/EnumFontFamilies
2653 * lpszCurrentPath can be NULL
2655 FIXME("(%d,%s,%s,%s): stub\n",
2656 fHidden, debugstr_a(lpszResourceFile), debugstr_a(lpszFontFile),
2657 debugstr_a(lpszCurrentPath) );
2659 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2660 if ((f = CreateFileA(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2662 SetLastError(ERROR_FILE_EXISTS);
2665 return FALSE; /* create failed */
2668 /***********************************************************************
2669 * CreateScalableFontResourceW (GDI32.@)
2671 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2672 LPCWSTR lpszResourceFile,
2673 LPCWSTR lpszFontFile,
2674 LPCWSTR lpszCurrentPath )
2676 FIXME("(%d,%p,%p,%p): stub\n",
2677 fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
2678 return FALSE; /* create failed */
2681 /*************************************************************************
2682 * GetKerningPairsA (GDI32.@)
2684 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2685 LPKERNINGPAIR kern_pairA )
2690 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2691 KERNINGPAIR *kern_pairW;
2693 if (!cPairs && kern_pairA)
2695 SetLastError(ERROR_INVALID_PARAMETER);
2699 charset = GetTextCharset(hDC);
2700 if (!TranslateCharsetInfo(ULongToPtr(charset), &csi, TCI_SRCCHARSET))
2702 FIXME("Can't find codepage for charset %d\n", charset);
2705 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2706 * to fail on an invalid character for CP_SYMBOL.
2708 cpi.DefaultChar[0] = 0;
2709 if (csi.ciACP != CP_SYMBOL && !GetCPInfo(csi.ciACP, &cpi))
2711 FIXME("Can't find codepage %u info\n", csi.ciACP);
2714 TRACE("charset %d => codepage %u\n", charset, csi.ciACP);
2716 total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2717 if (!total_kern_pairs) return 0;
2719 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2720 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2722 for (i = 0; i < total_kern_pairs; i++)
2726 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2729 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2732 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2737 if (kern_pairs_copied >= cPairs) break;
2739 kern_pairA->wFirst = (BYTE)first;
2740 kern_pairA->wSecond = (BYTE)second;
2741 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2744 kern_pairs_copied++;
2747 HeapFree(GetProcessHeap(), 0, kern_pairW);
2749 return kern_pairs_copied;
2752 /*************************************************************************
2753 * GetKerningPairsW (GDI32.@)
2755 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2756 LPKERNINGPAIR lpKerningPairs )
2761 TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2763 if (!cPairs && lpKerningPairs)
2765 SetLastError(ERROR_INVALID_PARAMETER);
2769 dc = DC_GetDCPtr(hDC);
2773 ret = WineEngGetKerningPairs(dc->gdiFont, cPairs, lpKerningPairs);
2775 DC_ReleaseDCPtr( dc );
2779 /*************************************************************************
2780 * TranslateCharsetInfo [GDI32.@]
2782 * Fills a CHARSETINFO structure for a character set, code page, or
2783 * font. This allows making the correspondance between different labelings
2784 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2785 * of the same encoding.
2787 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2788 * only one codepage should be set in *lpSrc.
2791 * TRUE on success, FALSE on failure.
2794 BOOL WINAPI TranslateCharsetInfo(
2795 LPDWORD lpSrc, /* [in]
2796 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2797 if flags == TCI_SRCCHARSET: a character set value
2798 if flags == TCI_SRCCODEPAGE: a code page value
2800 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2801 DWORD flags /* [in] determines interpretation of lpSrc */)
2805 case TCI_SRCFONTSIG:
2806 while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
2808 case TCI_SRCCODEPAGE:
2809 while (PtrToUlong(lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
2811 case TCI_SRCCHARSET:
2812 while (PtrToUlong(lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
2817 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2818 memcpy(lpCs, &FONT_tci[index], sizeof(CHARSETINFO));
2822 /*************************************************************************
2823 * GetFontLanguageInfo (GDI32.@)
2825 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2827 FONTSIGNATURE fontsig;
2828 static const DWORD GCP_DBCS_MASK=0x003F0000,
2829 GCP_DIACRITIC_MASK=0x00000000,
2830 FLI_GLYPHS_MASK=0x00000000,
2831 GCP_GLYPHSHAPE_MASK=0x00000040,
2832 GCP_KASHIDA_MASK=0x00000000,
2833 GCP_LIGATE_MASK=0x00000000,
2834 GCP_USEKERNING_MASK=0x00000000,
2835 GCP_REORDER_MASK=0x00000060;
2839 GetTextCharsetInfo( hdc, &fontsig, 0 );
2840 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2842 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2845 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2846 result|=GCP_DIACRITIC;
2848 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2851 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2852 result|=GCP_GLYPHSHAPE;
2854 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2855 result|=GCP_KASHIDA;
2857 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2860 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2861 result|=GCP_USEKERNING;
2863 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2864 if( GetTextAlign( hdc) & TA_RTLREADING )
2865 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2866 result|=GCP_REORDER;
2872 /*************************************************************************
2873 * GetFontData [GDI32.@]
2875 * Retrieve data for TrueType font.
2879 * success: Number of bytes returned
2880 * failure: GDI_ERROR
2884 * Calls SetLastError()
2887 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2888 LPVOID buffer, DWORD length)
2890 DC *dc = DC_GetDCPtr(hdc);
2891 DWORD ret = GDI_ERROR;
2893 if(!dc) return GDI_ERROR;
2896 ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2898 DC_ReleaseDCPtr( dc );
2902 /*************************************************************************
2903 * GetGlyphIndicesA [GDI32.@]
2905 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2906 LPWORD pgi, DWORD flags)
2912 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2913 hdc, debugstr_an(lpstr, count), count, pgi, flags);
2915 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2916 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2917 HeapFree(GetProcessHeap(), 0, lpstrW);
2922 /*************************************************************************
2923 * GetGlyphIndicesW [GDI32.@]
2925 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2926 LPWORD pgi, DWORD flags)
2928 DC *dc = DC_GetDCPtr(hdc);
2929 DWORD ret = GDI_ERROR;
2931 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2932 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2934 if(!dc) return GDI_ERROR;
2937 ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2939 DC_ReleaseDCPtr( dc );
2943 /*************************************************************************
2944 * GetCharacterPlacementA [GDI32.@]
2946 * See GetCharacterPlacementW.
2949 * the web browser control of ie4 calls this with dwFlags=0
2952 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2953 INT nMaxExtent, GCP_RESULTSA *lpResults,
2958 GCP_RESULTSW resultsW;
2962 TRACE("%s, %d, %d, 0x%08x\n",
2963 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2965 /* both structs are equal in size */
2966 memcpy(&resultsW, lpResults, sizeof(resultsW));
2968 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2969 if(lpResults->lpOutString)
2970 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2972 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2974 lpResults->nGlyphs = resultsW.nGlyphs;
2975 lpResults->nMaxFit = resultsW.nMaxFit;
2977 if(lpResults->lpOutString) {
2978 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2979 lpResults->lpOutString, uCount, NULL, NULL );
2982 HeapFree(GetProcessHeap(), 0, lpStringW);
2983 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2988 /*************************************************************************
2989 * GetCharacterPlacementW [GDI32.@]
2991 * Retrieve information about a string. This includes the width, reordering,
2992 * Glyphing and so on.
2996 * The width and height of the string if successful, 0 if failed.
3000 * All flags except GCP_REORDER are not yet implemented.
3001 * Reordering is not 100% complient to the Windows BiDi method.
3002 * Caret positioning is not yet implemented for BiDi.
3003 * Classes are not yet implemented.
3007 GetCharacterPlacementW(
3008 HDC hdc, /* [in] Device context for which the rendering is to be done */
3009 LPCWSTR lpString, /* [in] The string for which information is to be returned */
3010 INT uCount, /* [in] Number of WORDS in string. */
3011 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
3012 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
3013 DWORD dwFlags /* [in] Flags specifying how to process the string */
3020 TRACE("%s, %d, %d, 0x%08x\n",
3021 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
3023 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
3024 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
3025 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
3026 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
3027 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
3029 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08x ignored\n", dwFlags);
3030 if(lpResults->lpClass) FIXME("classes not implemented\n");
3031 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
3032 FIXME("Caret positions for complex scripts not implemented\n");
3034 nSet = (UINT)uCount;
3035 if(nSet > lpResults->nGlyphs)
3036 nSet = lpResults->nGlyphs;
3038 /* return number of initialized fields */
3039 lpResults->nGlyphs = nSet;
3041 if((dwFlags&GCP_REORDER)==0 )
3043 /* Treat the case where no special handling was requested in a fastpath way */
3044 /* copy will do if the GCP_REORDER flag is not set */
3045 if(lpResults->lpOutString)
3046 memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
3048 if(lpResults->lpOrder)
3050 for(i = 0; i < nSet; i++)
3051 lpResults->lpOrder[i] = i;
3055 BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
3056 nSet, lpResults->lpOrder );
3059 /* FIXME: Will use the placement chars */
3060 if (lpResults->lpDx)
3063 for (i = 0; i < nSet; i++)
3065 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
3066 lpResults->lpDx[i]= c;
3070 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
3074 lpResults->lpCaretPos[0] = 0;
3075 for (i = 1; i < nSet; i++)
3076 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
3077 lpResults->lpCaretPos[i] = (pos += size.cx);
3080 if(lpResults->lpGlyphs)
3081 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
3083 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
3084 ret = MAKELONG(size.cx, size.cy);
3089 /*************************************************************************
3090 * GetCharABCWidthsFloatA [GDI32.@]
3092 * See GetCharABCWidthsFloatW.
3094 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3096 INT i, wlen, count = (INT)(last - first + 1);
3101 if (count <= 0) return FALSE;
3103 str = HeapAlloc(GetProcessHeap(), 0, count);
3105 for(i = 0; i < count; i++)
3106 str[i] = (BYTE)(first + i);
3108 wstr = FONT_mbtowc( hdc, str, count, &wlen, NULL );
3110 for (i = 0; i < wlen; i++)
3112 if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
3120 HeapFree( GetProcessHeap(), 0, str );
3121 HeapFree( GetProcessHeap(), 0, wstr );
3126 /*************************************************************************
3127 * GetCharABCWidthsFloatW [GDI32.@]
3129 * Retrieves widths of a range of characters.
3132 * hdc [I] Handle to device context.
3133 * first [I] First character in range to query.
3134 * last [I] Last character in range to query.
3135 * abcf [O] Array of LPABCFLOAT structures.
3142 * Only works with TrueType fonts. It also doesn't return real
3143 * floats but converted integers because it's implemented on
3144 * top of GetCharABCWidthsW.
3146 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3149 unsigned int i, size = sizeof(ABC) * (last - first + 1);
3152 TRACE("%p, %d, %d, %p - partial stub\n", hdc, first, last, abcf);
3154 abc = HeapAlloc( GetProcessHeap(), 0, size );
3155 if (!abc) return FALSE;
3157 ret = GetCharABCWidthsW( hdc, first, last, abc );
3160 for (i = first; i <= last; i++, abc++, abcf++)
3162 abcf->abcfA = abc->abcA;
3163 abcf->abcfB = abc->abcB;
3164 abcf->abcfC = abc->abcC;
3167 HeapFree( GetProcessHeap(), 0, abc );
3171 /*************************************************************************
3172 * GetCharWidthFloatA [GDI32.@]
3174 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
3175 UINT iLastChar, PFLOAT pxBuffer)
3177 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3181 /*************************************************************************
3182 * GetCharWidthFloatW [GDI32.@]
3184 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
3185 UINT iLastChar, PFLOAT pxBuffer)
3187 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3192 /***********************************************************************
3194 * Font Resource API *
3196 ***********************************************************************/
3198 /***********************************************************************
3199 * AddFontResourceA (GDI32.@)
3201 INT WINAPI AddFontResourceA( LPCSTR str )
3203 return AddFontResourceExA( str, 0, NULL);
3206 /***********************************************************************
3207 * AddFontResourceW (GDI32.@)
3209 INT WINAPI AddFontResourceW( LPCWSTR str )
3211 return AddFontResourceExW(str, 0, NULL);
3215 /***********************************************************************
3216 * AddFontResourceExA (GDI32.@)
3218 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3220 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3221 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3224 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3225 ret = AddFontResourceExW(strW, fl, pdv);
3226 HeapFree(GetProcessHeap(), 0, strW);
3230 static BOOL CALLBACK load_enumed_resource(HMODULE hModule, LPCWSTR type, LPWSTR name, LONG_PTR lParam)
3232 HRSRC rsrc = FindResourceW(hModule, name, type);
3233 HGLOBAL hMem = LoadResource(hModule, rsrc);
3234 LPVOID *pMem = LockResource(hMem);
3235 int *num_total = (int *)lParam;
3238 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type));
3239 if (!AddFontMemResourceEx(pMem, SizeofResource(hModule, rsrc), NULL, &num_in_res))
3241 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule, hMem);
3245 *num_total += num_in_res;
3249 /***********************************************************************
3250 * AddFontResourceExW (GDI32.@)
3252 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3254 int ret = WineEngAddFontResourceEx(str, fl, pdv);
3257 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3258 HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
3259 if (hModule != NULL)
3261 int num_resources = 0;
3262 LPWSTR rt_font = (LPWSTR)((ULONG_PTR)8); /* we don't want to include winuser.h */
3264 TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3265 wine_dbgstr_w(str));
3266 if (EnumResourceNamesW(hModule, rt_font, load_enumed_resource, (LONG_PTR)&num_resources))
3267 ret = num_resources;
3268 FreeLibrary(hModule);
3274 /***********************************************************************
3275 * RemoveFontResourceA (GDI32.@)
3277 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3279 return RemoveFontResourceExA(str, 0, 0);
3282 /***********************************************************************
3283 * RemoveFontResourceW (GDI32.@)
3285 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3287 return RemoveFontResourceExW(str, 0, 0);
3290 /***********************************************************************
3291 * AddFontMemResourceEx (GDI32.@)
3293 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3295 return WineEngAddFontMemResourceEx(pbFont, cbFont, pdv, pcFonts);
3298 /***********************************************************************
3299 * RemoveFontResourceExA (GDI32.@)
3301 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3303 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3304 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3307 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3308 ret = RemoveFontResourceExW(strW, fl, pdv);
3309 HeapFree(GetProcessHeap(), 0, strW);
3313 /***********************************************************************
3314 * RemoveFontResourceExW (GDI32.@)
3316 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3318 return WineEngRemoveFontResourceEx(str, fl, pdv);
3321 /***********************************************************************
3322 * GetTextCharset (GDI32.@)
3324 UINT WINAPI GetTextCharset(HDC hdc)
3326 /* MSDN docs say this is equivalent */
3327 return GetTextCharsetInfo(hdc, NULL, 0);
3330 /***********************************************************************
3331 * GetTextCharsetInfo (GDI32.@)
3333 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3335 UINT ret = DEFAULT_CHARSET;
3336 DC *dc = DC_GetDCPtr(hdc);
3341 ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
3343 DC_ReleaseDCPtr( dc );
3346 if (ret == DEFAULT_CHARSET && fs)
3347 memset(fs, 0, sizeof(FONTSIGNATURE));
3351 /***********************************************************************
3352 * GdiGetCharDimensions (GDI32.@)
3354 * Gets the average width of the characters in the English alphabet.
3357 * hdc [I] Handle to the device context to measure on.
3358 * lptm [O] Pointer to memory to store the text metrics into.
3359 * height [O] On exit, the maximum height of characters in the English alphabet.
3362 * The average width of characters in the English alphabet.
3365 * This function is used by the dialog manager to get the size of a dialog
3366 * unit. It should also be used by other pieces of code that need to know
3367 * the size of a dialog unit in logical units without having access to the
3368 * window handle of the dialog.
3369 * Windows caches the font metrics from this function, but we don't and
3370 * there doesn't appear to be an immediate advantage to do so.
3373 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3375 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3378 static const WCHAR alphabet[] = {
3379 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3380 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3381 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3383 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3385 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3387 if (height) *height = sz.cy;
3388 return (sz.cx / 26 + 1) / 2;
3391 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3393 FIXME("(%d): stub\n", fEnableEUDC);
3397 /***********************************************************************
3398 * GetCharWidthI (GDI32.@)
3400 * Retrieve widths of characters.
3403 * hdc [I] Handle to a device context.
3404 * first [I] First glyph in range to query.
3405 * count [I] Number of glyph indices to query.
3406 * glyphs [I] Array of glyphs to query.
3407 * buffer [O] Buffer to receive character widths.
3410 * Only works with TrueType fonts.
3416 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3421 TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3423 if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3426 if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3428 HeapFree(GetProcessHeap(), 0, abc);
3432 for (i = 0; i < count; i++)
3433 buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3435 HeapFree(GetProcessHeap(), 0, abc);
3439 /***********************************************************************
3440 * GetFontUnicodeRanges (GDI32.@)
3442 * Retrieve a list of supported Unicode characters in a font.
3445 * hdc [I] Handle to a device context.
3446 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3449 * Success: Number of bytes written to the buffer pointed to by lpgs.
3453 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3456 DC *dc = DC_GetDCPtr(hdc);
3458 TRACE("(%p, %p)\n", hdc, lpgs);
3462 if (dc->gdiFont) ret = WineEngGetFontUnicodeRanges(dc->gdiFont, lpgs);
3463 DC_ReleaseDCPtr(dc);
3468 /*************************************************************
3469 * FontIsLinked (GDI32.@)
3471 BOOL WINAPI FontIsLinked(HDC hdc)
3473 DC *dc = DC_GetDCPtr(hdc);
3476 if (!dc) return FALSE;
3477 if (dc->gdiFont) ret = WineEngFontIsLinked(dc->gdiFont);
3478 DC_ReleaseDCPtr(dc);
3479 TRACE("returning %d\n", ret);