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 MAXTCIINDEX 32
145 static const CHARSETINFO FONT_tci[MAXTCIINDEX] = {
147 { ANSI_CHARSET, 1252, {{0,0,0,0},{FS_LATIN1,0}} },
148 { EASTEUROPE_CHARSET, 1250, {{0,0,0,0},{FS_LATIN2,0}} },
149 { RUSSIAN_CHARSET, 1251, {{0,0,0,0},{FS_CYRILLIC,0}} },
150 { GREEK_CHARSET, 1253, {{0,0,0,0},{FS_GREEK,0}} },
151 { TURKISH_CHARSET, 1254, {{0,0,0,0},{FS_TURKISH,0}} },
152 { HEBREW_CHARSET, 1255, {{0,0,0,0},{FS_HEBREW,0}} },
153 { ARABIC_CHARSET, 1256, {{0,0,0,0},{FS_ARABIC,0}} },
154 { BALTIC_CHARSET, 1257, {{0,0,0,0},{FS_BALTIC,0}} },
155 { VIETNAMESE_CHARSET, 1258, {{0,0,0,0},{FS_VIETNAMESE,0}} },
156 /* reserved by ANSI */
157 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
158 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
159 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
160 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
161 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
162 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
163 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
165 { THAI_CHARSET, 874, {{0,0,0,0},{FS_THAI,0}} },
166 { SHIFTJIS_CHARSET, 932, {{0,0,0,0},{FS_JISJAPAN,0}} },
167 { GB2312_CHARSET, 936, {{0,0,0,0},{FS_CHINESESIMP,0}} },
168 { HANGEUL_CHARSET, 949, {{0,0,0,0},{FS_WANSUNG,0}} },
169 { CHINESEBIG5_CHARSET, 950, {{0,0,0,0},{FS_CHINESETRAD,0}} },
170 { JOHAB_CHARSET, 1361, {{0,0,0,0},{FS_JOHAB,0}} },
171 /* reserved for alternate ANSI and OEM */
172 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
173 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
174 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
175 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
176 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
177 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
178 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
179 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
180 /* reserved for system */
181 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
182 { SYMBOL_CHARSET, CP_SYMBOL, {{0,0,0,0},{FS_SYMBOL,0}} }
185 /***********************************************************************
186 * LOGFONT conversion functions.
188 static void FONT_LogFontWTo16( const LOGFONTW* font32, LPLOGFONT16 font16 )
190 font16->lfHeight = font32->lfHeight;
191 font16->lfWidth = font32->lfWidth;
192 font16->lfEscapement = font32->lfEscapement;
193 font16->lfOrientation = font32->lfOrientation;
194 font16->lfWeight = font32->lfWeight;
195 font16->lfItalic = font32->lfItalic;
196 font16->lfUnderline = font32->lfUnderline;
197 font16->lfStrikeOut = font32->lfStrikeOut;
198 font16->lfCharSet = font32->lfCharSet;
199 font16->lfOutPrecision = font32->lfOutPrecision;
200 font16->lfClipPrecision = font32->lfClipPrecision;
201 font16->lfQuality = font32->lfQuality;
202 font16->lfPitchAndFamily = font32->lfPitchAndFamily;
203 WideCharToMultiByte( CP_ACP, 0, font32->lfFaceName, -1,
204 font16->lfFaceName, LF_FACESIZE, NULL, NULL );
205 font16->lfFaceName[LF_FACESIZE-1] = 0;
208 static void FONT_LogFont16ToW( const LOGFONT16 *font16, LPLOGFONTW font32 )
210 font32->lfHeight = font16->lfHeight;
211 font32->lfWidth = font16->lfWidth;
212 font32->lfEscapement = font16->lfEscapement;
213 font32->lfOrientation = font16->lfOrientation;
214 font32->lfWeight = font16->lfWeight;
215 font32->lfItalic = font16->lfItalic;
216 font32->lfUnderline = font16->lfUnderline;
217 font32->lfStrikeOut = font16->lfStrikeOut;
218 font32->lfCharSet = font16->lfCharSet;
219 font32->lfOutPrecision = font16->lfOutPrecision;
220 font32->lfClipPrecision = font16->lfClipPrecision;
221 font32->lfQuality = font16->lfQuality;
222 font32->lfPitchAndFamily = font16->lfPitchAndFamily;
223 MultiByteToWideChar( CP_ACP, 0, font16->lfFaceName, -1, font32->lfFaceName, LF_FACESIZE );
224 font32->lfFaceName[LF_FACESIZE-1] = 0;
227 static void FONT_LogFontAToW( const LOGFONTA *fontA, LPLOGFONTW fontW )
229 memcpy(fontW, fontA, sizeof(LOGFONTA) - LF_FACESIZE);
230 MultiByteToWideChar(CP_ACP, 0, fontA->lfFaceName, -1, fontW->lfFaceName,
232 fontW->lfFaceName[LF_FACESIZE-1] = 0;
235 static void FONT_LogFontWToA( const LOGFONTW *fontW, LPLOGFONTA fontA )
237 memcpy(fontA, fontW, sizeof(LOGFONTA) - LF_FACESIZE);
238 WideCharToMultiByte(CP_ACP, 0, fontW->lfFaceName, -1, fontA->lfFaceName,
239 LF_FACESIZE, NULL, NULL);
240 fontA->lfFaceName[LF_FACESIZE-1] = 0;
243 static void FONT_EnumLogFontExWTo16( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEX16 font16 )
245 FONT_LogFontWTo16( (const LOGFONTW *)fontW, (LPLOGFONT16)font16);
247 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
248 (LPSTR) font16->elfFullName, LF_FULLFACESIZE, NULL, NULL );
249 font16->elfFullName[LF_FULLFACESIZE-1] = '\0';
250 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
251 (LPSTR) font16->elfStyle, LF_FACESIZE, NULL, NULL );
252 font16->elfStyle[LF_FACESIZE-1] = '\0';
253 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
254 (LPSTR) font16->elfScript, LF_FACESIZE, NULL, NULL );
255 font16->elfScript[LF_FACESIZE-1] = '\0';
258 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEXA fontA )
260 FONT_LogFontWToA( (const LOGFONTW *)fontW, (LPLOGFONTA)fontA);
262 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
263 (LPSTR) fontA->elfFullName, LF_FULLFACESIZE, NULL, NULL );
264 fontA->elfFullName[LF_FULLFACESIZE-1] = '\0';
265 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
266 (LPSTR) fontA->elfStyle, LF_FACESIZE, NULL, NULL );
267 fontA->elfStyle[LF_FACESIZE-1] = '\0';
268 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
269 (LPSTR) fontA->elfScript, LF_FACESIZE, NULL, NULL );
270 fontA->elfScript[LF_FACESIZE-1] = '\0';
273 /***********************************************************************
274 * TEXTMETRIC conversion functions.
276 static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
278 ptmA->tmHeight = ptmW->tmHeight;
279 ptmA->tmAscent = ptmW->tmAscent;
280 ptmA->tmDescent = ptmW->tmDescent;
281 ptmA->tmInternalLeading = ptmW->tmInternalLeading;
282 ptmA->tmExternalLeading = ptmW->tmExternalLeading;
283 ptmA->tmAveCharWidth = ptmW->tmAveCharWidth;
284 ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth;
285 ptmA->tmWeight = ptmW->tmWeight;
286 ptmA->tmOverhang = ptmW->tmOverhang;
287 ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX;
288 ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
289 ptmA->tmFirstChar = min(ptmW->tmFirstChar, 255);
290 if (ptmW->tmCharSet == SYMBOL_CHARSET)
292 UINT last_char = ptmW->tmLastChar;
293 if (last_char > 0xf000) last_char -= 0xf000;
294 ptmA->tmLastChar = min(last_char, 255);
297 ptmA->tmLastChar = min(ptmW->tmLastChar, 255);
298 ptmA->tmDefaultChar = min(ptmW->tmDefaultChar, 255);
299 ptmA->tmBreakChar = min(ptmW->tmBreakChar, 255);
300 ptmA->tmItalic = ptmW->tmItalic;
301 ptmA->tmUnderlined = ptmW->tmUnderlined;
302 ptmA->tmStruckOut = ptmW->tmStruckOut;
303 ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
304 ptmA->tmCharSet = ptmW->tmCharSet;
308 static void FONT_NewTextMetricExWTo16(const NEWTEXTMETRICEXW *ptmW, LPNEWTEXTMETRICEX16 ptm16 )
310 ptm16->ntmTm.tmHeight = ptmW->ntmTm.tmHeight;
311 ptm16->ntmTm.tmAscent = ptmW->ntmTm.tmAscent;
312 ptm16->ntmTm.tmDescent = ptmW->ntmTm.tmDescent;
313 ptm16->ntmTm.tmInternalLeading = ptmW->ntmTm.tmInternalLeading;
314 ptm16->ntmTm.tmExternalLeading = ptmW->ntmTm.tmExternalLeading;
315 ptm16->ntmTm.tmAveCharWidth = ptmW->ntmTm.tmAveCharWidth;
316 ptm16->ntmTm.tmMaxCharWidth = ptmW->ntmTm.tmMaxCharWidth;
317 ptm16->ntmTm.tmWeight = ptmW->ntmTm.tmWeight;
318 ptm16->ntmTm.tmOverhang = ptmW->ntmTm.tmOverhang;
319 ptm16->ntmTm.tmDigitizedAspectX = ptmW->ntmTm.tmDigitizedAspectX;
320 ptm16->ntmTm.tmDigitizedAspectY = ptmW->ntmTm.tmDigitizedAspectY;
321 ptm16->ntmTm.tmFirstChar = ptmW->ntmTm.tmFirstChar > 255 ? 255 : ptmW->ntmTm.tmFirstChar;
322 ptm16->ntmTm.tmLastChar = ptmW->ntmTm.tmLastChar > 255 ? 255 : ptmW->ntmTm.tmLastChar;
323 ptm16->ntmTm.tmDefaultChar = ptmW->ntmTm.tmDefaultChar > 255 ? 255 : ptmW->ntmTm.tmDefaultChar;
324 ptm16->ntmTm.tmBreakChar = ptmW->ntmTm.tmBreakChar > 255 ? 255 : ptmW->ntmTm.tmBreakChar;
325 ptm16->ntmTm.tmItalic = ptmW->ntmTm.tmItalic;
326 ptm16->ntmTm.tmUnderlined = ptmW->ntmTm.tmUnderlined;
327 ptm16->ntmTm.tmStruckOut = ptmW->ntmTm.tmStruckOut;
328 ptm16->ntmTm.tmPitchAndFamily = ptmW->ntmTm.tmPitchAndFamily;
329 ptm16->ntmTm.tmCharSet = ptmW->ntmTm.tmCharSet;
330 ptm16->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
331 ptm16->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
332 ptm16->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
333 ptm16->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
334 memcpy(&ptm16->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
337 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW *ptmW, NEWTEXTMETRICEXA *ptmA )
339 FONT_TextMetricWToA((const TEXTMETRICW *)ptmW, (LPTEXTMETRICA)ptmA);
340 ptmA->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
341 ptmA->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
342 ptmA->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
343 ptmA->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
344 memcpy(&ptmA->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
348 /***********************************************************************
349 * GdiGetCodePage (GDI32.@)
351 DWORD WINAPI GdiGetCodePage( HDC hdc )
355 int charset = GetTextCharset(hdc);
357 /* Hmm, nicely designed api this one! */
358 if(TranslateCharsetInfo(ULongToPtr(charset), &csi, TCI_SRCCHARSET))
365 case DEFAULT_CHARSET:
376 /* FIXME: These have no place here, but because x11drv
377 enumerates fonts with these (made up) charsets some apps
378 might use them and then the FIXME below would become
379 annoying. Now we could pick the intended codepage for
380 each of these, but since it's broken anyway we'll just
381 use CP_ACP and hope it'll go away...
387 FIXME("Can't find codepage for charset %d\n", charset);
392 TRACE("charset %d => cp %d\n", charset, cp);
396 /***********************************************************************
399 * Returns a Unicode translation of str using the charset of the
400 * currently selected font in hdc. If count is -1 then str is assumed
401 * to be '\0' terminated, otherwise it contains the number of bytes to
402 * convert. If plenW is non-NULL, on return it will point to the
403 * number of WCHARs that have been written. If pCP is non-NULL, on
404 * return it will point to the codepage used in the conversion. The
405 * caller should free the returned LPWSTR from the process heap
408 static LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
414 cp = GdiGetCodePage( hdc );
416 if(count == -1) count = strlen(str);
417 lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
418 strW = HeapAlloc(GetProcessHeap(), 0, lenW*sizeof(WCHAR));
419 MultiByteToWideChar(cp, 0, str, count, strW, lenW);
420 TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW));
421 if(plenW) *plenW = lenW;
427 /***********************************************************************
428 * CreateFontIndirectA (GDI32.@)
430 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *plfA )
436 FONT_LogFontAToW( plfA, &lfW );
437 return CreateFontIndirectW( &lfW );
440 /***********************************************************************
441 * CreateFontIndirectW (GDI32.@)
443 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
445 static const WCHAR ItalicW[] = {' ','I','t','a','l','i','c','\0'};
446 static const WCHAR BoldW[] = {' ','B','o','l','d','\0'};
447 WCHAR *pFaceNameItalicSuffix, *pFaceNameBoldSuffix;
448 WCHAR *pFaceNameSuffix = NULL;
454 if (!(fontPtr = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC, (HGDIOBJ *)&hFont,
455 &font_funcs ))) return 0;
457 memcpy( &fontPtr->logfont, plf, sizeof(LOGFONTW) );
459 TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
460 plf->lfHeight, plf->lfWidth,
461 plf->lfEscapement, plf->lfOrientation,
462 plf->lfPitchAndFamily,
463 plf->lfOutPrecision, plf->lfClipPrecision,
464 plf->lfQuality, plf->lfCharSet,
465 debugstr_w(plf->lfFaceName),
466 plf->lfWeight > 400 ? "Bold" : "",
467 plf->lfItalic ? "Italic" : "",
468 plf->lfUnderline ? "Underline" : "", hFont);
470 if (plf->lfEscapement != plf->lfOrientation)
472 /* this should really depend on whether GM_ADVANCED is set */
473 fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
474 WARN("orientation angle %f set to "
475 "escapement angle %f for new font %p\n",
476 plf->lfOrientation/10., plf->lfEscapement/10., hFont);
479 pFaceNameItalicSuffix = strstrW(fontPtr->logfont.lfFaceName, ItalicW);
480 if (pFaceNameItalicSuffix)
482 fontPtr->logfont.lfItalic = TRUE;
483 pFaceNameSuffix = pFaceNameItalicSuffix;
486 pFaceNameBoldSuffix = strstrW(fontPtr->logfont.lfFaceName, BoldW);
487 if (pFaceNameBoldSuffix)
489 if (fontPtr->logfont.lfWeight < FW_BOLD)
490 fontPtr->logfont.lfWeight = FW_BOLD;
491 if (!pFaceNameSuffix || (pFaceNameBoldSuffix < pFaceNameSuffix))
492 pFaceNameSuffix = pFaceNameBoldSuffix;
495 if (pFaceNameSuffix) *pFaceNameSuffix = 0;
497 GDI_ReleaseObj( hFont );
501 /*************************************************************************
502 * CreateFontA (GDI32.@)
504 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
505 INT orient, INT weight, DWORD italic,
506 DWORD underline, DWORD strikeout, DWORD charset,
507 DWORD outpres, DWORD clippres, DWORD quality,
508 DWORD pitch, LPCSTR name )
512 logfont.lfHeight = height;
513 logfont.lfWidth = width;
514 logfont.lfEscapement = esc;
515 logfont.lfOrientation = orient;
516 logfont.lfWeight = weight;
517 logfont.lfItalic = italic;
518 logfont.lfUnderline = underline;
519 logfont.lfStrikeOut = strikeout;
520 logfont.lfCharSet = charset;
521 logfont.lfOutPrecision = outpres;
522 logfont.lfClipPrecision = clippres;
523 logfont.lfQuality = quality;
524 logfont.lfPitchAndFamily = pitch;
527 lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
529 logfont.lfFaceName[0] = '\0';
531 return CreateFontIndirectA( &logfont );
534 /*************************************************************************
535 * CreateFontW (GDI32.@)
537 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
538 INT orient, INT weight, DWORD italic,
539 DWORD underline, DWORD strikeout, DWORD charset,
540 DWORD outpres, DWORD clippres, DWORD quality,
541 DWORD pitch, LPCWSTR name )
545 logfont.lfHeight = height;
546 logfont.lfWidth = width;
547 logfont.lfEscapement = esc;
548 logfont.lfOrientation = orient;
549 logfont.lfWeight = weight;
550 logfont.lfItalic = italic;
551 logfont.lfUnderline = underline;
552 logfont.lfStrikeOut = strikeout;
553 logfont.lfCharSet = charset;
554 logfont.lfOutPrecision = outpres;
555 logfont.lfClipPrecision = clippres;
556 logfont.lfQuality = quality;
557 logfont.lfPitchAndFamily = pitch;
560 lstrcpynW(logfont.lfFaceName, name,
561 sizeof(logfont.lfFaceName) / sizeof(WCHAR));
563 logfont.lfFaceName[0] = '\0';
565 return CreateFontIndirectW( &logfont );
569 /***********************************************************************
572 * If the driver supports vector fonts we create a gdi font first and
573 * then call the driver to give it a chance to supply its own device
574 * font. If the driver wants to do this it returns TRUE and we can
575 * delete the gdi font, if the driver wants to use the gdi font it
576 * should return FALSE, to signal an error return GDI_ERROR. For
577 * drivers that don't support vector fonts they must supply their own
580 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc )
583 DC *dc = get_dc_ptr( hdc );
587 if (!GDI_inc_ref_count( handle ))
589 release_dc_ptr( dc );
593 if (dc->hFont != handle || dc->gdiFont == NULL)
595 if(GetDeviceCaps(dc->hSelf, TEXTCAPS) & TC_VA_ABLE)
597 FONTOBJ *font = GDI_GetObjPtr( handle, FONT_MAGIC ); /* to grab the GDI lock (FIXME) */
598 dc->gdiFont = WineEngCreateFontInstance(dc, handle);
599 if (font) GDI_ReleaseObj( handle );
603 if (dc->funcs->pSelectFont) ret = dc->funcs->pSelectFont( dc->physDev, handle, dc->gdiFont );
605 if (ret && dc->gdiFont) dc->gdiFont = 0;
607 if (ret == HGDI_ERROR)
609 GDI_dec_ref_count( handle );
610 ret = 0; /* SelectObject returns 0 on error */
616 GDI_dec_ref_count( ret );
618 release_dc_ptr( dc );
623 /***********************************************************************
626 static INT FONT_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
631 FONT_LogFontWTo16( &font->logfont, &lf16 );
633 if (count > sizeof(LOGFONT16)) count = sizeof(LOGFONT16);
634 memcpy( buffer, &lf16, count );
638 /***********************************************************************
641 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
648 FONT_LogFontWToA( &font->logfont, &lfA );
650 if (count > sizeof(lfA)) count = sizeof(lfA);
651 memcpy( buffer, &lfA, count );
655 /***********************************************************************
658 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
662 return sizeof(LOGFONTW);
663 if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
664 memcpy( buffer, &font->logfont, count );
669 /***********************************************************************
672 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj )
674 WineEngDestroyFontInstance( handle );
675 return GDI_FreeObject( handle, obj );
679 /***********************************************************************
680 * FONT_EnumInstance16
682 * Called by the device driver layer to pass font info
683 * down to the application.
685 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
686 * We have to use other types because of the FONTENUMPROCW definition.
688 static INT CALLBACK FONT_EnumInstance16( const LOGFONTW *plf, const TEXTMETRICW *ptm,
689 DWORD fType, LPARAM lp )
691 fontEnum16 *pfe = (fontEnum16*)lp;
695 if( pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
696 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet )
701 FONT_EnumLogFontExWTo16((const ENUMLOGFONTEXW *)plf, pfe->lpLogFont);
702 FONT_NewTextMetricExWTo16((const NEWTEXTMETRICEXW *)ptm, pfe->lpTextMetric);
703 pfe->dwFlags |= ENUM_CALLED;
704 DC_ReleaseDCPtr( pfe->dc ); /* release the GDI lock */
706 args[6] = SELECTOROF(pfe->segLogFont);
707 args[5] = OFFSETOF(pfe->segLogFont);
708 args[4] = SELECTOROF(pfe->segTextMetric);
709 args[3] = OFFSETOF(pfe->segTextMetric);
711 args[1] = HIWORD(pfe->lpData);
712 args[0] = LOWORD(pfe->lpData);
713 WOWCallback16Ex( (DWORD)pfe->lpEnumFunc, WCB16_PASCAL, sizeof(args), args, &result );
714 ret = LOWORD(result);
716 /* get the lock again and make sure the DC is still valid */
717 dc = DC_GetDCPtr( pfe->hdc );
718 if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
720 if (dc) DC_ReleaseDCPtr( dc );
721 pfe->hdc = 0; /* make sure we don't try to release it later on */
729 /***********************************************************************
732 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
733 * We have to use other types because of the FONTENUMPROCW definition.
735 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
736 DWORD fType, LPARAM lp )
738 fontEnum32 *pfe = (fontEnum32*)lp;
742 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
743 if((pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
744 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
745 (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
747 /* convert font metrics */
748 ENUMLOGFONTEXA logfont;
749 NEWTEXTMETRICEXA tmA;
751 pfe->dwFlags |= ENUM_CALLED;
752 if (!(pfe->dwFlags & ENUM_UNICODE))
754 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
755 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
756 plf = (LOGFONTW *)&logfont.elfLogFont;
757 ptm = (TEXTMETRICW *)&tmA;
759 DC_ReleaseDCPtr( pfe->dc ); /* release the GDI lock */
761 ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
763 /* get the lock again and make sure the DC is still valid */
764 dc = DC_GetDCPtr( pfe->hdc );
765 if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
767 if (dc) DC_ReleaseDCPtr( dc );
768 pfe->hdc = 0; /* make sure we don't try to release it later on */
776 /***********************************************************************
777 * EnumFontFamiliesEx (GDI.613)
779 INT16 WINAPI EnumFontFamiliesEx16( HDC16 hDC, LPLOGFONT16 plf,
780 FONTENUMPROC16 efproc, LPARAM lParam,
785 DC* dc = DC_GetDCPtr( HDC_32(hDC) );
786 NEWTEXTMETRICEX16 tm16;
787 ENUMLOGFONTEX16 lf16;
792 FONT_LogFont16ToW(plf, &lfW);
794 fe16.hdc = HDC_32(hDC);
796 fe16.physDev = dc->physDev;
797 fe16.lpLogFontParam = plf;
798 fe16.lpEnumFunc = efproc;
799 fe16.lpData = lParam;
800 fe16.lpTextMetric = &tm16;
801 fe16.lpLogFont = &lf16;
802 fe16.segTextMetric = MapLS( &tm16 );
803 fe16.segLogFont = MapLS( &lf16 );
806 enum_gdi_fonts = GetDeviceCaps(fe16.hdc, TEXTCAPS) & TC_VA_ABLE;
808 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
815 ret = WineEngEnumFonts( &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
816 fe16.dwFlags &= ~ENUM_CALLED;
817 if (ret && dc->funcs->pEnumDeviceFonts) {
818 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
819 if(fe16.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
823 UnMapLS( fe16.segTextMetric );
824 UnMapLS( fe16.segLogFont );
825 if (fe16.dc) DC_ReleaseDCPtr( fe16.dc );
829 /***********************************************************************
830 * FONT_EnumFontFamiliesEx
832 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf,
833 FONTENUMPROCW efproc,
834 LPARAM lParam, DWORD dwUnicode)
837 DC *dc = DC_GetDCPtr( hDC );
843 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName),
845 fe32.lpLogFontParam = plf;
846 fe32.lpEnumFunc = efproc;
847 fe32.lpData = lParam;
848 fe32.dwFlags = dwUnicode;
851 fe32.physDev = dc->physDev;
853 enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE;
855 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
862 ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
863 fe32.dwFlags &= ~ENUM_CALLED;
864 if (ret && dc->funcs->pEnumDeviceFonts) {
865 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, plf, FONT_EnumInstance, (LPARAM)&fe32 );
866 if(fe32.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
870 if (fe32.dc) DC_ReleaseDCPtr( fe32.dc );
874 /***********************************************************************
875 * EnumFontFamiliesExW (GDI32.@)
877 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
878 FONTENUMPROCW efproc,
879 LPARAM lParam, DWORD dwFlags )
881 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, ENUM_UNICODE );
884 /***********************************************************************
885 * EnumFontFamiliesExA (GDI32.@)
887 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
888 FONTENUMPROCA efproc,
889 LPARAM lParam, DWORD dwFlags)
892 FONT_LogFontAToW( plf, &lfW );
894 return FONT_EnumFontFamiliesEx( hDC, &lfW, (FONTENUMPROCW)efproc, lParam, 0);
897 /***********************************************************************
898 * EnumFontFamilies (GDI.330)
900 INT16 WINAPI EnumFontFamilies16( HDC16 hDC, LPCSTR lpFamily,
901 FONTENUMPROC16 efproc, LPARAM lpData )
905 lf.lfCharSet = DEFAULT_CHARSET;
908 if (!*lpFamily) return 1;
909 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
911 else lf.lfFaceName[0] = '\0';
913 return EnumFontFamiliesEx16( hDC, &lf, efproc, lpData, 0 );
916 /***********************************************************************
917 * EnumFontFamiliesA (GDI32.@)
919 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
920 FONTENUMPROCA efproc, LPARAM lpData )
924 lf.lfCharSet = DEFAULT_CHARSET;
927 if (!*lpFamily) return 1;
928 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
930 else lf.lfFaceName[0] = lf.lfFaceName[1] = '\0';
932 return EnumFontFamiliesExA( hDC, &lf, efproc, lpData, 0 );
935 /***********************************************************************
936 * EnumFontFamiliesW (GDI32.@)
938 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
939 FONTENUMPROCW efproc, LPARAM lpData )
943 lf.lfCharSet = DEFAULT_CHARSET;
946 if (!*lpFamily) return 1;
947 lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
949 else lf.lfFaceName[0] = 0;
951 return EnumFontFamiliesExW( hDC, &lf, efproc, lpData, 0 );
954 /***********************************************************************
957 INT16 WINAPI EnumFonts16( HDC16 hDC, LPCSTR lpName, FONTENUMPROC16 efproc,
960 return EnumFontFamilies16( hDC, lpName, efproc, lpData );
963 /***********************************************************************
964 * EnumFontsA (GDI32.@)
966 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
969 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
972 /***********************************************************************
973 * EnumFontsW (GDI32.@)
975 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
978 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
982 /***********************************************************************
983 * GetTextCharacterExtra (GDI32.@)
985 INT WINAPI GetTextCharacterExtra( HDC hdc )
988 DC *dc = DC_GetDCPtr( hdc );
989 if (!dc) return 0x80000000;
991 DC_ReleaseDCPtr( dc );
996 /***********************************************************************
997 * SetTextCharacterExtra (GDI32.@)
999 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
1002 DC * dc = DC_GetDCPtr( hdc );
1003 if (!dc) return 0x80000000;
1004 if (dc->funcs->pSetTextCharacterExtra)
1005 prev = dc->funcs->pSetTextCharacterExtra( dc->physDev, extra );
1008 prev = dc->charExtra;
1009 dc->charExtra = extra;
1011 DC_ReleaseDCPtr( dc );
1016 /***********************************************************************
1017 * SetTextJustification (GDI32.@)
1019 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
1022 DC * dc = DC_GetDCPtr( hdc );
1023 if (!dc) return FALSE;
1024 if (dc->funcs->pSetTextJustification)
1025 ret = dc->funcs->pSetTextJustification( dc->physDev, extra, breaks );
1028 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
1029 if (!extra) breaks = 0;
1032 dc->breakExtra = extra / breaks;
1033 dc->breakRem = extra - (breaks * dc->breakExtra);
1041 DC_ReleaseDCPtr( dc );
1046 /***********************************************************************
1047 * GetTextFaceA (GDI32.@)
1049 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
1051 INT res = GetTextFaceW(hdc, 0, NULL);
1052 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
1053 GetTextFaceW( hdc, res, nameW );
1057 if (count && !WideCharToMultiByte( CP_ACP, 0, nameW, -1, name, count, NULL, NULL))
1062 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
1063 HeapFree( GetProcessHeap(), 0, nameW );
1067 /***********************************************************************
1068 * GetTextFaceW (GDI32.@)
1070 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
1075 DC * dc = DC_GetDCPtr( hdc );
1079 ret = WineEngGetTextFace(dc->gdiFont, count, name);
1080 else if ((font = (FONTOBJ *) GDI_GetObjPtr( dc->hFont, FONT_MAGIC )))
1084 lstrcpynW( name, font->logfont.lfFaceName, count );
1085 ret = strlenW(name);
1087 else ret = strlenW(font->logfont.lfFaceName) + 1;
1088 GDI_ReleaseObj( dc->hFont );
1090 DC_ReleaseDCPtr( dc );
1095 /***********************************************************************
1096 * GetTextExtentPoint32A (GDI32.@)
1098 * See GetTextExtentPoint32W.
1100 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
1105 LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1108 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
1109 HeapFree( GetProcessHeap(), 0, p );
1112 TRACE("(%p %s %d %p): returning %d x %d\n",
1113 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
1118 /***********************************************************************
1119 * GetTextExtentPoint32W [GDI32.@]
1121 * Computes width/height for a string.
1123 * Computes width and height of the specified string.
1129 BOOL WINAPI GetTextExtentPoint32W(
1130 HDC hdc, /* [in] Handle of device context */
1131 LPCWSTR str, /* [in] Address of text string */
1132 INT count, /* [in] Number of characters in string */
1133 LPSIZE size) /* [out] Address of structure for string size */
1135 return GetTextExtentExPointW(hdc, str, count, 0, NULL, NULL, size);
1138 /***********************************************************************
1139 * GetTextExtentExPointI [GDI32.@]
1141 * Computes width and height of the array of glyph indices.
1144 * hdc [I] Handle of device context.
1145 * indices [I] Glyph index array.
1146 * count [I] Number of glyphs in array.
1147 * max_ext [I] Maximum width in glyphs.
1148 * nfit [O] Maximum number of characters.
1149 * dxs [O] Partial string widths.
1150 * size [O] Returned string size.
1156 BOOL WINAPI GetTextExtentExPointI( HDC hdc, const WORD *indices, INT count, INT max_ext,
1157 LPINT nfit, LPINT dxs, LPSIZE size )
1160 DC * dc = DC_GetDCPtr( hdc );
1161 if (!dc) return FALSE;
1164 ret = WineEngGetTextExtentExPointI(dc->gdiFont, indices, count, max_ext, nfit, dxs, size);
1165 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1166 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1167 size->cx += count * dc->charExtra;
1169 else if(dc->funcs->pGetTextExtentExPoint) {
1170 FIXME("calling GetTextExtentExPoint\n");
1171 ret = dc->funcs->pGetTextExtentExPoint( dc->physDev, (LPCWSTR)indices,
1172 count, max_ext, nfit, dxs, size );
1175 DC_ReleaseDCPtr( dc );
1177 TRACE("(%p %p %d %p): returning %d x %d\n",
1178 hdc, indices, count, size, size->cx, size->cy );
1182 /***********************************************************************
1183 * GetTextExtentPointI [GDI32.@]
1185 * Computes width and height of the array of glyph indices.
1188 * hdc [I] Handle of device context.
1189 * indices [I] Glyph index array.
1190 * count [I] Number of glyphs in array.
1191 * size [O] Returned string size.
1197 BOOL WINAPI GetTextExtentPointI( HDC hdc, const WORD *indices, INT count, LPSIZE size )
1199 return GetTextExtentExPointI( hdc, indices, count, 0, NULL, NULL, size );
1203 /***********************************************************************
1204 * GetTextExtentPointA (GDI32.@)
1206 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
1209 TRACE("not bug compatible.\n");
1210 return GetTextExtentPoint32A( hdc, str, count, size );
1213 /***********************************************************************
1214 * GetTextExtentPointW (GDI32.@)
1216 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1219 TRACE("not bug compatible.\n");
1220 return GetTextExtentPoint32W( hdc, str, count, size );
1224 /***********************************************************************
1225 * GetTextExtentExPointA (GDI32.@)
1227 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1228 INT maxExt, LPINT lpnFit,
1229 LPINT alpDx, LPSIZE size )
1237 NULL == (walpDx = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT))))
1240 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1241 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
1244 INT n = lpnFit ? *lpnFit : wlen;
1246 for(i = 0, j = 0; i < n; i++, j++)
1248 alpDx[j] = walpDx[i];
1249 if (IsDBCSLeadByte(str[j])) alpDx[++j] = walpDx[i];
1252 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1253 HeapFree( GetProcessHeap(), 0, p );
1254 HeapFree( GetProcessHeap(), 0, walpDx );
1259 /***********************************************************************
1260 * GetTextExtentExPointW (GDI32.@)
1262 * Return the size of the string as it would be if it was output properly by
1265 * This should include
1266 * - Intercharacter spacing
1267 * - justification spacing (not yet done)
1268 * - kerning? see below
1270 * Kerning. Since kerning would be carried out by the rendering code it should
1271 * be done by the driver. However they don't support it yet. Also I am not
1272 * yet persuaded that (certainly under Win95) any kerning is actually done.
1274 * str: According to MSDN this should be null-terminated. That is not true; a
1275 * null will not terminate it early.
1276 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1277 * than count. I have seen it be either the size of the full string or
1278 * 1 less than the size of the full string. I have not seen it bear any
1279 * resemblance to the portion that would fit.
1280 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1281 * trailing intercharacter spacing and any trailing justification.
1284 * Currently we do this by measuring each character etc. We should do it by
1285 * passing the request to the driver, perhaps by extending the
1286 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1287 * thinking about kerning issues and rounding issues in the justification.
1290 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1291 INT maxExt, LPINT lpnFit,
1292 LPINT alpDx, LPSIZE size )
1300 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1302 dc = DC_GetDCPtr(hdc);
1306 GetTextMetricsW(hdc, &tm);
1308 /* If we need to calculate nFit, then we need the partial extents even if
1309 the user hasn't provided us with an array. */
1312 dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]);
1315 DC_ReleaseDCPtr(dc);
1316 SetLastError(ERROR_OUTOFMEMORY);
1324 ret = WineEngGetTextExtentExPoint(dc->gdiFont, str, count,
1325 0, NULL, dxs, size);
1326 else if (dc->funcs->pGetTextExtentExPoint)
1327 ret = dc->funcs->pGetTextExtentExPoint(dc->physDev, str, count,
1328 0, NULL, dxs, size);
1330 /* Perform device size to world size transformations. */
1333 INT extra = dc->charExtra,
1334 breakExtra = dc->breakExtra,
1335 breakRem = dc->breakRem,
1340 for (i = 0; i < count; ++i)
1342 dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
1343 dxs[i] += (i+1) * extra;
1344 if (count > 1 && (breakExtra || breakRem) && str[i] == tm.tmBreakChar)
1346 dxs[i] += breakExtra;
1353 if (dxs[i] <= maxExt)
1356 breakRem = dc->breakRem;
1358 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1359 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1361 if (!dxs && count > 1 && (breakExtra || breakRem))
1363 for (i = 0; i < count; i++)
1365 if (str[i] == tm.tmBreakChar)
1367 size->cx += breakExtra;
1382 HeapFree(GetProcessHeap(), 0, dxs);
1384 DC_ReleaseDCPtr( dc );
1386 TRACE("returning %d %d x %d\n",nFit,size->cx,size->cy);
1390 /***********************************************************************
1391 * GetTextMetricsA (GDI32.@)
1393 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1397 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1398 FONT_TextMetricWToA( &tm32, metrics );
1402 /***********************************************************************
1403 * GetTextMetricsW (GDI32.@)
1405 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1408 DC * dc = DC_GetDCPtr( hdc );
1409 if (!dc) return FALSE;
1412 ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1413 else if (dc->funcs->pGetTextMetrics)
1414 ret = dc->funcs->pGetTextMetrics( dc->physDev, metrics );
1418 /* device layer returns values in device units
1419 * therefore we have to convert them to logical */
1421 metrics->tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1422 metrics->tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1424 #define WDPTOLP(x) ((x<0)? \
1425 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1426 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1427 #define HDPTOLP(y) ((y<0)? \
1428 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1429 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1431 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1432 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1433 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1434 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1435 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1436 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1437 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1438 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1442 TRACE("text metrics:\n"
1443 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1444 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1445 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1446 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1447 " PitchAndFamily = %02x\n"
1448 " --------------------\n"
1449 " InternalLeading = %i\n"
1453 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1454 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1455 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1456 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1457 metrics->tmPitchAndFamily,
1458 metrics->tmInternalLeading,
1461 metrics->tmHeight );
1463 DC_ReleaseDCPtr( dc );
1468 /***********************************************************************
1469 * GetOutlineTextMetrics [GDI.308] Gets metrics for TrueType fonts.
1472 * lpOTM should be LPOUTLINETEXTMETRIC
1475 * Success: Non-zero or size of required buffer
1478 UINT16 WINAPI GetOutlineTextMetrics16(
1479 HDC16 hdc, /* [in] Handle of device context */
1480 UINT16 cbData, /* [in] Size of metric data array */
1481 LPOUTLINETEXTMETRIC16 lpOTM) /* [out] Address of metric data array */
1483 FIXME("(%04x,%04x,%p): stub\n", hdc,cbData,lpOTM);
1488 /***********************************************************************
1489 * GetOutlineTextMetricsA (GDI32.@)
1490 * Gets metrics for TrueType fonts.
1493 * If the supplied buffer isn't big enough Windows partially fills it up to
1494 * its given length and returns that length.
1497 * Success: Non-zero or size of required buffer
1500 UINT WINAPI GetOutlineTextMetricsA(
1501 HDC hdc, /* [in] Handle of device context */
1502 UINT cbData, /* [in] Size of metric data array */
1503 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1505 char buf[512], *ptr;
1507 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1508 OUTLINETEXTMETRICA *output = lpOTM;
1511 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1513 if(ret > sizeof(buf))
1514 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1515 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1517 needed = sizeof(OUTLINETEXTMETRICA);
1518 if(lpOTMW->otmpFamilyName)
1519 needed += WideCharToMultiByte(CP_ACP, 0,
1520 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1521 NULL, 0, NULL, NULL);
1522 if(lpOTMW->otmpFaceName)
1523 needed += WideCharToMultiByte(CP_ACP, 0,
1524 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1525 NULL, 0, NULL, NULL);
1526 if(lpOTMW->otmpStyleName)
1527 needed += WideCharToMultiByte(CP_ACP, 0,
1528 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1529 NULL, 0, NULL, NULL);
1530 if(lpOTMW->otmpFullName)
1531 needed += WideCharToMultiByte(CP_ACP, 0,
1532 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1533 NULL, 0, NULL, NULL);
1540 TRACE("needed = %d\n", needed);
1542 /* Since the supplied buffer isn't big enough, we'll alloc one
1543 that is and memcpy the first cbData bytes into the lpOTM at
1545 output = HeapAlloc(GetProcessHeap(), 0, needed);
1547 ret = output->otmSize = min(needed, cbData);
1548 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1549 output->otmFiller = 0;
1550 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1551 output->otmfsSelection = lpOTMW->otmfsSelection;
1552 output->otmfsType = lpOTMW->otmfsType;
1553 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1554 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1555 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1556 output->otmEMSquare = lpOTMW->otmEMSquare;
1557 output->otmAscent = lpOTMW->otmAscent;
1558 output->otmDescent = lpOTMW->otmDescent;
1559 output->otmLineGap = lpOTMW->otmLineGap;
1560 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1561 output->otmsXHeight = lpOTMW->otmsXHeight;
1562 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1563 output->otmMacAscent = lpOTMW->otmMacAscent;
1564 output->otmMacDescent = lpOTMW->otmMacDescent;
1565 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1566 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1567 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1568 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1569 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1570 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1571 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1572 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1573 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1574 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1577 ptr = (char*)(output + 1);
1578 left = needed - sizeof(*output);
1580 if(lpOTMW->otmpFamilyName) {
1581 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1582 len = WideCharToMultiByte(CP_ACP, 0,
1583 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1584 ptr, left, NULL, NULL);
1588 output->otmpFamilyName = 0;
1590 if(lpOTMW->otmpFaceName) {
1591 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1592 len = WideCharToMultiByte(CP_ACP, 0,
1593 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1594 ptr, left, NULL, NULL);
1598 output->otmpFaceName = 0;
1600 if(lpOTMW->otmpStyleName) {
1601 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1602 len = WideCharToMultiByte(CP_ACP, 0,
1603 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1604 ptr, left, NULL, NULL);
1608 output->otmpStyleName = 0;
1610 if(lpOTMW->otmpFullName) {
1611 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1612 len = WideCharToMultiByte(CP_ACP, 0,
1613 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1614 ptr, left, NULL, NULL);
1617 output->otmpFullName = 0;
1621 if(output != lpOTM) {
1622 memcpy(lpOTM, output, cbData);
1623 HeapFree(GetProcessHeap(), 0, output);
1625 /* check if the string offsets really fit into the provided size */
1626 /* FIXME: should we check string length as well? */
1627 /* make sure that we don't read/write beyond the provided buffer */
1628 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(LPSTR))
1630 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1631 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1634 /* make sure that we don't read/write beyond the provided buffer */
1635 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(LPSTR))
1637 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1638 lpOTM->otmpFaceName = 0; /* doesn't fit */
1641 /* make sure that we don't read/write beyond the provided buffer */
1642 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(LPSTR))
1644 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1645 lpOTM->otmpStyleName = 0; /* doesn't fit */
1648 /* make sure that we don't read/write beyond the provided buffer */
1649 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(LPSTR))
1651 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1652 lpOTM->otmpFullName = 0; /* doesn't fit */
1657 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1658 HeapFree(GetProcessHeap(), 0, lpOTMW);
1664 /***********************************************************************
1665 * GetOutlineTextMetricsW [GDI32.@]
1667 UINT WINAPI GetOutlineTextMetricsW(
1668 HDC hdc, /* [in] Handle of device context */
1669 UINT cbData, /* [in] Size of metric data array */
1670 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1672 DC *dc = DC_GetDCPtr( hdc );
1673 OUTLINETEXTMETRICW *output = lpOTM;
1676 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1680 ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, output);
1683 output = HeapAlloc(GetProcessHeap(), 0, ret);
1684 WineEngGetOutlineTextMetrics(dc->gdiFont, ret, output);
1687 #define WDPTOLP(x) ((x<0)? \
1688 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1689 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1690 #define HDPTOLP(y) ((y<0)? \
1691 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1692 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1694 output->otmTextMetrics.tmHeight = HDPTOLP(output->otmTextMetrics.tmHeight);
1695 output->otmTextMetrics.tmAscent = HDPTOLP(output->otmTextMetrics.tmAscent);
1696 output->otmTextMetrics.tmDescent = HDPTOLP(output->otmTextMetrics.tmDescent);
1697 output->otmTextMetrics.tmInternalLeading = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1698 output->otmTextMetrics.tmExternalLeading = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1699 output->otmTextMetrics.tmAveCharWidth = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1700 output->otmTextMetrics.tmMaxCharWidth = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1701 output->otmTextMetrics.tmOverhang = WDPTOLP(output->otmTextMetrics.tmOverhang);
1702 output->otmAscent = HDPTOLP(output->otmAscent);
1703 output->otmDescent = HDPTOLP(output->otmDescent);
1704 output->otmLineGap = HDPTOLP(output->otmLineGap);
1705 output->otmsCapEmHeight = HDPTOLP(output->otmsCapEmHeight);
1706 output->otmsXHeight = HDPTOLP(output->otmsXHeight);
1707 output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1708 output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1709 output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1710 output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1711 output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1712 output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1713 output->otmMacLineGap = HDPTOLP(output->otmMacLineGap);
1714 output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1715 output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1716 output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1717 output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1718 output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1719 output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1720 output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1721 output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1722 output->otmsStrikeoutSize = HDPTOLP(output->otmsStrikeoutSize);
1723 output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1724 output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1725 output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1728 if(output != lpOTM) {
1729 memcpy(lpOTM, output, cbData);
1730 HeapFree(GetProcessHeap(), 0, output);
1736 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1737 but really this should just be a return 0. */
1739 ret = sizeof(*lpOTM);
1744 memset(lpOTM, 0, ret);
1745 lpOTM->otmSize = sizeof(*lpOTM);
1746 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1748 Further fill of the structure not implemented,
1749 Needs real values for the structure members
1754 DC_ReleaseDCPtr(dc);
1759 /***********************************************************************
1760 * GetCharWidthW (GDI32.@)
1761 * GetCharWidth32W (GDI32.@)
1763 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1768 DC * dc = DC_GetDCPtr( hdc );
1769 if (!dc) return FALSE;
1772 ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1773 else if (dc->funcs->pGetCharWidth)
1774 ret = dc->funcs->pGetCharWidth( dc->physDev, firstChar, lastChar, buffer);
1778 /* convert device units to logical */
1779 for( i = firstChar; i <= lastChar; i++, buffer++ )
1780 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1783 DC_ReleaseDCPtr( dc );
1788 /***********************************************************************
1789 * GetCharWidthA (GDI32.@)
1790 * GetCharWidth32A (GDI32.@)
1792 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1795 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1800 if(count <= 0) return FALSE;
1802 str = HeapAlloc(GetProcessHeap(), 0, count);
1803 for(i = 0; i < count; i++)
1804 str[i] = (BYTE)(firstChar + i);
1806 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1808 for(i = 0; i < wlen; i++)
1810 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1818 HeapFree(GetProcessHeap(), 0, str);
1819 HeapFree(GetProcessHeap(), 0, wstr);
1825 /***********************************************************************
1826 * ExtTextOutA (GDI32.@)
1830 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1831 const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1839 if (flags & ETO_GLYPH_INDEX)
1840 return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
1842 p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
1845 unsigned int i = 0, j = 0;
1847 lpDxW = HeapAlloc( GetProcessHeap(), 0, wlen*sizeof(INT));
1849 if(IsDBCSLeadByteEx(codepage, str[i])) {
1850 lpDxW[j++] = lpDx[i] + lpDx[i+1];
1853 lpDxW[j++] = lpDx[i];
1859 ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1861 HeapFree( GetProcessHeap(), 0, p );
1862 HeapFree( GetProcessHeap(), 0, lpDxW );
1867 /***********************************************************************
1868 * ExtTextOutW (GDI32.@)
1870 * Draws text using the currently selected font, background color, and text color.
1874 * x,y [I] coordinates of string
1876 * ETO_GRAYED - undocumented on MSDN
1877 * ETO_OPAQUE - use background color for fill the rectangle
1878 * ETO_CLIPPED - clipping text to the rectangle
1879 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1880 * than encoded characters. Implies ETO_IGNORELANGUAGE
1881 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1882 * Affects BiDi ordering
1883 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1884 * ETO_PDY - unimplemented
1885 * ETO_NUMERICSLATIN - unimplemented always assumed -
1886 * do not translate numbers into locale representations
1887 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1888 * lprect [I] dimensions for clipping or/and opaquing
1889 * str [I] text string
1890 * count [I] number of symbols in string
1891 * lpDx [I] optional parameter with distance between drawing characters
1897 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1898 const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1901 LPWSTR reordered_str = (LPWSTR)str;
1902 WORD *glyphs = NULL;
1903 UINT align = GetTextAlign( hdc );
1907 double cosEsc, sinEsc;
1908 INT *deltas = NULL, char_extra;
1911 BOOL done_extents = FALSE;
1912 INT width = 0, xwidth = 0, ywidth = 0;
1914 DC * dc = get_dc_ptr( hdc );
1917 if (!dc) return FALSE;
1919 breakRem = dc->breakRem;
1921 if (flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY))
1922 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY unimplemented\n");
1924 if (!dc->funcs->pExtTextOut && !PATH_IsPathOpen(dc->path))
1926 release_dc_ptr( dc );
1931 type = GetObjectType(hdc);
1932 if(type == OBJ_METADC || type == OBJ_ENHMETADC)
1934 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, flags, lprect, str, count, lpDx);
1935 release_dc_ptr( dc );
1940 flags &= ~ETO_CLIPPED;
1942 if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && count > 0 )
1944 reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1946 BIDI_Reorder( str, count, GCP_REORDER,
1947 ((flags&ETO_RTLREADING)!=0 || (GetTextAlign(hdc)&TA_RTLREADING)!=0)?
1948 WINE_GCPW_FORCE_RTL:WINE_GCPW_FORCE_LTR,
1949 reordered_str, count, NULL );
1951 flags |= ETO_IGNORELANGUAGE;
1954 TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc, x, y, flags,
1955 lprect, debugstr_wn(str, count), count, lpDx);
1957 if(flags & ETO_GLYPH_INDEX)
1958 glyphs = reordered_str;
1961 TRACE("rect: %d,%d - %d,%d\n", lprect->left, lprect->top, lprect->right,
1963 TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
1965 if(align & TA_UPDATECP)
1967 GetCurrentPositionEx( hdc, &pt );
1972 GetTextMetricsW(hdc, &tm);
1973 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1975 if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
1976 lf.lfEscapement = 0;
1978 if(lf.lfEscapement != 0)
1980 cosEsc = cos(lf.lfEscapement * M_PI / 1800);
1981 sinEsc = sin(lf.lfEscapement * M_PI / 1800);
1989 if(flags & (ETO_CLIPPED | ETO_OPAQUE))
1993 if(flags & ETO_GLYPH_INDEX)
1994 GetTextExtentPointI(hdc, glyphs, count, &sz);
1996 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1998 done_extents = TRUE;
2001 rc.right = x + sz.cx;
2002 rc.bottom = y + sz.cy;
2009 LPtoDP(hdc, (POINT*)&rc, 2);
2011 if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
2012 if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
2015 if ((flags & ETO_OPAQUE) && !PATH_IsPathOpen(dc->path))
2016 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
2026 LPtoDP(hdc, &pt, 1);
2030 char_extra = GetTextCharacterExtra(hdc);
2031 if(char_extra || dc->breakExtra || breakRem || lpDx || lf.lfEscapement != 0)
2035 deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT));
2036 for(i = 0; i < count; i++)
2038 if(lpDx && (flags & ETO_PDY))
2039 deltas[i] = lpDx[i*2] + char_extra;
2041 deltas[i] = lpDx[i] + char_extra;
2044 if(flags & ETO_GLYPH_INDEX)
2045 GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
2047 GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
2049 deltas[i] = tmpsz.cx;
2052 if (!(flags & ETO_GLYPH_INDEX) && (dc->breakExtra || breakRem) && reordered_str[i] == tm.tmBreakChar)
2054 deltas[i] = deltas[i] + dc->breakExtra;
2061 deltas[i] = INTERNAL_XWSTODS(dc, deltas[i]);
2069 if(flags & ETO_GLYPH_INDEX)
2070 GetTextExtentPointI(hdc, glyphs, count, &sz);
2072 GetTextExtentPointW(hdc, reordered_str, count, &sz);
2073 done_extents = TRUE;
2075 width = INTERNAL_XWSTODS(dc, sz.cx);
2077 xwidth = width * cosEsc;
2078 ywidth = width * sinEsc;
2080 tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
2081 tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
2082 switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
2085 if (align & TA_UPDATECP)
2089 DPtoLP(hdc, &pt, 1);
2090 MoveToEx(hdc, pt.x, pt.y, NULL);
2102 if (align & TA_UPDATECP)
2106 DPtoLP(hdc, &pt, 1);
2107 MoveToEx(hdc, pt.x, pt.y, NULL);
2112 switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
2115 y += tm.tmAscent * cosEsc;
2116 x += tm.tmAscent * sinEsc;
2120 y -= tm.tmDescent * cosEsc;
2121 x -= tm.tmDescent * sinEsc;
2128 if (GetBkMode(hdc) != TRANSPARENT && !PATH_IsPathOpen(dc->path))
2130 if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
2132 if(!(flags & ETO_OPAQUE) || x < rc.left || x + width >= rc.right ||
2133 y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
2137 rc.right = x + width;
2138 rc.top = y - tm.tmAscent;
2139 rc.bottom = y + tm.tmDescent;
2140 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
2145 if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
2147 HFONT orig_font = dc->hFont, cur_font;
2149 INT span = 0, *offsets = NULL;
2152 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2153 for(i = 0; i < count; i++)
2155 WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
2156 if(cur_font != dc->hFont)
2161 offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
2166 for(j = 1; j < count; j++)
2168 GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
2169 offsets[j] = offsets[j-1] + INTERNAL_XWSTODS(dc, tmpsz.cx);
2174 for(j = 1; j < count; j++)
2175 offsets[j] = offsets[j-1] + deltas[j];
2180 if (PATH_IsPathOpen(dc->path))
2181 ret = PATH_ExtTextOut(dc, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
2182 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2183 glyphs, span, deltas ? deltas + i - span : NULL);
2185 dc->funcs->pExtTextOut(dc->physDev, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
2186 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2187 glyphs, span, deltas ? deltas + i - span : NULL);
2190 SelectObject(hdc, cur_font);
2192 glyphs[span++] = glyph;
2196 if (PATH_IsPathOpen(dc->path))
2197 ret = PATH_ExtTextOut(dc, x + (offsets ? offsets[count - span] * cosEsc : 0),
2198 y - (offsets ? offsets[count - span] * sinEsc : 0),
2199 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2200 glyphs, span, deltas ? deltas + count - span : NULL);
2202 ret = dc->funcs->pExtTextOut(dc->physDev, x + (offsets ? offsets[count - span] * cosEsc : 0),
2203 y - (offsets ? offsets[count - span] * sinEsc : 0),
2204 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2205 glyphs, span, deltas ? deltas + count - span : NULL);
2206 SelectObject(hdc, orig_font);
2207 HeapFree(GetProcessHeap(), 0, offsets);
2213 if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
2215 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2216 GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
2217 flags |= ETO_GLYPH_INDEX;
2220 if (PATH_IsPathOpen(dc->path))
2221 ret = PATH_ExtTextOut(dc, x, y, (flags & ~ETO_OPAQUE), &rc,
2222 glyphs ? glyphs : reordered_str, count, deltas);
2224 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, (flags & ~ETO_OPAQUE), &rc,
2225 glyphs ? glyphs : reordered_str, count, deltas);
2229 HeapFree(GetProcessHeap(), 0, deltas);
2230 if(glyphs != reordered_str)
2231 HeapFree(GetProcessHeap(), 0, glyphs);
2232 if(reordered_str != str)
2233 HeapFree(GetProcessHeap(), 0, reordered_str);
2235 release_dc_ptr( dc );
2237 if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2239 int underlinePos, strikeoutPos;
2240 int underlineWidth, strikeoutWidth;
2241 UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2242 OUTLINETEXTMETRICW* otm = NULL;
2247 underlineWidth = tm.tmAscent / 20 + 1;
2248 strikeoutPos = tm.tmAscent / 2;
2249 strikeoutWidth = underlineWidth;
2253 otm = HeapAlloc(GetProcessHeap(), 0, size);
2254 GetOutlineTextMetricsW(hdc, size, otm);
2255 underlinePos = otm->otmsUnderscorePosition;
2256 underlineWidth = otm->otmsUnderscoreSize;
2257 strikeoutPos = otm->otmsStrikeoutPosition;
2258 strikeoutWidth = otm->otmsStrikeoutSize;
2259 HeapFree(GetProcessHeap(), 0, otm);
2262 if (PATH_IsPathOpen(dc->path))
2266 HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2268 hbrush = SelectObject(hdc, hbrush);
2269 hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2273 pts[0].x = x - underlinePos * sinEsc;
2274 pts[0].y = y - underlinePos * cosEsc;
2275 pts[1].x = x + xwidth - underlinePos * sinEsc;
2276 pts[1].y = y - ywidth - underlinePos * cosEsc;
2277 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2278 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2279 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2280 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2281 pts[4].x = pts[0].x;
2282 pts[4].y = pts[0].y;
2283 DPtoLP(hdc, pts, 5);
2284 Polygon(hdc, pts, 5);
2289 pts[0].x = x - strikeoutPos * sinEsc;
2290 pts[0].y = y - strikeoutPos * cosEsc;
2291 pts[1].x = x + xwidth - strikeoutPos * sinEsc;
2292 pts[1].y = y - ywidth - strikeoutPos * cosEsc;
2293 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2294 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2295 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2296 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2297 pts[4].x = pts[0].x;
2298 pts[4].y = pts[0].y;
2299 DPtoLP(hdc, pts, 5);
2300 Polygon(hdc, pts, 5);
2303 SelectObject(hdc, hpen);
2304 hbrush = SelectObject(hdc, hbrush);
2305 DeleteObject(hbrush);
2309 POINT pts[2], oldpt;
2314 hpen = CreatePen(PS_SOLID, underlineWidth, GetTextColor(hdc));
2315 hpen = SelectObject(hdc, hpen);
2318 pts[1].x = x + xwidth;
2319 pts[1].y = y - ywidth;
2320 DPtoLP(hdc, pts, 2);
2321 MoveToEx(hdc, pts[0].x - underlinePos * sinEsc, pts[0].y - underlinePos * cosEsc, &oldpt);
2322 LineTo(hdc, pts[1].x - underlinePos * sinEsc, pts[1].y - underlinePos * cosEsc);
2323 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2324 DeleteObject(SelectObject(hdc, hpen));
2329 hpen = CreatePen(PS_SOLID, strikeoutWidth, GetTextColor(hdc));
2330 hpen = SelectObject(hdc, hpen);
2333 pts[1].x = x + xwidth;
2334 pts[1].y = y - ywidth;
2335 DPtoLP(hdc, pts, 2);
2336 MoveToEx(hdc, pts[0].x - strikeoutPos * sinEsc, pts[0].y - strikeoutPos * cosEsc, &oldpt);
2337 LineTo(hdc, pts[1].x - strikeoutPos * sinEsc, pts[1].y - strikeoutPos * cosEsc);
2338 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2339 DeleteObject(SelectObject(hdc, hpen));
2348 /***********************************************************************
2349 * TextOutA (GDI32.@)
2351 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2353 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2357 /***********************************************************************
2358 * TextOutW (GDI32.@)
2360 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2362 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2366 /***********************************************************************
2367 * PolyTextOutA (GDI32.@)
2371 BOOL WINAPI PolyTextOutA( HDC hdc, const POLYTEXTA *pptxt, INT cStrings )
2373 for (; cStrings>0; cStrings--, pptxt++)
2374 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2381 /***********************************************************************
2382 * PolyTextOutW (GDI32.@)
2384 * Draw several Strings
2390 BOOL WINAPI PolyTextOutW( HDC hdc, const POLYTEXTW *pptxt, INT cStrings )
2392 for (; cStrings>0; cStrings--, pptxt++)
2393 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2399 /* FIXME: all following APIs ******************************************/
2402 /***********************************************************************
2403 * SetMapperFlags (GDI32.@)
2405 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
2407 DC *dc = DC_GetDCPtr( hDC );
2410 if(dc->funcs->pSetMapperFlags)
2412 ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
2413 /* FIXME: ret is just a success flag, we should return a proper value */
2416 FIXME("(%p, 0x%08x): stub - harmless\n", hDC, dwFlag);
2417 DC_ReleaseDCPtr( dc );
2421 /***********************************************************************
2422 * GetAspectRatioFilterEx (GDI.486)
2424 BOOL16 WINAPI GetAspectRatioFilterEx16( HDC16 hdc, LPSIZE16 pAspectRatio )
2426 FIXME("(%04x, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2430 /***********************************************************************
2431 * GetAspectRatioFilterEx (GDI32.@)
2433 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2435 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2440 /***********************************************************************
2441 * GetCharABCWidthsA (GDI32.@)
2443 * See GetCharABCWidthsW.
2445 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2448 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
2453 if(count <= 0) return FALSE;
2455 str = HeapAlloc(GetProcessHeap(), 0, count);
2456 for(i = 0; i < count; i++)
2457 str[i] = (BYTE)(firstChar + i);
2459 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
2461 for(i = 0; i < wlen; i++)
2463 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2471 HeapFree(GetProcessHeap(), 0, str);
2472 HeapFree(GetProcessHeap(), 0, wstr);
2478 /******************************************************************************
2479 * GetCharABCWidthsW [GDI32.@]
2481 * Retrieves widths of characters in range.
2484 * hdc [I] Handle of device context
2485 * firstChar [I] First character in range to query
2486 * lastChar [I] Last character in range to query
2487 * abc [O] Address of character-width structure
2490 * Only works with TrueType fonts
2496 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2499 DC *dc = DC_GetDCPtr(hdc);
2503 if (!dc) return FALSE;
2507 DC_ReleaseDCPtr( dc );
2512 ret = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
2518 /* convert device units to logical */
2519 for( i = firstChar; i <= lastChar; i++, abc++ ) {
2520 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2521 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2522 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2527 DC_ReleaseDCPtr( dc );
2532 /******************************************************************************
2533 * GetCharABCWidthsI [GDI32.@]
2535 * Retrieves widths of characters in range.
2538 * hdc [I] Handle of device context
2539 * firstChar [I] First glyphs in range to query
2540 * count [I] Last glyphs in range to query
2541 * pgi [i] Array of glyphs to query
2542 * abc [O] Address of character-width structure
2545 * Only works with TrueType fonts
2551 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2552 LPWORD pgi, LPABC abc)
2554 DC *dc = DC_GetDCPtr(hdc);
2558 if (!dc) return FALSE;
2562 DC_ReleaseDCPtr( dc );
2567 ret = WineEngGetCharABCWidthsI( dc->gdiFont, firstChar, count, pgi, abc );
2573 /* convert device units to logical */
2574 for( i = 0; i < count; i++, abc++ ) {
2575 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2576 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2577 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2582 DC_ReleaseDCPtr( dc );
2587 /***********************************************************************
2588 * GetGlyphOutlineA (GDI32.@)
2590 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2591 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2592 LPVOID lpBuffer, const MAT2 *lpmat2 )
2598 if(!(fuFormat & GGO_GLYPH_INDEX)) {
2601 if(uChar > 0xff) { /* but, 2 bytes character only */
2603 mbchs[0] = (uChar & 0xff00) >> 8;
2604 mbchs[1] = (uChar & 0xff);
2607 mbchs[0] = (uChar & 0xff);
2609 p = FONT_mbtowc(hdc, mbchs, len, NULL, NULL);
2613 ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
2615 HeapFree(GetProcessHeap(), 0, p);
2619 /***********************************************************************
2620 * GetGlyphOutlineW (GDI32.@)
2622 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2623 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2624 LPVOID lpBuffer, const MAT2 *lpmat2 )
2626 DC *dc = DC_GetDCPtr(hdc);
2629 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2630 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2632 if(!dc) return GDI_ERROR;
2635 ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
2636 cbBuffer, lpBuffer, lpmat2);
2640 DC_ReleaseDCPtr( dc );
2645 /***********************************************************************
2646 * CreateScalableFontResourceA (GDI32.@)
2648 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2649 LPCSTR lpszResourceFile,
2650 LPCSTR lpszFontFile,
2651 LPCSTR lpszCurrentPath )
2655 /* fHidden=1 - only visible for the calling app, read-only, not
2656 * enumbered with EnumFonts/EnumFontFamilies
2657 * lpszCurrentPath can be NULL
2659 FIXME("(%d,%s,%s,%s): stub\n",
2660 fHidden, debugstr_a(lpszResourceFile), debugstr_a(lpszFontFile),
2661 debugstr_a(lpszCurrentPath) );
2663 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2664 if ((f = CreateFileA(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2666 SetLastError(ERROR_FILE_EXISTS);
2669 return FALSE; /* create failed */
2672 /***********************************************************************
2673 * CreateScalableFontResourceW (GDI32.@)
2675 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2676 LPCWSTR lpszResourceFile,
2677 LPCWSTR lpszFontFile,
2678 LPCWSTR lpszCurrentPath )
2680 FIXME("(%d,%p,%p,%p): stub\n",
2681 fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
2682 return FALSE; /* create failed */
2685 /*************************************************************************
2686 * GetKerningPairsA (GDI32.@)
2688 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2689 LPKERNINGPAIR kern_pairA )
2694 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2695 KERNINGPAIR *kern_pairW;
2697 if (!cPairs && kern_pairA)
2699 SetLastError(ERROR_INVALID_PARAMETER);
2703 charset = GetTextCharset(hDC);
2704 if (!TranslateCharsetInfo(ULongToPtr(charset), &csi, TCI_SRCCHARSET))
2706 FIXME("Can't find codepage for charset %d\n", charset);
2709 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2710 * to fail on an invalid character for CP_SYMBOL.
2712 cpi.DefaultChar[0] = 0;
2713 if (csi.ciACP != CP_SYMBOL && !GetCPInfo(csi.ciACP, &cpi))
2715 FIXME("Can't find codepage %u info\n", csi.ciACP);
2718 TRACE("charset %d => codepage %u\n", charset, csi.ciACP);
2720 total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2721 if (!total_kern_pairs) return 0;
2723 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2724 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2726 for (i = 0; i < total_kern_pairs; i++)
2730 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2733 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2736 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2741 if (kern_pairs_copied >= cPairs) break;
2743 kern_pairA->wFirst = (BYTE)first;
2744 kern_pairA->wSecond = (BYTE)second;
2745 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2748 kern_pairs_copied++;
2751 HeapFree(GetProcessHeap(), 0, kern_pairW);
2753 return kern_pairs_copied;
2756 /*************************************************************************
2757 * GetKerningPairsW (GDI32.@)
2759 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2760 LPKERNINGPAIR lpKerningPairs )
2765 TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2767 if (!cPairs && lpKerningPairs)
2769 SetLastError(ERROR_INVALID_PARAMETER);
2773 dc = DC_GetDCPtr(hDC);
2777 ret = WineEngGetKerningPairs(dc->gdiFont, cPairs, lpKerningPairs);
2779 DC_ReleaseDCPtr( dc );
2783 /*************************************************************************
2784 * TranslateCharsetInfo [GDI32.@]
2786 * Fills a CHARSETINFO structure for a character set, code page, or
2787 * font. This allows making the correspondence between different labels
2788 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2789 * of the same encoding.
2791 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2792 * only one codepage should be set in *lpSrc.
2795 * TRUE on success, FALSE on failure.
2798 BOOL WINAPI TranslateCharsetInfo(
2799 LPDWORD lpSrc, /* [in]
2800 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2801 if flags == TCI_SRCCHARSET: a character set value
2802 if flags == TCI_SRCCODEPAGE: a code page value
2804 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2805 DWORD flags /* [in] determines interpretation of lpSrc */)
2809 case TCI_SRCFONTSIG:
2810 while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
2812 case TCI_SRCCODEPAGE:
2813 while (PtrToUlong(lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
2815 case TCI_SRCCHARSET:
2816 while (PtrToUlong(lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
2821 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2822 memcpy(lpCs, &FONT_tci[index], sizeof(CHARSETINFO));
2826 /*************************************************************************
2827 * GetFontLanguageInfo (GDI32.@)
2829 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2831 FONTSIGNATURE fontsig;
2832 static const DWORD GCP_DBCS_MASK=0x003F0000,
2833 GCP_DIACRITIC_MASK=0x00000000,
2834 FLI_GLYPHS_MASK=0x00000000,
2835 GCP_GLYPHSHAPE_MASK=0x00000040,
2836 GCP_KASHIDA_MASK=0x00000000,
2837 GCP_LIGATE_MASK=0x00000000,
2838 GCP_USEKERNING_MASK=0x00000000,
2839 GCP_REORDER_MASK=0x00000060;
2843 GetTextCharsetInfo( hdc, &fontsig, 0 );
2844 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2846 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2849 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2850 result|=GCP_DIACRITIC;
2852 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2855 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2856 result|=GCP_GLYPHSHAPE;
2858 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2859 result|=GCP_KASHIDA;
2861 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2864 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2865 result|=GCP_USEKERNING;
2867 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2868 if( GetTextAlign( hdc) & TA_RTLREADING )
2869 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2870 result|=GCP_REORDER;
2876 /*************************************************************************
2877 * GetFontData [GDI32.@]
2879 * Retrieve data for TrueType font.
2883 * success: Number of bytes returned
2884 * failure: GDI_ERROR
2888 * Calls SetLastError()
2891 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2892 LPVOID buffer, DWORD length)
2894 DC *dc = DC_GetDCPtr(hdc);
2895 DWORD ret = GDI_ERROR;
2897 if(!dc) return GDI_ERROR;
2900 ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2902 DC_ReleaseDCPtr( dc );
2906 /*************************************************************************
2907 * GetGlyphIndicesA [GDI32.@]
2909 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2910 LPWORD pgi, DWORD flags)
2916 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2917 hdc, debugstr_an(lpstr, count), count, pgi, flags);
2919 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2920 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2921 HeapFree(GetProcessHeap(), 0, lpstrW);
2926 /*************************************************************************
2927 * GetGlyphIndicesW [GDI32.@]
2929 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2930 LPWORD pgi, DWORD flags)
2932 DC *dc = DC_GetDCPtr(hdc);
2933 DWORD ret = GDI_ERROR;
2935 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2936 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2938 if(!dc) return GDI_ERROR;
2941 ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2943 DC_ReleaseDCPtr( dc );
2947 /*************************************************************************
2948 * GetCharacterPlacementA [GDI32.@]
2950 * See GetCharacterPlacementW.
2953 * the web browser control of ie4 calls this with dwFlags=0
2956 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2957 INT nMaxExtent, GCP_RESULTSA *lpResults,
2962 GCP_RESULTSW resultsW;
2966 TRACE("%s, %d, %d, 0x%08x\n",
2967 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2969 /* both structs are equal in size */
2970 memcpy(&resultsW, lpResults, sizeof(resultsW));
2972 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2973 if(lpResults->lpOutString)
2974 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2976 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2978 lpResults->nGlyphs = resultsW.nGlyphs;
2979 lpResults->nMaxFit = resultsW.nMaxFit;
2981 if(lpResults->lpOutString) {
2982 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2983 lpResults->lpOutString, uCount, NULL, NULL );
2986 HeapFree(GetProcessHeap(), 0, lpStringW);
2987 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2992 /*************************************************************************
2993 * GetCharacterPlacementW [GDI32.@]
2995 * Retrieve information about a string. This includes the width, reordering,
2996 * Glyphing and so on.
3000 * The width and height of the string if successful, 0 if failed.
3004 * All flags except GCP_REORDER are not yet implemented.
3005 * Reordering is not 100% complient to the Windows BiDi method.
3006 * Caret positioning is not yet implemented for BiDi.
3007 * Classes are not yet implemented.
3011 GetCharacterPlacementW(
3012 HDC hdc, /* [in] Device context for which the rendering is to be done */
3013 LPCWSTR lpString, /* [in] The string for which information is to be returned */
3014 INT uCount, /* [in] Number of WORDS in string. */
3015 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
3016 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
3017 DWORD dwFlags /* [in] Flags specifying how to process the string */
3024 TRACE("%s, %d, %d, 0x%08x\n",
3025 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
3027 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
3028 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
3029 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
3030 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
3031 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
3033 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08x ignored\n", dwFlags);
3034 if(lpResults->lpClass) FIXME("classes not implemented\n");
3035 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
3036 FIXME("Caret positions for complex scripts not implemented\n");
3038 nSet = (UINT)uCount;
3039 if(nSet > lpResults->nGlyphs)
3040 nSet = lpResults->nGlyphs;
3042 /* return number of initialized fields */
3043 lpResults->nGlyphs = nSet;
3045 if((dwFlags&GCP_REORDER)==0 )
3047 /* Treat the case where no special handling was requested in a fastpath way */
3048 /* copy will do if the GCP_REORDER flag is not set */
3049 if(lpResults->lpOutString)
3050 memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
3052 if(lpResults->lpOrder)
3054 for(i = 0; i < nSet; i++)
3055 lpResults->lpOrder[i] = i;
3059 BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
3060 nSet, lpResults->lpOrder );
3063 /* FIXME: Will use the placement chars */
3064 if (lpResults->lpDx)
3067 for (i = 0; i < nSet; i++)
3069 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
3070 lpResults->lpDx[i]= c;
3074 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
3078 lpResults->lpCaretPos[0] = 0;
3079 for (i = 1; i < nSet; i++)
3080 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
3081 lpResults->lpCaretPos[i] = (pos += size.cx);
3084 if(lpResults->lpGlyphs)
3085 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
3087 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
3088 ret = MAKELONG(size.cx, size.cy);
3093 /*************************************************************************
3094 * GetCharABCWidthsFloatA [GDI32.@]
3096 * See GetCharABCWidthsFloatW.
3098 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3100 INT i, wlen, count = (INT)(last - first + 1);
3105 if (count <= 0) return FALSE;
3107 str = HeapAlloc(GetProcessHeap(), 0, count);
3109 for(i = 0; i < count; i++)
3110 str[i] = (BYTE)(first + i);
3112 wstr = FONT_mbtowc( hdc, str, count, &wlen, NULL );
3114 for (i = 0; i < wlen; i++)
3116 if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
3124 HeapFree( GetProcessHeap(), 0, str );
3125 HeapFree( GetProcessHeap(), 0, wstr );
3130 /*************************************************************************
3131 * GetCharABCWidthsFloatW [GDI32.@]
3133 * Retrieves widths of a range of characters.
3136 * hdc [I] Handle to device context.
3137 * first [I] First character in range to query.
3138 * last [I] Last character in range to query.
3139 * abcf [O] Array of LPABCFLOAT structures.
3146 * Only works with TrueType fonts. It also doesn't return real
3147 * floats but converted integers because it's implemented on
3148 * top of GetCharABCWidthsW.
3150 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3153 unsigned int i, size = sizeof(ABC) * (last - first + 1);
3156 TRACE("%p, %d, %d, %p - partial stub\n", hdc, first, last, abcf);
3158 abc = HeapAlloc( GetProcessHeap(), 0, size );
3159 if (!abc) return FALSE;
3161 ret = GetCharABCWidthsW( hdc, first, last, abc );
3164 for (i = first; i <= last; i++, abc++, abcf++)
3166 abcf->abcfA = abc->abcA;
3167 abcf->abcfB = abc->abcB;
3168 abcf->abcfC = abc->abcC;
3171 HeapFree( GetProcessHeap(), 0, abc );
3175 /*************************************************************************
3176 * GetCharWidthFloatA [GDI32.@]
3178 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
3179 UINT iLastChar, PFLOAT pxBuffer)
3181 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3185 /*************************************************************************
3186 * GetCharWidthFloatW [GDI32.@]
3188 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
3189 UINT iLastChar, PFLOAT pxBuffer)
3191 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3196 /***********************************************************************
3198 * Font Resource API *
3200 ***********************************************************************/
3202 /***********************************************************************
3203 * AddFontResourceA (GDI32.@)
3205 INT WINAPI AddFontResourceA( LPCSTR str )
3207 return AddFontResourceExA( str, 0, NULL);
3210 /***********************************************************************
3211 * AddFontResourceW (GDI32.@)
3213 INT WINAPI AddFontResourceW( LPCWSTR str )
3215 return AddFontResourceExW(str, 0, NULL);
3219 /***********************************************************************
3220 * AddFontResourceExA (GDI32.@)
3222 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3224 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3225 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3228 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3229 ret = AddFontResourceExW(strW, fl, pdv);
3230 HeapFree(GetProcessHeap(), 0, strW);
3234 static BOOL CALLBACK load_enumed_resource(HMODULE hModule, LPCWSTR type, LPWSTR name, LONG_PTR lParam)
3236 HRSRC rsrc = FindResourceW(hModule, name, type);
3237 HGLOBAL hMem = LoadResource(hModule, rsrc);
3238 LPVOID *pMem = LockResource(hMem);
3239 int *num_total = (int *)lParam;
3242 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type));
3243 if (!AddFontMemResourceEx(pMem, SizeofResource(hModule, rsrc), NULL, &num_in_res))
3245 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule, hMem);
3249 *num_total += num_in_res;
3253 /***********************************************************************
3254 * AddFontResourceExW (GDI32.@)
3256 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3258 int ret = WineEngAddFontResourceEx(str, fl, pdv);
3261 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3262 HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
3263 if (hModule != NULL)
3265 int num_resources = 0;
3266 LPWSTR rt_font = (LPWSTR)((ULONG_PTR)8); /* we don't want to include winuser.h */
3268 TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3269 wine_dbgstr_w(str));
3270 if (EnumResourceNamesW(hModule, rt_font, load_enumed_resource, (LONG_PTR)&num_resources))
3271 ret = num_resources;
3272 FreeLibrary(hModule);
3278 /***********************************************************************
3279 * RemoveFontResourceA (GDI32.@)
3281 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3283 return RemoveFontResourceExA(str, 0, 0);
3286 /***********************************************************************
3287 * RemoveFontResourceW (GDI32.@)
3289 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3291 return RemoveFontResourceExW(str, 0, 0);
3294 /***********************************************************************
3295 * AddFontMemResourceEx (GDI32.@)
3297 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3299 return WineEngAddFontMemResourceEx(pbFont, cbFont, pdv, pcFonts);
3302 /***********************************************************************
3303 * RemoveFontMemResourceEx (GDI32.@)
3305 BOOL WINAPI RemoveFontMemResourceEx( HANDLE fh )
3307 FIXME("(%p) stub\n", fh);
3311 /***********************************************************************
3312 * RemoveFontResourceExA (GDI32.@)
3314 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3316 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3317 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3320 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3321 ret = RemoveFontResourceExW(strW, fl, pdv);
3322 HeapFree(GetProcessHeap(), 0, strW);
3326 /***********************************************************************
3327 * RemoveFontResourceExW (GDI32.@)
3329 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3331 return WineEngRemoveFontResourceEx(str, fl, pdv);
3334 /***********************************************************************
3335 * GetTextCharset (GDI32.@)
3337 UINT WINAPI GetTextCharset(HDC hdc)
3339 /* MSDN docs say this is equivalent */
3340 return GetTextCharsetInfo(hdc, NULL, 0);
3343 /***********************************************************************
3344 * GetTextCharsetInfo (GDI32.@)
3346 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3348 UINT ret = DEFAULT_CHARSET;
3349 DC *dc = DC_GetDCPtr(hdc);
3354 ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
3356 DC_ReleaseDCPtr( dc );
3359 if (ret == DEFAULT_CHARSET && fs)
3360 memset(fs, 0, sizeof(FONTSIGNATURE));
3364 /***********************************************************************
3365 * GdiGetCharDimensions (GDI32.@)
3367 * Gets the average width of the characters in the English alphabet.
3370 * hdc [I] Handle to the device context to measure on.
3371 * lptm [O] Pointer to memory to store the text metrics into.
3372 * height [O] On exit, the maximum height of characters in the English alphabet.
3375 * The average width of characters in the English alphabet.
3378 * This function is used by the dialog manager to get the size of a dialog
3379 * unit. It should also be used by other pieces of code that need to know
3380 * the size of a dialog unit in logical units without having access to the
3381 * window handle of the dialog.
3382 * Windows caches the font metrics from this function, but we don't and
3383 * there doesn't appear to be an immediate advantage to do so.
3386 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3388 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3391 static const WCHAR alphabet[] = {
3392 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3393 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3394 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3396 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3398 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3400 if (height) *height = sz.cy;
3401 return (sz.cx / 26 + 1) / 2;
3404 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3406 FIXME("(%d): stub\n", fEnableEUDC);
3410 /***********************************************************************
3411 * GetCharWidthI (GDI32.@)
3413 * Retrieve widths of characters.
3416 * hdc [I] Handle to a device context.
3417 * first [I] First glyph in range to query.
3418 * count [I] Number of glyph indices to query.
3419 * glyphs [I] Array of glyphs to query.
3420 * buffer [O] Buffer to receive character widths.
3423 * Only works with TrueType fonts.
3429 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3434 TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3436 if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3439 if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3441 HeapFree(GetProcessHeap(), 0, abc);
3445 for (i = 0; i < count; i++)
3446 buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3448 HeapFree(GetProcessHeap(), 0, abc);
3452 /***********************************************************************
3453 * GetFontUnicodeRanges (GDI32.@)
3455 * Retrieve a list of supported Unicode characters in a font.
3458 * hdc [I] Handle to a device context.
3459 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3462 * Success: Number of bytes written to the buffer pointed to by lpgs.
3466 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3469 DC *dc = DC_GetDCPtr(hdc);
3471 TRACE("(%p, %p)\n", hdc, lpgs);
3475 if (dc->gdiFont) ret = WineEngGetFontUnicodeRanges(dc->gdiFont, lpgs);
3476 DC_ReleaseDCPtr(dc);
3481 /*************************************************************
3482 * FontIsLinked (GDI32.@)
3484 BOOL WINAPI FontIsLinked(HDC hdc)
3486 DC *dc = DC_GetDCPtr(hdc);
3489 if (!dc) return FALSE;
3490 if (dc->gdiFont) ret = WineEngFontIsLinked(dc->gdiFont);
3491 DC_ReleaseDCPtr(dc);
3492 TRACE("returning %d\n", ret);