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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include "wine/port.h"
36 #include "gdi_private.h"
37 #include "wine/unicode.h"
38 #include "wine/debug.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(font);
41 WINE_DECLARE_DEBUG_CHANNEL(gdi);
43 /* Device -> World size conversion */
45 /* Performs a device to world transformation on the specified width (which
46 * is in integer format).
48 static inline INT INTERNAL_XDSTOWS(DC *dc, INT width)
52 /* Perform operation with floating point */
53 floatWidth = (FLOAT)width * dc->xformVport2World.eM11;
54 /* Round to integers */
55 return GDI_ROUND(floatWidth);
58 /* Performs a device to world transformation on the specified size (which
59 * is in integer format).
61 static inline INT INTERNAL_YDSTOWS(DC *dc, INT height)
65 /* Perform operation with floating point */
66 floatHeight = (FLOAT)height * dc->xformVport2World.eM22;
67 /* Round to integers */
68 return GDI_ROUND(floatHeight);
71 static inline INT INTERNAL_XWSTODS(DC *dc, INT width)
74 pt[0].x = pt[0].y = 0;
77 LPtoDP(dc->hSelf, pt, 2);
78 return pt[1].x - pt[0].x;
81 static inline INT INTERNAL_YWSTODS(DC *dc, INT height)
84 pt[0].x = pt[0].y = 0;
87 LPtoDP(dc->hSelf, pt, 2);
88 return pt[1].y - pt[0].y;
91 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, void *obj, HDC hdc );
92 static INT FONT_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
93 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
94 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
95 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj );
97 static const struct gdi_obj_funcs font_funcs =
99 FONT_SelectObject, /* pSelectObject */
100 FONT_GetObject16, /* pGetObject16 */
101 FONT_GetObjectA, /* pGetObjectA */
102 FONT_GetObjectW, /* pGetObjectW */
103 NULL, /* pUnrealizeObject */
104 FONT_DeleteObject /* pDeleteObject */
107 #define ENUM_UNICODE 0x00000001
108 #define ENUM_CALLED 0x00000002
118 LPLOGFONT16 lpLogFontParam;
119 FONTENUMPROC16 lpEnumFunc;
122 LPNEWTEXTMETRICEX16 lpTextMetric;
123 LPENUMLOGFONTEX16 lpLogFont;
124 SEGPTR segTextMetric;
134 LPLOGFONTW lpLogFontParam;
135 FONTENUMPROCW lpEnumFunc;
144 * For TranslateCharsetInfo
146 #define FS(x) {{0,0,0,0},{0x1<<(x),0}}
147 #define MAXTCIINDEX 32
148 static const CHARSETINFO FONT_tci[MAXTCIINDEX] = {
150 { ANSI_CHARSET, 1252, FS(0)},
151 { EASTEUROPE_CHARSET, 1250, FS(1)},
152 { RUSSIAN_CHARSET, 1251, FS(2)},
153 { GREEK_CHARSET, 1253, FS(3)},
154 { TURKISH_CHARSET, 1254, FS(4)},
155 { HEBREW_CHARSET, 1255, FS(5)},
156 { ARABIC_CHARSET, 1256, FS(6)},
157 { BALTIC_CHARSET, 1257, FS(7)},
158 { VIETNAMESE_CHARSET, 1258, FS(8)},
159 /* reserved by ANSI */
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)},
165 { DEFAULT_CHARSET, 0, FS(0)},
166 { DEFAULT_CHARSET, 0, FS(0)},
168 { THAI_CHARSET, 874, FS(16)},
169 { SHIFTJIS_CHARSET, 932, FS(17)},
170 { GB2312_CHARSET, 936, FS(18)},
171 { HANGEUL_CHARSET, 949, FS(19)},
172 { CHINESEBIG5_CHARSET, 950, FS(20)},
173 { JOHAB_CHARSET, 1361, FS(21)},
174 /* reserved for alternate ANSI and OEM */
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 { DEFAULT_CHARSET, 0, FS(0)},
182 { DEFAULT_CHARSET, 0, FS(0)},
183 /* reserved for system */
184 { DEFAULT_CHARSET, 0, FS(0)},
185 { SYMBOL_CHARSET, CP_SYMBOL, FS(31)},
188 /***********************************************************************
189 * LOGFONT conversion functions.
191 static void FONT_LogFontWTo16( const LOGFONTW* font32, LPLOGFONT16 font16 )
193 font16->lfHeight = font32->lfHeight;
194 font16->lfWidth = font32->lfWidth;
195 font16->lfEscapement = font32->lfEscapement;
196 font16->lfOrientation = font32->lfOrientation;
197 font16->lfWeight = font32->lfWeight;
198 font16->lfItalic = font32->lfItalic;
199 font16->lfUnderline = font32->lfUnderline;
200 font16->lfStrikeOut = font32->lfStrikeOut;
201 font16->lfCharSet = font32->lfCharSet;
202 font16->lfOutPrecision = font32->lfOutPrecision;
203 font16->lfClipPrecision = font32->lfClipPrecision;
204 font16->lfQuality = font32->lfQuality;
205 font16->lfPitchAndFamily = font32->lfPitchAndFamily;
206 WideCharToMultiByte( CP_ACP, 0, font32->lfFaceName, -1,
207 font16->lfFaceName, LF_FACESIZE, NULL, NULL );
208 font16->lfFaceName[LF_FACESIZE-1] = 0;
211 static void FONT_LogFont16ToW( const LOGFONT16 *font16, LPLOGFONTW font32 )
213 font32->lfHeight = font16->lfHeight;
214 font32->lfWidth = font16->lfWidth;
215 font32->lfEscapement = font16->lfEscapement;
216 font32->lfOrientation = font16->lfOrientation;
217 font32->lfWeight = font16->lfWeight;
218 font32->lfItalic = font16->lfItalic;
219 font32->lfUnderline = font16->lfUnderline;
220 font32->lfStrikeOut = font16->lfStrikeOut;
221 font32->lfCharSet = font16->lfCharSet;
222 font32->lfOutPrecision = font16->lfOutPrecision;
223 font32->lfClipPrecision = font16->lfClipPrecision;
224 font32->lfQuality = font16->lfQuality;
225 font32->lfPitchAndFamily = font16->lfPitchAndFamily;
226 MultiByteToWideChar( CP_ACP, 0, font16->lfFaceName, -1, font32->lfFaceName, LF_FACESIZE );
227 font32->lfFaceName[LF_FACESIZE-1] = 0;
230 static void FONT_LogFontAToW( const LOGFONTA *fontA, LPLOGFONTW fontW )
232 memcpy(fontW, fontA, sizeof(LOGFONTA) - LF_FACESIZE);
233 MultiByteToWideChar(CP_ACP, 0, fontA->lfFaceName, -1, fontW->lfFaceName,
235 fontW->lfFaceName[LF_FACESIZE-1] = 0;
238 static void FONT_LogFontWToA( const LOGFONTW *fontW, LPLOGFONTA fontA )
240 memcpy(fontA, fontW, sizeof(LOGFONTA) - LF_FACESIZE);
241 WideCharToMultiByte(CP_ACP, 0, fontW->lfFaceName, -1, fontA->lfFaceName,
242 LF_FACESIZE, NULL, NULL);
243 fontA->lfFaceName[LF_FACESIZE-1] = 0;
246 static void FONT_EnumLogFontExWTo16( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEX16 font16 )
248 FONT_LogFontWTo16( (LPLOGFONTW)fontW, (LPLOGFONT16)font16);
250 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
251 (LPSTR) font16->elfFullName, LF_FULLFACESIZE, NULL, NULL );
252 font16->elfFullName[LF_FULLFACESIZE-1] = '\0';
253 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
254 (LPSTR) font16->elfStyle, LF_FACESIZE, NULL, NULL );
255 font16->elfStyle[LF_FACESIZE-1] = '\0';
256 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
257 (LPSTR) font16->elfScript, LF_FACESIZE, NULL, NULL );
258 font16->elfScript[LF_FACESIZE-1] = '\0';
261 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEXA fontA )
263 FONT_LogFontWToA( (LPLOGFONTW)fontW, (LPLOGFONTA)fontA);
265 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
266 (LPSTR) fontA->elfFullName, LF_FULLFACESIZE, NULL, NULL );
267 fontA->elfFullName[LF_FULLFACESIZE-1] = '\0';
268 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
269 (LPSTR) fontA->elfStyle, LF_FACESIZE, NULL, NULL );
270 fontA->elfStyle[LF_FACESIZE-1] = '\0';
271 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
272 (LPSTR) fontA->elfScript, LF_FACESIZE, NULL, NULL );
273 fontA->elfScript[LF_FACESIZE-1] = '\0';
276 /***********************************************************************
277 * TEXTMETRIC conversion functions.
279 static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
281 ptmA->tmHeight = ptmW->tmHeight;
282 ptmA->tmAscent = ptmW->tmAscent;
283 ptmA->tmDescent = ptmW->tmDescent;
284 ptmA->tmInternalLeading = ptmW->tmInternalLeading;
285 ptmA->tmExternalLeading = ptmW->tmExternalLeading;
286 ptmA->tmAveCharWidth = ptmW->tmAveCharWidth;
287 ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth;
288 ptmA->tmWeight = ptmW->tmWeight;
289 ptmA->tmOverhang = ptmW->tmOverhang;
290 ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX;
291 ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
292 ptmA->tmFirstChar = ptmW->tmFirstChar > 255 ? 255 : ptmW->tmFirstChar;
293 ptmA->tmLastChar = ptmW->tmLastChar > 255 ? 255 : ptmW->tmLastChar;
294 ptmA->tmDefaultChar = ptmW->tmDefaultChar > 255 ? 255 : ptmW->tmDefaultChar;
295 ptmA->tmBreakChar = ptmW->tmBreakChar > 255 ? 255 : ptmW->tmBreakChar;
296 ptmA->tmItalic = ptmW->tmItalic;
297 ptmA->tmUnderlined = ptmW->tmUnderlined;
298 ptmA->tmStruckOut = ptmW->tmStruckOut;
299 ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
300 ptmA->tmCharSet = ptmW->tmCharSet;
304 static void FONT_NewTextMetricExWTo16(const NEWTEXTMETRICEXW *ptmW, LPNEWTEXTMETRICEX16 ptm16 )
306 ptm16->ntmTm.tmHeight = ptmW->ntmTm.tmHeight;
307 ptm16->ntmTm.tmAscent = ptmW->ntmTm.tmAscent;
308 ptm16->ntmTm.tmDescent = ptmW->ntmTm.tmDescent;
309 ptm16->ntmTm.tmInternalLeading = ptmW->ntmTm.tmInternalLeading;
310 ptm16->ntmTm.tmExternalLeading = ptmW->ntmTm.tmExternalLeading;
311 ptm16->ntmTm.tmAveCharWidth = ptmW->ntmTm.tmAveCharWidth;
312 ptm16->ntmTm.tmMaxCharWidth = ptmW->ntmTm.tmMaxCharWidth;
313 ptm16->ntmTm.tmWeight = ptmW->ntmTm.tmWeight;
314 ptm16->ntmTm.tmOverhang = ptmW->ntmTm.tmOverhang;
315 ptm16->ntmTm.tmDigitizedAspectX = ptmW->ntmTm.tmDigitizedAspectX;
316 ptm16->ntmTm.tmDigitizedAspectY = ptmW->ntmTm.tmDigitizedAspectY;
317 ptm16->ntmTm.tmFirstChar = ptmW->ntmTm.tmFirstChar > 255 ? 255 : ptmW->ntmTm.tmFirstChar;
318 ptm16->ntmTm.tmLastChar = ptmW->ntmTm.tmLastChar > 255 ? 255 : ptmW->ntmTm.tmLastChar;
319 ptm16->ntmTm.tmDefaultChar = ptmW->ntmTm.tmDefaultChar > 255 ? 255 : ptmW->ntmTm.tmDefaultChar;
320 ptm16->ntmTm.tmBreakChar = ptmW->ntmTm.tmBreakChar > 255 ? 255 : ptmW->ntmTm.tmBreakChar;
321 ptm16->ntmTm.tmItalic = ptmW->ntmTm.tmItalic;
322 ptm16->ntmTm.tmUnderlined = ptmW->ntmTm.tmUnderlined;
323 ptm16->ntmTm.tmStruckOut = ptmW->ntmTm.tmStruckOut;
324 ptm16->ntmTm.tmPitchAndFamily = ptmW->ntmTm.tmPitchAndFamily;
325 ptm16->ntmTm.tmCharSet = ptmW->ntmTm.tmCharSet;
326 ptm16->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
327 ptm16->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
328 ptm16->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
329 ptm16->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
330 memcpy(&ptm16->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
333 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW *ptmW, NEWTEXTMETRICEXA *ptmA )
335 FONT_TextMetricWToA((LPTEXTMETRICW)ptmW, (LPTEXTMETRICA)ptmA);
336 ptmA->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
337 ptmA->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
338 ptmA->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
339 ptmA->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
340 memcpy(&ptmA->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
344 /***********************************************************************
347 * Returns a Unicode translation of str using the charset of the
348 * currently selected font in hdc. If count is -1 then str is assumed
349 * to be '\0' terminated, otherwise it contains the number of bytes to
350 * convert. If plenW is non-NULL, on return it will point to the
351 * number of WCHARs that have been written. If pCP is non-NULL, on
352 * return it will point to the codepage used in the conversion. The
353 * caller should free the returned LPWSTR from the process heap
356 static LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
362 int charset = GetTextCharset(hdc);
364 /* Hmm, nicely designed api this one! */
365 if(TranslateCharsetInfo((DWORD*)charset, &csi, TCI_SRCCHARSET))
372 case DEFAULT_CHARSET:
383 /* FIXME: These have no place here, but because x11drv
384 enumerates fonts with these (made up) charsets some apps
385 might use them and then the FIXME below would become
386 annoying. Now we could pick the intended codepage for
387 each of these, but since it's broken anyway we'll just
388 use CP_ACP and hope it'll go away...
394 FIXME("Can't find codepage for charset %d\n", charset);
399 TRACE("charset %d => cp %d\n", charset, cp);
401 if(count == -1) count = strlen(str);
402 lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
403 strW = HeapAlloc(GetProcessHeap(), 0, lenW*sizeof(WCHAR));
404 MultiByteToWideChar(cp, 0, str, count, strW, lenW);
405 TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW));
406 if(plenW) *plenW = lenW;
412 /***********************************************************************
413 * CreateFontIndirectA (GDI32.@)
415 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *plfA )
420 FONT_LogFontAToW( plfA, &lfW );
421 return CreateFontIndirectW( &lfW );
423 return CreateFontIndirectW( NULL );
427 /***********************************************************************
428 * CreateFontIndirectW (GDI32.@)
430 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
437 if ((fontPtr = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC,
438 (HGDIOBJ *)&hFont, &font_funcs )))
440 static const WCHAR ItalicW[] = {' ','I','t','a','l','i','c','\0'};
441 static const WCHAR BoldW[] = {' ','B','o','l','d','\0'};
442 WCHAR *pFaceNameItalicSuffix, *pFaceNameBoldSuffix;
443 WCHAR* pFaceNameSuffix = NULL;
445 memcpy( &fontPtr->logfont, plf, sizeof(LOGFONTW) );
447 TRACE("(%ld %ld %ld %ld %x %d %x %d %d) %s %s %s %s => %p\n",
448 plf->lfHeight, plf->lfWidth,
449 plf->lfEscapement, plf->lfOrientation,
450 plf->lfPitchAndFamily,
451 plf->lfOutPrecision, plf->lfClipPrecision,
452 plf->lfQuality, plf->lfCharSet,
453 debugstr_w(plf->lfFaceName),
454 plf->lfWeight > 400 ? "Bold" : "",
455 plf->lfItalic ? "Italic" : "",
456 plf->lfUnderline ? "Underline" : "", hFont);
458 if (plf->lfEscapement != plf->lfOrientation) {
459 /* this should really depend on whether GM_ADVANCED is set */
460 fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
461 WARN("orientation angle %f set to "
462 "escapement angle %f for new font %p\n",
463 plf->lfOrientation/10., plf->lfEscapement/10., hFont);
466 pFaceNameItalicSuffix = strstrW(fontPtr->logfont.lfFaceName, ItalicW);
467 if (pFaceNameItalicSuffix) {
468 fontPtr->logfont.lfItalic = TRUE;
469 pFaceNameSuffix = pFaceNameItalicSuffix;
472 pFaceNameBoldSuffix = strstrW(fontPtr->logfont.lfFaceName, BoldW);
473 if (pFaceNameBoldSuffix) {
474 if (fontPtr->logfont.lfWeight < FW_BOLD) {
475 fontPtr->logfont.lfWeight = FW_BOLD;
477 if (!pFaceNameSuffix ||
478 (pFaceNameBoldSuffix < pFaceNameSuffix)) {
479 pFaceNameSuffix = pFaceNameBoldSuffix;
483 if (pFaceNameSuffix) *pFaceNameSuffix = 0;
485 GDI_ReleaseObj( hFont );
488 else WARN("(NULL) => NULL\n");
493 /*************************************************************************
494 * CreateFontA (GDI32.@)
496 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
497 INT orient, INT weight, DWORD italic,
498 DWORD underline, DWORD strikeout, DWORD charset,
499 DWORD outpres, DWORD clippres, DWORD quality,
500 DWORD pitch, LPCSTR name )
504 logfont.lfHeight = height;
505 logfont.lfWidth = width;
506 logfont.lfEscapement = esc;
507 logfont.lfOrientation = orient;
508 logfont.lfWeight = weight;
509 logfont.lfItalic = italic;
510 logfont.lfUnderline = underline;
511 logfont.lfStrikeOut = strikeout;
512 logfont.lfCharSet = charset;
513 logfont.lfOutPrecision = outpres;
514 logfont.lfClipPrecision = clippres;
515 logfont.lfQuality = quality;
516 logfont.lfPitchAndFamily = pitch;
519 lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
521 logfont.lfFaceName[0] = '\0';
523 return CreateFontIndirectA( &logfont );
526 /*************************************************************************
527 * CreateFontW (GDI32.@)
529 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
530 INT orient, INT weight, DWORD italic,
531 DWORD underline, DWORD strikeout, DWORD charset,
532 DWORD outpres, DWORD clippres, DWORD quality,
533 DWORD pitch, LPCWSTR name )
537 logfont.lfHeight = height;
538 logfont.lfWidth = width;
539 logfont.lfEscapement = esc;
540 logfont.lfOrientation = orient;
541 logfont.lfWeight = weight;
542 logfont.lfItalic = italic;
543 logfont.lfUnderline = underline;
544 logfont.lfStrikeOut = strikeout;
545 logfont.lfCharSet = charset;
546 logfont.lfOutPrecision = outpres;
547 logfont.lfClipPrecision = clippres;
548 logfont.lfQuality = quality;
549 logfont.lfPitchAndFamily = pitch;
552 lstrcpynW(logfont.lfFaceName, name,
553 sizeof(logfont.lfFaceName) / sizeof(WCHAR));
555 logfont.lfFaceName[0] = '\0';
557 return CreateFontIndirectW( &logfont );
561 /***********************************************************************
564 * If the driver supports vector fonts we create a gdi font first and
565 * then call the driver to give it a chance to supply its own device
566 * font. If the driver wants to do this it returns TRUE and we can
567 * delete the gdi font, if the driver wants to use the gdi font it
568 * should return FALSE, to signal an error return GDI_ERROR. For
569 * drivers that don't support vector fonts they must supply their own
572 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, void *obj, HDC hdc )
575 DC *dc = DC_GetDCPtr( hdc );
579 if (dc->hFont != handle || dc->gdiFont == NULL)
581 if(GetDeviceCaps(dc->hSelf, TEXTCAPS) & TC_VA_ABLE)
582 dc->gdiFont = WineEngCreateFontInstance(dc, handle);
585 if (dc->funcs->pSelectFont) ret = dc->funcs->pSelectFont( dc->physDev, handle, dc->gdiFont );
587 if (ret && dc->gdiFont) dc->gdiFont = 0;
589 if (ret == HGDI_ERROR)
590 ret = 0; /* SelectObject returns 0 on error */
596 GDI_ReleaseObj( hdc );
601 /***********************************************************************
604 static INT FONT_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
609 FONT_LogFontWTo16( &font->logfont, &lf16 );
611 if (count > sizeof(LOGFONT16)) count = sizeof(LOGFONT16);
612 memcpy( buffer, &lf16, count );
616 /***********************************************************************
619 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
626 FONT_LogFontWToA( &font->logfont, &lfA );
628 if (count > sizeof(lfA)) count = sizeof(lfA);
629 memcpy( buffer, &lfA, count );
633 /***********************************************************************
636 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
640 return sizeof(LOGFONTW);
641 if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
642 memcpy( buffer, &font->logfont, count );
647 /***********************************************************************
650 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj )
652 WineEngDestroyFontInstance( handle );
653 return GDI_FreeObject( handle, obj );
657 /***********************************************************************
658 * FONT_EnumInstance16
660 * Called by the device driver layer to pass font info
661 * down to the application.
663 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
664 * We have to use other types because of the FONTENUMPROCW definition.
666 static INT CALLBACK FONT_EnumInstance16( const LOGFONTW *plf, const TEXTMETRICW *ptm,
667 DWORD fType, LPARAM lp )
669 fontEnum16 *pfe = (fontEnum16*)lp;
673 if( pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
674 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet )
679 FONT_EnumLogFontExWTo16((const ENUMLOGFONTEXW *)plf, pfe->lpLogFont);
680 FONT_NewTextMetricExWTo16((const NEWTEXTMETRICEXW *)ptm, pfe->lpTextMetric);
681 pfe->dwFlags |= ENUM_CALLED;
682 GDI_ReleaseObj( pfe->hdc ); /* release the GDI lock */
684 args[6] = SELECTOROF(pfe->segLogFont);
685 args[5] = OFFSETOF(pfe->segLogFont);
686 args[4] = SELECTOROF(pfe->segTextMetric);
687 args[3] = OFFSETOF(pfe->segTextMetric);
689 args[1] = HIWORD(pfe->lpData);
690 args[0] = LOWORD(pfe->lpData);
691 WOWCallback16Ex( (DWORD)pfe->lpEnumFunc, WCB16_PASCAL, sizeof(args), args, &result );
692 ret = LOWORD(result);
694 /* get the lock again and make sure the DC is still valid */
695 dc = DC_GetDCPtr( pfe->hdc );
696 if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
698 if (dc) GDI_ReleaseObj( pfe->hdc );
699 pfe->hdc = 0; /* make sure we don't try to release it later on */
706 /***********************************************************************
709 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
710 * We have to use other types because of the FONTENUMPROCW definition.
712 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
713 DWORD fType, LPARAM lp )
715 fontEnum32 *pfe = (fontEnum32*)lp;
719 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
720 if((pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
721 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
722 (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
724 /* convert font metrics */
725 ENUMLOGFONTEXA logfont;
726 NEWTEXTMETRICEXA tmA;
728 pfe->dwFlags |= ENUM_CALLED;
729 if (!(pfe->dwFlags & ENUM_UNICODE))
731 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
732 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
733 plf = (LOGFONTW *)&logfont.elfLogFont;
734 ptm = (TEXTMETRICW *)&tmA;
736 GDI_ReleaseObj( pfe->hdc ); /* release the GDI lock */
738 ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
740 /* get the lock again and make sure the DC is still valid */
741 dc = DC_GetDCPtr( pfe->hdc );
742 if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
744 if (dc) GDI_ReleaseObj( pfe->hdc );
745 pfe->hdc = 0; /* make sure we don't try to release it later on */
752 /***********************************************************************
753 * EnumFontFamiliesEx (GDI.613)
755 INT16 WINAPI EnumFontFamiliesEx16( HDC16 hDC, LPLOGFONT16 plf,
756 FONTENUMPROC16 efproc, LPARAM lParam,
761 DC* dc = DC_GetDCPtr( HDC_32(hDC) );
762 NEWTEXTMETRICEX16 tm16;
763 ENUMLOGFONTEX16 lf16;
768 FONT_LogFont16ToW(plf, &lfW);
770 fe16.hdc = HDC_32(hDC);
772 fe16.physDev = dc->physDev;
773 fe16.lpLogFontParam = plf;
774 fe16.lpEnumFunc = efproc;
775 fe16.lpData = lParam;
776 fe16.lpTextMetric = &tm16;
777 fe16.lpLogFont = &lf16;
778 fe16.segTextMetric = MapLS( &tm16 );
779 fe16.segLogFont = MapLS( &lf16 );
782 enum_gdi_fonts = GetDeviceCaps(fe16.hdc, TEXTCAPS) & TC_VA_ABLE;
784 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
791 ret = WineEngEnumFonts( &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
792 fe16.dwFlags &= ~ENUM_CALLED;
793 if (ret && dc->funcs->pEnumDeviceFonts) {
794 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
795 if(fe16.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
799 UnMapLS( fe16.segTextMetric );
800 UnMapLS( fe16.segLogFont );
801 if (fe16.hdc) GDI_ReleaseObj( fe16.hdc );
805 /***********************************************************************
806 * FONT_EnumFontFamiliesEx
808 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf,
809 FONTENUMPROCW efproc,
810 LPARAM lParam, DWORD dwUnicode)
813 DC *dc = DC_GetDCPtr( hDC );
819 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName),
821 fe32.lpLogFontParam = plf;
822 fe32.lpEnumFunc = efproc;
823 fe32.lpData = lParam;
824 fe32.dwFlags = dwUnicode;
827 fe32.physDev = dc->physDev;
829 enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE;
831 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
838 ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
839 fe32.dwFlags &= ~ENUM_CALLED;
840 if (ret && dc->funcs->pEnumDeviceFonts) {
841 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, plf, FONT_EnumInstance, (LPARAM)&fe32 );
842 if(fe32.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
846 if (fe32.hdc) GDI_ReleaseObj( fe32.hdc );
850 /***********************************************************************
851 * EnumFontFamiliesExW (GDI32.@)
853 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
854 FONTENUMPROCW efproc,
855 LPARAM lParam, DWORD dwFlags )
857 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, ENUM_UNICODE );
860 /***********************************************************************
861 * EnumFontFamiliesExA (GDI32.@)
863 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
864 FONTENUMPROCA efproc,
865 LPARAM lParam, DWORD dwFlags)
868 FONT_LogFontAToW( plf, &lfW );
870 return FONT_EnumFontFamiliesEx( hDC, &lfW, (FONTENUMPROCW)efproc, lParam, 0);
873 /***********************************************************************
874 * EnumFontFamilies (GDI.330)
876 INT16 WINAPI EnumFontFamilies16( HDC16 hDC, LPCSTR lpFamily,
877 FONTENUMPROC16 efproc, LPARAM lpData )
881 lf.lfCharSet = DEFAULT_CHARSET;
882 if( lpFamily ) lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
883 else lf.lfFaceName[0] = '\0';
885 return EnumFontFamiliesEx16( hDC, &lf, efproc, lpData, 0 );
888 /***********************************************************************
889 * EnumFontFamiliesA (GDI32.@)
891 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
892 FONTENUMPROCA efproc, LPARAM lpData )
896 lf.lfCharSet = DEFAULT_CHARSET;
897 if( lpFamily ) lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
898 else lf.lfFaceName[0] = lf.lfFaceName[1] = '\0';
900 return EnumFontFamiliesExA( hDC, &lf, efproc, lpData, 0 );
903 /***********************************************************************
904 * EnumFontFamiliesW (GDI32.@)
906 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
907 FONTENUMPROCW efproc, LPARAM lpData )
911 lf.lfCharSet = DEFAULT_CHARSET;
912 if( lpFamily ) lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
913 else lf.lfFaceName[0] = 0;
915 return EnumFontFamiliesExW( hDC, &lf, efproc, lpData, 0 );
918 /***********************************************************************
921 INT16 WINAPI EnumFonts16( HDC16 hDC, LPCSTR lpName, FONTENUMPROC16 efproc,
924 return EnumFontFamilies16( hDC, lpName, efproc, lpData );
927 /***********************************************************************
928 * EnumFontsA (GDI32.@)
930 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
933 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
936 /***********************************************************************
937 * EnumFontsW (GDI32.@)
939 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
942 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
946 /***********************************************************************
947 * GetTextCharacterExtra (GDI32.@)
949 INT WINAPI GetTextCharacterExtra( HDC hdc )
952 DC *dc = DC_GetDCPtr( hdc );
953 if (!dc) return 0x80000000;
955 GDI_ReleaseObj( hdc );
960 /***********************************************************************
961 * SetTextCharacterExtra (GDI32.@)
963 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
966 DC * dc = DC_GetDCPtr( hdc );
967 if (!dc) return 0x80000000;
968 if (dc->funcs->pSetTextCharacterExtra)
969 prev = dc->funcs->pSetTextCharacterExtra( dc->physDev, extra );
972 prev = dc->charExtra;
973 dc->charExtra = extra;
975 GDI_ReleaseObj( hdc );
980 /***********************************************************************
981 * SetTextJustification (GDI32.@)
983 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
986 DC * dc = DC_GetDCPtr( hdc );
987 if (!dc) return FALSE;
988 if (dc->funcs->pSetTextJustification)
989 ret = dc->funcs->pSetTextJustification( dc->physDev, extra, breaks );
992 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
993 if (!extra) breaks = 0;
996 dc->breakExtra = extra / breaks;
997 dc->breakRem = extra - (breaks * dc->breakExtra);
1005 GDI_ReleaseObj( hdc );
1010 /***********************************************************************
1011 * GetTextFaceA (GDI32.@)
1013 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
1015 INT res = GetTextFaceW(hdc, 0, NULL);
1016 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
1017 GetTextFaceW( hdc, res, nameW );
1021 if (count && !WideCharToMultiByte( CP_ACP, 0, nameW, -1, name, count, NULL, NULL))
1026 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
1027 HeapFree( GetProcessHeap(), 0, nameW );
1031 /***********************************************************************
1032 * GetTextFaceW (GDI32.@)
1034 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
1039 DC * dc = DC_GetDCPtr( hdc );
1043 ret = WineEngGetTextFace(dc->gdiFont, count, name);
1044 else if ((font = (FONTOBJ *) GDI_GetObjPtr( dc->hFont, FONT_MAGIC )))
1048 lstrcpynW( name, font->logfont.lfFaceName, count );
1049 ret = strlenW(name);
1051 else ret = strlenW(font->logfont.lfFaceName) + 1;
1052 GDI_ReleaseObj( dc->hFont );
1054 GDI_ReleaseObj( hdc );
1059 /***********************************************************************
1060 * GetTextExtentPoint32A (GDI32.@)
1062 * See GetTextExtentPoint32W.
1064 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
1069 LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1072 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
1073 HeapFree( GetProcessHeap(), 0, p );
1076 TRACE("(%p %s %d %p): returning %ld x %ld\n",
1077 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
1082 /***********************************************************************
1083 * GetTextExtentPoint32W [GDI32.@]
1085 * Computes width/height for a string.
1087 * Computes width and height of the specified string.
1093 BOOL WINAPI GetTextExtentPoint32W(
1094 HDC hdc, /* [in] Handle of device context */
1095 LPCWSTR str, /* [in] Address of text string */
1096 INT count, /* [in] Number of characters in string */
1097 LPSIZE size) /* [out] Address of structure for string size */
1100 DC * dc = DC_GetDCPtr( hdc );
1101 if (!dc) return FALSE;
1104 ret = WineEngGetTextExtentPoint(dc->gdiFont, str, count, size);
1105 else if(dc->funcs->pGetTextExtentPoint)
1106 ret = dc->funcs->pGetTextExtentPoint( dc->physDev, str, count, size );
1110 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1111 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1112 size->cx += count * dc->charExtra + dc->breakRem;
1115 GDI_ReleaseObj( hdc );
1117 TRACE("(%p %s %d %p): returning %ld x %ld\n",
1118 hdc, debugstr_wn (str, count), count, size, size->cx, size->cy );
1122 /***********************************************************************
1123 * GetTextExtentPointI [GDI32.@]
1125 * Computes width and height of the array of glyph indices.
1131 BOOL WINAPI GetTextExtentPointI(
1132 HDC hdc, /* [in] Handle of device context */
1133 const WORD *indices, /* [in] Address of glyph index array */
1134 INT count, /* [in] Number of glyphs in array */
1135 LPSIZE size) /* [out] Address of structure for string size */
1138 DC * dc = DC_GetDCPtr( hdc );
1139 if (!dc) return FALSE;
1142 ret = WineEngGetTextExtentPointI(dc->gdiFont, indices, count, size);
1143 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1144 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1145 size->cx += count * dc->charExtra;
1147 else if(dc->funcs->pGetTextExtentPoint) {
1148 FIXME("calling GetTextExtentPoint\n");
1149 ret = dc->funcs->pGetTextExtentPoint( dc->physDev, (LPCWSTR)indices, count, size );
1152 GDI_ReleaseObj( hdc );
1154 TRACE("(%p %p %d %p): returning %ld x %ld\n",
1155 hdc, indices, count, size, size->cx, size->cy );
1160 /***********************************************************************
1161 * GetTextExtentPointA (GDI32.@)
1163 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
1166 TRACE("not bug compatible.\n");
1167 return GetTextExtentPoint32A( hdc, str, count, size );
1170 /***********************************************************************
1171 * GetTextExtentPointW (GDI32.@)
1173 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1176 TRACE("not bug compatible.\n");
1177 return GetTextExtentPoint32W( hdc, str, count, size );
1181 /***********************************************************************
1182 * GetTextExtentExPointA (GDI32.@)
1184 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1185 INT maxExt, LPINT lpnFit,
1186 LPINT alpDx, LPSIZE size )
1190 LPWSTR p = FONT_mbtowc( hdc, str, count, &wlen, NULL);
1191 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, alpDx, size);
1192 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1193 HeapFree( GetProcessHeap(), 0, p );
1198 /***********************************************************************
1199 * GetTextExtentExPointW (GDI32.@)
1201 * Return the size of the string as it would be if it was output properly by
1204 * This should include
1205 * - Intercharacter spacing
1206 * - justification spacing (not yet done)
1207 * - kerning? see below
1209 * Kerning. Since kerning would be carried out by the rendering code it should
1210 * be done by the driver. However they don't support it yet. Also I am not
1211 * yet persuaded that (certainly under Win95) any kerning is actually done.
1213 * str: According to MSDN this should be null-terminated. That is not true; a
1214 * null will not terminate it early.
1215 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1216 * than count. I have seen it be either the size of the full string or
1217 * 1 less than the size of the full string. I have not seen it bear any
1218 * resemblance to the portion that would fit.
1219 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1220 * trailing intercharacter spacing and any trailing justification.
1223 * Currently we do this by measuring each character etc. We should do it by
1224 * passing the request to the driver, perhaps by extending the
1225 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1226 * thinking about kerning issues and rounding issues in the justification.
1229 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1230 INT maxExt, LPINT lpnFit,
1231 LPINT alpDx, LPSIZE size )
1233 int index, nFit, extent;
1237 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1239 size->cx = size->cy = nFit = extent = 0;
1240 for(index = 0; index < count; index++)
1242 if(!GetTextExtentPoint32W( hdc, str, 1, &tSize )) goto done;
1243 /* GetTextExtentPoint includes intercharacter spacing. */
1244 /* FIXME - justification needs doing yet. Remember that the base
1245 * data will not be in logical coordinates.
1248 if( !lpnFit || extent <= maxExt )
1249 /* It is allowed to be equal. */
1252 if( alpDx ) alpDx[index] = extent;
1254 if( tSize.cy > size->cy ) size->cy = tSize.cy;
1258 if(lpnFit) *lpnFit = nFit;
1261 TRACE("returning %d %ld x %ld\n",nFit,size->cx,size->cy);
1267 /***********************************************************************
1268 * GetTextMetricsA (GDI32.@)
1270 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1274 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1275 FONT_TextMetricWToA( &tm32, metrics );
1279 /***********************************************************************
1280 * GetTextMetricsW (GDI32.@)
1282 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1285 DC * dc = DC_GetDCPtr( hdc );
1286 if (!dc) return FALSE;
1289 ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1290 else if (dc->funcs->pGetTextMetrics)
1291 ret = dc->funcs->pGetTextMetrics( dc->physDev, metrics );
1295 /* device layer returns values in device units
1296 * therefore we have to convert them to logical */
1298 #define WDPTOLP(x) ((x<0)? \
1299 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1300 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1301 #define HDPTOLP(y) ((y<0)? \
1302 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1303 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1305 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1306 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1307 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1308 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1309 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1310 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1311 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1312 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1316 TRACE("text metrics:\n"
1317 " Weight = %03li\t FirstChar = %i\t AveCharWidth = %li\n"
1318 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %li\n"
1319 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %li\n"
1320 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1321 " PitchAndFamily = %02x\n"
1322 " --------------------\n"
1323 " InternalLeading = %li\n"
1327 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1328 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1329 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1330 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1331 metrics->tmPitchAndFamily,
1332 metrics->tmInternalLeading,
1335 metrics->tmHeight );
1337 GDI_ReleaseObj( hdc );
1342 /***********************************************************************
1343 * GetOutlineTextMetrics [GDI.308] Gets metrics for TrueType fonts.
1346 * lpOTM should be LPOUTLINETEXTMETRIC
1349 * Success: Non-zero or size of required buffer
1352 UINT16 WINAPI GetOutlineTextMetrics16(
1353 HDC16 hdc, /* [in] Handle of device context */
1354 UINT16 cbData, /* [in] Size of metric data array */
1355 LPOUTLINETEXTMETRIC16 lpOTM) /* [out] Address of metric data array */
1357 FIXME("(%04x,%04x,%p): stub\n", hdc,cbData,lpOTM);
1362 /***********************************************************************
1363 * GetOutlineTextMetricsA (GDI32.@)
1364 * Gets metrics for TrueType fonts.
1367 * If the supplied buffer isn't big enough Windows partially fills it up to
1368 * its given length and returns that length.
1371 * Success: Non-zero or size of required buffer
1374 UINT WINAPI GetOutlineTextMetricsA(
1375 HDC hdc, /* [in] Handle of device context */
1376 UINT cbData, /* [in] Size of metric data array */
1377 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1379 char buf[512], *ptr;
1381 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1382 OUTLINETEXTMETRICA *output = lpOTM;
1385 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1387 if(ret > sizeof(buf))
1388 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1389 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1391 needed = sizeof(OUTLINETEXTMETRICA);
1392 if(lpOTMW->otmpFamilyName)
1393 needed += WideCharToMultiByte(CP_ACP, 0,
1394 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1395 NULL, 0, NULL, NULL);
1396 if(lpOTMW->otmpFaceName)
1397 needed += WideCharToMultiByte(CP_ACP, 0,
1398 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1399 NULL, 0, NULL, NULL);
1400 if(lpOTMW->otmpStyleName)
1401 needed += WideCharToMultiByte(CP_ACP, 0,
1402 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1403 NULL, 0, NULL, NULL);
1404 if(lpOTMW->otmpFullName)
1405 needed += WideCharToMultiByte(CP_ACP, 0,
1406 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1407 NULL, 0, NULL, NULL);
1414 TRACE("needed = %d\n", needed);
1416 /* Since the supplied buffer isn't big enough, we'll alloc one
1417 that is and memcpy the first cbData bytes into the lpOTM at
1419 output = HeapAlloc(GetProcessHeap(), 0, needed);
1421 ret = output->otmSize = min(needed, cbData);
1422 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1423 output->otmFiller = 0;
1424 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1425 output->otmfsSelection = lpOTMW->otmfsSelection;
1426 output->otmfsType = lpOTMW->otmfsType;
1427 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1428 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1429 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1430 output->otmEMSquare = lpOTMW->otmEMSquare;
1431 output->otmAscent = lpOTMW->otmAscent;
1432 output->otmDescent = lpOTMW->otmDescent;
1433 output->otmLineGap = lpOTMW->otmLineGap;
1434 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1435 output->otmsXHeight = lpOTMW->otmsXHeight;
1436 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1437 output->otmMacAscent = lpOTMW->otmMacAscent;
1438 output->otmMacDescent = lpOTMW->otmMacDescent;
1439 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1440 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1441 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1442 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1443 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1444 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1445 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1446 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1447 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1448 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1451 ptr = (char*)(output + 1);
1452 left = needed - sizeof(*output);
1454 if(lpOTMW->otmpFamilyName) {
1455 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1456 len = WideCharToMultiByte(CP_ACP, 0,
1457 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1458 ptr, left, NULL, NULL);
1462 output->otmpFamilyName = 0;
1464 if(lpOTMW->otmpFaceName) {
1465 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1466 len = WideCharToMultiByte(CP_ACP, 0,
1467 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1468 ptr, left, NULL, NULL);
1472 output->otmpFaceName = 0;
1474 if(lpOTMW->otmpStyleName) {
1475 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1476 len = WideCharToMultiByte(CP_ACP, 0,
1477 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1478 ptr, left, NULL, NULL);
1482 output->otmpStyleName = 0;
1484 if(lpOTMW->otmpFullName) {
1485 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1486 len = WideCharToMultiByte(CP_ACP, 0,
1487 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1488 ptr, left, NULL, NULL);
1491 output->otmpFullName = 0;
1495 if(output != lpOTM) {
1496 memcpy(lpOTM, output, cbData);
1497 HeapFree(GetProcessHeap(), 0, output);
1501 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1502 HeapFree(GetProcessHeap(), 0, lpOTMW);
1508 /***********************************************************************
1509 * GetOutlineTextMetricsW [GDI32.@]
1511 UINT WINAPI GetOutlineTextMetricsW(
1512 HDC hdc, /* [in] Handle of device context */
1513 UINT cbData, /* [in] Size of metric data array */
1514 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1516 DC *dc = DC_GetDCPtr( hdc );
1517 OUTLINETEXTMETRICW *output = lpOTM;
1520 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1524 ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, output);
1527 output = HeapAlloc(GetProcessHeap(), 0, ret);
1528 WineEngGetOutlineTextMetrics(dc->gdiFont, ret, output);
1531 #define WDPTOLP(x) ((x<0)? \
1532 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1533 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1534 #define HDPTOLP(y) ((y<0)? \
1535 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1536 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1538 output->otmTextMetrics.tmHeight = HDPTOLP(output->otmTextMetrics.tmHeight);
1539 output->otmTextMetrics.tmAscent = HDPTOLP(output->otmTextMetrics.tmAscent);
1540 output->otmTextMetrics.tmDescent = HDPTOLP(output->otmTextMetrics.tmDescent);
1541 output->otmTextMetrics.tmInternalLeading = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1542 output->otmTextMetrics.tmExternalLeading = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1543 output->otmTextMetrics.tmAveCharWidth = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1544 output->otmTextMetrics.tmMaxCharWidth = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1545 output->otmTextMetrics.tmOverhang = WDPTOLP(output->otmTextMetrics.tmOverhang);
1546 output->otmAscent = HDPTOLP(output->otmAscent);
1547 output->otmDescent = HDPTOLP(output->otmDescent);
1548 output->otmLineGap = HDPTOLP(output->otmLineGap);
1549 output->otmsCapEmHeight = HDPTOLP(output->otmsCapEmHeight);
1550 output->otmsXHeight = HDPTOLP(output->otmsXHeight);
1551 output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1552 output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1553 output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1554 output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1555 output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1556 output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1557 output->otmMacLineGap = HDPTOLP(output->otmMacLineGap);
1558 output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1559 output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1560 output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1561 output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1562 output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1563 output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1564 output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1565 output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1566 output->otmsStrikeoutSize = HDPTOLP(output->otmsStrikeoutSize);
1567 output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1568 output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1569 output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1572 if(output != lpOTM) {
1573 memcpy(lpOTM, output, cbData);
1574 HeapFree(GetProcessHeap(), 0, output);
1580 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1581 but really this should just be a return 0. */
1583 ret = sizeof(*lpOTM);
1588 memset(lpOTM, 0, ret);
1589 lpOTM->otmSize = sizeof(*lpOTM);
1590 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1592 Further fill of the structure not implemented,
1593 Needs real values for the structure members
1598 GDI_ReleaseObj(hdc);
1603 /***********************************************************************
1604 * GetCharWidthW (GDI32.@)
1605 * GetCharWidth32W (GDI32.@)
1607 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1612 DC * dc = DC_GetDCPtr( hdc );
1613 if (!dc) return FALSE;
1616 ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1617 else if (dc->funcs->pGetCharWidth)
1618 ret = dc->funcs->pGetCharWidth( dc->physDev, firstChar, lastChar, buffer);
1622 /* convert device units to logical */
1623 for( i = firstChar; i <= lastChar; i++, buffer++ )
1624 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1627 GDI_ReleaseObj( hdc );
1632 /***********************************************************************
1633 * GetCharWidthA (GDI32.@)
1634 * GetCharWidth32A (GDI32.@)
1636 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1639 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1644 if(count <= 0) return FALSE;
1646 str = HeapAlloc(GetProcessHeap(), 0, count);
1647 for(i = 0; i < count; i++)
1648 str[i] = (BYTE)(firstChar + i);
1650 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1652 for(i = 0; i < wlen; i++)
1654 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1662 HeapFree(GetProcessHeap(), 0, str);
1663 HeapFree(GetProcessHeap(), 0, wstr);
1669 /***********************************************************************
1670 * ExtTextOutA (GDI32.@)
1674 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1675 const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1683 if (flags & ETO_GLYPH_INDEX)
1684 return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
1686 p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
1689 unsigned int i = 0, j = 0;
1691 lpDxW = HeapAlloc( GetProcessHeap(), 0, wlen*sizeof(INT));
1693 if(IsDBCSLeadByteEx(codepage, str[i])) {
1694 lpDxW[j++] = lpDx[i] + lpDx[i+1];
1697 lpDxW[j++] = lpDx[i];
1703 ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1705 HeapFree( GetProcessHeap(), 0, p );
1706 HeapFree( GetProcessHeap(), 0, lpDxW );
1711 /***********************************************************************
1712 * ExtTextOutW (GDI32.@)
1714 * Draws text using the currently selected font, background color, and text color.
1718 * x,y [I] coordinates of string
1720 * ETO_GRAYED - undocumented on MSDN
1721 * ETO_OPAQUE - use background color for fill the rectangle
1722 * ETO_CLIPPED - clipping text to the rectangle
1723 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1724 * than encoded characters. Implies ETO_IGNORELANGUAGE
1725 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1726 * Affects BiDi ordering
1727 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1728 * ETO_PDY - unimplemented
1729 * ETO_NUMERICSLATIN - unimplemented always assumed -
1730 * do not translate numbers into locale representations
1731 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1732 * lprect [I] dimensions for clipping or/and opaquing
1733 * str [I] text string
1734 * count [I] number of symbols in string
1735 * lpDx [I] optional parameter with distance between drawing characters
1741 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1742 const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1745 LPWSTR reordered_str = (LPWSTR)str;
1746 WORD *glyphs = NULL;
1747 UINT align = GetTextAlign( hdc );
1751 double cosEsc, sinEsc;
1752 INT *deltas = NULL, char_extra;
1755 BOOL done_extents = FALSE;
1756 INT width, xwidth = 0, ywidth = 0;
1758 DC * dc = DC_GetDCUpdate( hdc );
1760 if (!dc) return FALSE;
1762 if (flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY))
1763 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY unimplemented\n");
1765 if (!dc->funcs->pExtTextOut && !PATH_IsPathOpen(dc->path))
1767 GDI_ReleaseObj( hdc );
1771 type = GetObjectType(hdc);
1772 if(type == OBJ_METADC || type == OBJ_ENHMETADC)
1774 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, flags, lprect, str, count, lpDx);
1775 GDI_ReleaseObj( hdc );
1779 if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && BidiAvail && count > 0 )
1781 reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1783 BIDI_Reorder( str, count, GCP_REORDER,
1784 ((flags&ETO_RTLREADING)!=0 || (GetTextAlign(hdc)&TA_RTLREADING)!=0)?
1785 WINE_GCPW_FORCE_RTL:WINE_GCPW_FORCE_LTR,
1786 reordered_str, count, NULL );
1788 flags |= ETO_IGNORELANGUAGE;
1791 TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc, x, y, flags,
1792 lprect, debugstr_wn(str, count), count, lpDx);
1794 if(flags & ETO_GLYPH_INDEX)
1795 glyphs = reordered_str;
1798 TRACE("rect: %ld,%ld - %ld,%ld\n", lprect->left, lprect->top, lprect->right,
1800 TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
1802 if(align & TA_UPDATECP)
1804 GetCurrentPositionEx( hdc, &pt );
1809 GetTextMetricsW(hdc, &tm);
1810 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1812 if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
1813 lf.lfEscapement = 0;
1815 if(lf.lfEscapement != 0)
1817 cosEsc = cos(lf.lfEscapement * M_PI / 1800);
1818 sinEsc = sin(lf.lfEscapement * M_PI / 1800);
1826 if(flags & (ETO_CLIPPED | ETO_OPAQUE))
1830 if(flags & ETO_CLIPPED) goto done;
1831 if(flags & ETO_GLYPH_INDEX)
1832 GetTextExtentPointI(hdc, glyphs, count, &sz);
1834 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1836 done_extents = TRUE;
1839 rc.right = x + sz.cx;
1840 rc.bottom = y + sz.cy;
1847 LPtoDP(hdc, (POINT*)&rc, 2);
1849 if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
1850 if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
1853 if ((flags & ETO_OPAQUE) && !PATH_IsPathOpen(dc->path))
1854 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1864 LPtoDP(hdc, &pt, 1);
1868 char_extra = GetTextCharacterExtra(hdc);
1870 if(char_extra || dc->breakExtra || lpDx)
1874 deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT));
1875 for(i = 0; i < count; i++)
1878 deltas[i] = lpDx[i] + char_extra;
1881 if(flags & ETO_GLYPH_INDEX)
1882 GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
1884 GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
1886 deltas[i] = tmpsz.cx;
1889 if (!(flags & ETO_GLYPH_INDEX) && dc->breakExtra && reordered_str[i] == tm.tmBreakChar)
1891 deltas[i] = deltas[i] + dc->breakExtra;
1893 deltas[i] = INTERNAL_XWSTODS(dc, deltas[i]);
1901 if(flags & ETO_GLYPH_INDEX)
1902 GetTextExtentPointI(hdc, glyphs, count, &sz);
1904 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1905 done_extents = TRUE;
1907 width = INTERNAL_XWSTODS(dc, sz.cx);
1909 xwidth = width * cosEsc;
1910 ywidth = width * sinEsc;
1912 tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
1913 tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
1914 switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
1917 if (align & TA_UPDATECP)
1921 DPtoLP(hdc, &pt, 1);
1922 MoveToEx(hdc, pt.x, pt.y, NULL);
1934 if (align & TA_UPDATECP)
1938 DPtoLP(hdc, &pt, 1);
1939 MoveToEx(hdc, pt.x, pt.y, NULL);
1944 switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
1947 y += tm.tmAscent * cosEsc;
1948 x += tm.tmAscent * sinEsc;
1952 y -= tm.tmDescent * cosEsc;
1953 x -= tm.tmDescent * sinEsc;
1960 if (GetBkMode(hdc) != TRANSPARENT && !PATH_IsPathOpen(dc->path))
1962 if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
1964 if(!(flags & ETO_OPAQUE) || x < rc.left || x + width >= rc.right ||
1965 y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
1969 rc.right = x + width;
1970 rc.top = y - tm.tmAscent;
1971 rc.bottom = y + tm.tmDescent;
1972 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1977 if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
1979 HFONT orig_font = dc->hFont, cur_font;
1981 INT span = 0, *offsets = NULL, i;
1983 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
1984 for(i = 0; i < count; i++)
1986 WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
1987 if(cur_font != dc->hFont)
1992 offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
1997 for(j = 1; j < count; j++)
1999 GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
2000 offsets[j] = offsets[j-1] + INTERNAL_XWSTODS(dc, tmpsz.cx);
2005 for(j = 1; j < count; j++)
2006 offsets[j] = offsets[j-1] + deltas[j];
2011 if (PATH_IsPathOpen(dc->path))
2012 ret = PATH_ExtTextOut(dc, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
2013 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2014 glyphs, span, deltas ? deltas + i - span : NULL);
2016 dc->funcs->pExtTextOut(dc->physDev, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
2017 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2018 glyphs, span, deltas ? deltas + i - span : NULL);
2021 SelectObject(hdc, cur_font);
2023 glyphs[span++] = glyph;
2027 if (PATH_IsPathOpen(dc->path))
2028 ret = PATH_ExtTextOut(dc, x + (offsets ? offsets[count - span] * cosEsc : 0),
2029 y - (offsets ? offsets[count - span] * sinEsc : 0),
2030 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2031 glyphs, span, deltas ? deltas + count - span : NULL);
2033 ret = dc->funcs->pExtTextOut(dc->physDev, x + (offsets ? offsets[count - span] * cosEsc : 0),
2034 y - (offsets ? offsets[count - span] * sinEsc : 0),
2035 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2036 glyphs, span, deltas ? deltas + count - span : NULL);
2037 SelectObject(hdc, orig_font);
2038 HeapFree(GetProcessHeap(), 0, offsets);
2044 if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
2046 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2047 GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
2048 flags |= ETO_GLYPH_INDEX;
2051 if (PATH_IsPathOpen(dc->path))
2052 ret = PATH_ExtTextOut(dc, x, y, (flags & ~ETO_OPAQUE), &rc,
2053 glyphs ? glyphs : reordered_str, count, deltas);
2055 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, (flags & ~ETO_OPAQUE), &rc,
2056 glyphs ? glyphs : reordered_str, count, deltas);
2060 HeapFree(GetProcessHeap(), 0, deltas);
2061 if(glyphs != reordered_str)
2062 HeapFree(GetProcessHeap(), 0, glyphs);
2063 if(reordered_str != str)
2064 HeapFree(GetProcessHeap(), 0, reordered_str);
2066 GDI_ReleaseObj( hdc );
2068 if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2070 int underlinePos, strikeoutPos;
2071 int underlineWidth, strikeoutWidth;
2072 UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2073 OUTLINETEXTMETRICW* otm = NULL;
2078 underlineWidth = tm.tmAscent / 20 + 1;
2079 strikeoutPos = tm.tmAscent / 2;
2080 strikeoutWidth = underlineWidth;
2084 otm = HeapAlloc(GetProcessHeap(), 0, size);
2085 GetOutlineTextMetricsW(hdc, size, otm);
2086 underlinePos = otm->otmsUnderscorePosition;
2087 underlineWidth = otm->otmsUnderscoreSize;
2088 strikeoutPos = otm->otmsStrikeoutPosition;
2089 strikeoutWidth = otm->otmsStrikeoutSize;
2090 HeapFree(GetProcessHeap(), 0, otm);
2093 if (PATH_IsPathOpen(dc->path))
2097 HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2099 hbrush = SelectObject(hdc, hbrush);
2100 hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2104 pts[0].x = x - underlinePos * sinEsc;
2105 pts[0].y = y - underlinePos * cosEsc;
2106 pts[1].x = x + xwidth - underlinePos * sinEsc;
2107 pts[1].y = y - ywidth - underlinePos * cosEsc;
2108 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2109 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2110 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2111 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2112 pts[4].x = pts[0].x;
2113 pts[4].y = pts[0].y;
2114 DPtoLP(hdc, pts, 5);
2115 Polygon(hdc, pts, 5);
2120 pts[0].x = x - strikeoutPos * sinEsc;
2121 pts[0].y = y - strikeoutPos * cosEsc;
2122 pts[1].x = x + xwidth - strikeoutPos * sinEsc;
2123 pts[1].y = y - ywidth - strikeoutPos * cosEsc;
2124 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2125 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2126 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2127 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2128 pts[4].x = pts[0].x;
2129 pts[4].y = pts[0].y;
2130 DPtoLP(hdc, pts, 5);
2131 Polygon(hdc, pts, 5);
2134 SelectObject(hdc, hpen);
2135 hbrush = SelectObject(hdc, hbrush);
2136 DeleteObject(hbrush);
2140 POINT pts[2], oldpt;
2145 hpen = CreatePen(PS_SOLID, underlineWidth, GetTextColor(hdc));
2146 hpen = SelectObject(hdc, hpen);
2149 pts[1].x = x + xwidth;
2150 pts[1].y = y - ywidth;
2151 DPtoLP(hdc, pts, 2);
2152 MoveToEx(hdc, pts[0].x - underlinePos * sinEsc, pts[0].y - underlinePos * cosEsc, &oldpt);
2153 LineTo(hdc, pts[1].x - underlinePos * sinEsc, pts[1].y - underlinePos * cosEsc);
2154 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2155 DeleteObject(SelectObject(hdc, hpen));
2160 hpen = CreatePen(PS_SOLID, strikeoutWidth, GetTextColor(hdc));
2161 hpen = SelectObject(hdc, hpen);
2164 pts[1].x = x + xwidth;
2165 pts[1].y = y - ywidth;
2166 DPtoLP(hdc, pts, 2);
2167 MoveToEx(hdc, pts[0].x - strikeoutPos * sinEsc, pts[0].y - strikeoutPos * cosEsc, &oldpt);
2168 LineTo(hdc, pts[1].x - strikeoutPos * sinEsc, pts[1].y - strikeoutPos * cosEsc);
2169 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2170 DeleteObject(SelectObject(hdc, hpen));
2179 /***********************************************************************
2180 * TextOutA (GDI32.@)
2182 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2184 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2188 /***********************************************************************
2189 * TextOutW (GDI32.@)
2191 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2193 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2197 /***********************************************************************
2198 * PolyTextOutA (GDI32.@)
2202 BOOL WINAPI PolyTextOutA ( HDC hdc, /* [in] Handle to device context */
2203 PPOLYTEXTA pptxt, /* [in] Array of strings */
2204 INT cStrings ) /* [in] Number of strings in array */
2206 for (; cStrings>0; cStrings--, pptxt++)
2207 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2214 /***********************************************************************
2215 * PolyTextOutW (GDI32.@)
2217 * Draw several Strings
2223 BOOL WINAPI PolyTextOutW ( HDC hdc, /* [in] Handle to device context */
2224 PPOLYTEXTW pptxt, /* [in] Array of strings */
2225 INT cStrings ) /* [in] Number of strings in array */
2227 for (; cStrings>0; cStrings--, pptxt++)
2228 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2234 /* FIXME: all following APIs ******************************************/
2237 /***********************************************************************
2238 * SetMapperFlags (GDI32.@)
2240 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
2242 DC *dc = DC_GetDCPtr( hDC );
2245 if(dc->funcs->pSetMapperFlags)
2247 ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
2248 /* FIXME: ret is just a success flag, we should return a proper value */
2251 FIXME("(%p, 0x%08lx): stub - harmless\n", hDC, dwFlag);
2252 GDI_ReleaseObj( hDC );
2256 /***********************************************************************
2257 * GetAspectRatioFilterEx (GDI.486)
2259 BOOL16 WINAPI GetAspectRatioFilterEx16( HDC16 hdc, LPSIZE16 pAspectRatio )
2261 FIXME("(%04x, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2265 /***********************************************************************
2266 * GetAspectRatioFilterEx (GDI32.@)
2268 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2270 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2275 /***********************************************************************
2276 * GetCharABCWidthsA (GDI32.@)
2278 * See GetCharABCWidthsW.
2280 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2283 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
2288 if(count <= 0) return FALSE;
2290 str = HeapAlloc(GetProcessHeap(), 0, count);
2291 for(i = 0; i < count; i++)
2292 str[i] = (BYTE)(firstChar + i);
2294 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
2296 for(i = 0; i < wlen; i++)
2298 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2306 HeapFree(GetProcessHeap(), 0, str);
2307 HeapFree(GetProcessHeap(), 0, wstr);
2313 /******************************************************************************
2314 * GetCharABCWidthsW [GDI32.@]
2316 * Retrieves widths of characters in range.
2319 * hdc [I] Handle of device context
2320 * firstChar [I] First character in range to query
2321 * lastChar [I] Last character in range to query
2322 * abc [O] Address of character-width structure
2325 * Only works with TrueType fonts
2331 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2334 DC *dc = DC_GetDCPtr(hdc);
2338 if (!dc) return FALSE;
2341 ret = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
2347 /* convert device units to logical */
2348 for( i = firstChar; i <= lastChar; i++, abc++ ) {
2349 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2350 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2351 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2356 GDI_ReleaseObj(hdc);
2361 /***********************************************************************
2362 * GetGlyphOutlineA (GDI32.@)
2364 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2365 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2366 LPVOID lpBuffer, const MAT2 *lpmat2 )
2372 if(!(fuFormat & GGO_GLYPH_INDEX)) {
2375 if(uChar > 0xff) { /* but, 2 bytes character only */
2377 mbchs[0] = (uChar & 0xff00) >> 8;
2378 mbchs[1] = (uChar & 0xff);
2381 mbchs[0] = (uChar & 0xff);
2383 p = FONT_mbtowc(hdc, mbchs, len, NULL, NULL);
2387 ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
2389 HeapFree(GetProcessHeap(), 0, p);
2393 /***********************************************************************
2394 * GetGlyphOutlineW (GDI32.@)
2396 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2397 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2398 LPVOID lpBuffer, const MAT2 *lpmat2 )
2400 DC *dc = DC_GetDCPtr(hdc);
2403 TRACE("(%p, %04x, %04x, %p, %ld, %p, %p)\n",
2404 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2406 if(!dc) return GDI_ERROR;
2409 ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
2410 cbBuffer, lpBuffer, lpmat2);
2414 GDI_ReleaseObj(hdc);
2419 /***********************************************************************
2420 * CreateScalableFontResourceA (GDI32.@)
2422 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2423 LPCSTR lpszResourceFile,
2424 LPCSTR lpszFontFile,
2425 LPCSTR lpszCurrentPath )
2429 /* fHidden=1 - only visible for the calling app, read-only, not
2430 * enumbered with EnumFonts/EnumFontFamilies
2431 * lpszCurrentPath can be NULL
2433 FIXME("(%ld,%s,%s,%s): stub\n",
2434 fHidden, debugstr_a(lpszResourceFile), debugstr_a(lpszFontFile),
2435 debugstr_a(lpszCurrentPath) );
2437 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2438 if ((f = CreateFileA(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2440 SetLastError(ERROR_FILE_EXISTS);
2443 return FALSE; /* create failed */
2446 /***********************************************************************
2447 * CreateScalableFontResourceW (GDI32.@)
2449 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2450 LPCWSTR lpszResourceFile,
2451 LPCWSTR lpszFontFile,
2452 LPCWSTR lpszCurrentPath )
2454 FIXME("(%ld,%p,%p,%p): stub\n",
2455 fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
2456 return FALSE; /* create failed */
2459 /*************************************************************************
2460 * GetKerningPairsA (GDI32.@)
2462 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2463 LPKERNINGPAIR lpKerningPairs )
2465 return GetKerningPairsW( hDC, cPairs, lpKerningPairs );
2469 /*************************************************************************
2470 * GetKerningPairsW (GDI32.@)
2472 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2473 LPKERNINGPAIR lpKerningPairs )
2476 FIXME("(%p,%ld,%p): almost empty stub!\n", hDC, cPairs, lpKerningPairs);
2478 if(!lpKerningPairs) /* return the number of kerning pairs */
2481 for (i = 0; i < cPairs; i++)
2482 lpKerningPairs[i].iKernAmount = 0;
2486 /*************************************************************************
2487 * TranslateCharsetInfo [GDI32.@]
2489 * Fills a CHARSETINFO structure for a character set, code page, or
2490 * font. This allows making the correspondance between different labelings
2491 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2492 * of the same encoding.
2494 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2495 * only one codepage should be set in *lpSrc.
2498 * TRUE on success, FALSE on failure.
2501 BOOL WINAPI TranslateCharsetInfo(
2502 LPDWORD lpSrc, /* [in]
2503 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2504 if flags == TCI_SRCCHARSET: a character set value
2505 if flags == TCI_SRCCODEPAGE: a code page value
2507 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2508 DWORD flags /* [in] determines interpretation of lpSrc */)
2512 case TCI_SRCFONTSIG:
2513 while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
2515 case TCI_SRCCODEPAGE:
2516 while ((UINT) (lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
2518 case TCI_SRCCHARSET:
2519 while ((UINT) (lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
2524 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2525 memcpy(lpCs, &FONT_tci[index], sizeof(CHARSETINFO));
2529 /*************************************************************************
2530 * GetFontLanguageInfo (GDI32.@)
2532 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2534 FONTSIGNATURE fontsig;
2535 static const DWORD GCP_DBCS_MASK=0x003F0000,
2536 GCP_DIACRITIC_MASK=0x00000000,
2537 FLI_GLYPHS_MASK=0x00000000,
2538 GCP_GLYPHSHAPE_MASK=0x00000040,
2539 GCP_KASHIDA_MASK=0x00000000,
2540 GCP_LIGATE_MASK=0x00000000,
2541 GCP_USEKERNING_MASK=0x00000000,
2542 GCP_REORDER_MASK=0x00000060;
2546 GetTextCharsetInfo( hdc, &fontsig, 0 );
2547 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2549 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2552 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2553 result|=GCP_DIACRITIC;
2555 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2558 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2559 result|=GCP_GLYPHSHAPE;
2561 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2562 result|=GCP_KASHIDA;
2564 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2567 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2568 result|=GCP_USEKERNING;
2570 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2571 if( GetTextAlign( hdc) & TA_RTLREADING )
2572 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2573 result|=GCP_REORDER;
2579 /*************************************************************************
2580 * GetFontData [GDI32.@]
2582 * Retrieve data for TrueType font.
2586 * success: Number of bytes returned
2587 * failure: GDI_ERROR
2591 * Calls SetLastError()
2594 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2595 LPVOID buffer, DWORD length)
2597 DC *dc = DC_GetDCPtr(hdc);
2598 DWORD ret = GDI_ERROR;
2600 if(!dc) return GDI_ERROR;
2603 ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2605 GDI_ReleaseObj(hdc);
2609 /*************************************************************************
2610 * GetGlyphIndicesA [GDI32.@]
2612 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2613 LPWORD pgi, DWORD flags)
2619 TRACE("(%p, %s, %d, %p, 0x%lx)\n",
2620 hdc, debugstr_an(lpstr, count), count, pgi, flags);
2622 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2623 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2624 HeapFree(GetProcessHeap(), 0, lpstrW);
2629 /*************************************************************************
2630 * GetGlyphIndicesW [GDI32.@]
2632 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2633 LPWORD pgi, DWORD flags)
2635 DC *dc = DC_GetDCPtr(hdc);
2636 DWORD ret = GDI_ERROR;
2638 TRACE("(%p, %s, %d, %p, 0x%lx)\n",
2639 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2641 if(!dc) return GDI_ERROR;
2644 ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2646 GDI_ReleaseObj(hdc);
2650 /*************************************************************************
2651 * GetCharacterPlacementA [GDI32.@]
2653 * See GetCharacterPlacementW.
2656 * the web browser control of ie4 calls this with dwFlags=0
2659 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2660 INT nMaxExtent, GCP_RESULTSA *lpResults,
2665 GCP_RESULTSW resultsW;
2669 TRACE("%s, %d, %d, 0x%08lx\n",
2670 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2672 /* both structs are equal in size */
2673 memcpy(&resultsW, lpResults, sizeof(resultsW));
2675 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2676 if(lpResults->lpOutString)
2677 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2679 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2681 lpResults->nGlyphs = resultsW.nGlyphs;
2682 lpResults->nMaxFit = resultsW.nMaxFit;
2684 if(lpResults->lpOutString) {
2685 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2686 lpResults->lpOutString, uCount, NULL, NULL );
2689 HeapFree(GetProcessHeap(), 0, lpStringW);
2690 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2695 /*************************************************************************
2696 * GetCharacterPlacementW [GDI32.@]
2698 * Retrieve information about a string. This includes the width, reordering,
2699 * Glyphing and so on.
2703 * The width and height of the string if successful, 0 if failed.
2707 * All flags except GCP_REORDER are not yet implemented.
2708 * Reordering is not 100% complient to the Windows BiDi method.
2709 * Caret positioning is not yet implemented for BiDi.
2710 * Classes are not yet implemented.
2714 GetCharacterPlacementW(
2715 HDC hdc, /* [in] Device context for which the rendering is to be done */
2716 LPCWSTR lpString, /* [in] The string for which information is to be returned */
2717 INT uCount, /* [in] Number of WORDS in string. */
2718 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
2719 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2720 DWORD dwFlags /* [in] Flags specifying how to process the string */
2727 TRACE("%s, %d, %d, 0x%08lx\n",
2728 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2730 TRACE("lStructSize=%ld, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2731 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2732 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2733 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2734 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2736 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08lx ignored\n", dwFlags);
2737 if(lpResults->lpClass) FIXME("classes not implemented\n");
2738 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2739 FIXME("Caret positions for complex scripts not implemented\n");
2741 nSet = (UINT)uCount;
2742 if(nSet > lpResults->nGlyphs)
2743 nSet = lpResults->nGlyphs;
2745 /* return number of initialized fields */
2746 lpResults->nGlyphs = nSet;
2748 if((dwFlags&GCP_REORDER)==0 || !BidiAvail)
2750 /* Treat the case where no special handling was requested in a fastpath way */
2751 /* copy will do if the GCP_REORDER flag is not set */
2752 if(lpResults->lpOutString)
2753 memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
2755 if(lpResults->lpOrder)
2757 for(i = 0; i < nSet; i++)
2758 lpResults->lpOrder[i] = i;
2762 BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
2763 nSet, lpResults->lpOrder );
2766 /* FIXME: Will use the placement chars */
2767 if (lpResults->lpDx)
2770 for (i = 0; i < nSet; i++)
2772 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
2773 lpResults->lpDx[i]= c;
2777 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
2781 lpResults->lpCaretPos[0] = 0;
2782 for (i = 1; i < nSet; i++)
2783 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
2784 lpResults->lpCaretPos[i] = (pos += size.cx);
2787 if(lpResults->lpGlyphs)
2788 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
2790 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
2791 ret = MAKELONG(size.cx, size.cy);
2796 /*************************************************************************
2797 * GetCharABCWidthsFloatA [GDI32.@]
2799 * See GetCharABCWidthsFloatW.
2801 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
2803 INT i, wlen, count = (INT)(last - first + 1);
2808 if (count <= 0) return FALSE;
2810 str = HeapAlloc(GetProcessHeap(), 0, count);
2812 for(i = 0; i < count; i++)
2813 str[i] = (BYTE)(first + i);
2815 wstr = FONT_mbtowc( hdc, str, count, &wlen, NULL );
2817 for (i = 0; i < wlen; i++)
2819 if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
2827 HeapFree( GetProcessHeap(), 0, str );
2828 HeapFree( GetProcessHeap(), 0, wstr );
2833 /*************************************************************************
2834 * GetCharABCWidthsFloatW [GDI32.@]
2836 * Retrieves widths of a range of characters.
2839 * hdc [I] Handle to device context.
2840 * first [I] First character in range to query.
2841 * last [I] Last character in range to query.
2842 * abcf [O] Array of LPABCFLOAT structures.
2849 * Only works with TrueType fonts. It also doesn't return real
2850 * floats but converted integers because it's implemented on
2851 * top of GetCharABCWidthsW.
2853 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
2856 unsigned int i, size = sizeof(ABC) * (last - first + 1);
2859 TRACE("%p, %d, %d, %p - partial stub\n", hdc, first, last, abcf);
2861 abc = HeapAlloc( GetProcessHeap(), 0, size );
2862 if (!abc) return FALSE;
2864 ret = GetCharABCWidthsW( hdc, first, last, abc );
2867 for (i = first; i <= last; i++, abc++, abcf++)
2869 abcf->abcfA = abc->abcA;
2870 abcf->abcfB = abc->abcB;
2871 abcf->abcfC = abc->abcC;
2874 HeapFree( GetProcessHeap(), 0, abc );
2878 /*************************************************************************
2879 * GetCharWidthFloatA [GDI32.@]
2881 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
2882 UINT iLastChar, PFLOAT pxBuffer)
2884 FIXME_(gdi)("GetCharWidthFloatA, stub\n");
2888 /*************************************************************************
2889 * GetCharWidthFloatW [GDI32.@]
2891 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
2892 UINT iLastChar, PFLOAT pxBuffer)
2894 FIXME_(gdi)("GetCharWidthFloatW, stub\n");
2899 /***********************************************************************
2901 * Font Resource API *
2903 ***********************************************************************/
2905 /***********************************************************************
2906 * AddFontResourceA (GDI32.@)
2908 INT WINAPI AddFontResourceA( LPCSTR str )
2910 return AddFontResourceExA( str, 0, NULL);
2913 /***********************************************************************
2914 * AddFontResourceW (GDI32.@)
2916 INT WINAPI AddFontResourceW( LPCWSTR str )
2918 return AddFontResourceExW(str, 0, NULL);
2922 /***********************************************************************
2923 * AddFontResourceExA (GDI32.@)
2925 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
2927 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
2928 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2931 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
2932 ret = AddFontResourceExW(strW, fl, pdv);
2933 HeapFree(GetProcessHeap(), 0, strW);
2937 /***********************************************************************
2938 * AddFontResourceExW (GDI32.@)
2940 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
2942 return WineEngAddFontResourceEx(str, fl, pdv);
2945 /***********************************************************************
2946 * RemoveFontResourceA (GDI32.@)
2948 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
2950 return RemoveFontResourceExA(str, 0, 0);
2953 /***********************************************************************
2954 * RemoveFontResourceW (GDI32.@)
2956 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
2958 return RemoveFontResourceExW(str, 0, 0);
2961 /***********************************************************************
2962 * AddFontMemResourceEx (GDI32.@)
2964 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
2966 FIXME("(%p,%08lx,%p,%p): stub\n", pbFont, cbFont, pdv, pcFonts);
2970 /***********************************************************************
2971 * RemoveFontResourceExA (GDI32.@)
2973 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
2975 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
2976 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2979 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
2980 ret = RemoveFontResourceExW(strW, fl, pdv);
2981 HeapFree(GetProcessHeap(), 0, strW);
2985 /***********************************************************************
2986 * RemoveFontResourceExW (GDI32.@)
2988 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
2990 return WineEngRemoveFontResourceEx(str, fl, pdv);
2993 /***********************************************************************
2994 * GetTextCharset (GDI32.@)
2996 UINT WINAPI GetTextCharset(HDC hdc)
2998 /* MSDN docs say this is equivalent */
2999 return GetTextCharsetInfo(hdc, NULL, 0);
3002 /***********************************************************************
3003 * GetTextCharsetInfo (GDI32.@)
3005 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3007 UINT ret = DEFAULT_CHARSET;
3008 DC *dc = DC_GetDCPtr(hdc);
3013 ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
3015 GDI_ReleaseObj(hdc);
3018 if (ret == DEFAULT_CHARSET && fs)
3019 memset(fs, 0, sizeof(FONTSIGNATURE));
3023 /***********************************************************************
3024 * GdiGetCharDimensions (GDI32.@)
3026 * Gets the average width of the characters in the English alphabet.
3029 * hdc [I] Handle to the device context to measure on.
3030 * lptm [O] Pointer to memory to store the text metrics into.
3031 * height [O] On exit, the maximum height of characters in the English alphabet.
3034 * The average width of characters in the English alphabet.
3037 * This function is used by the dialog manager to get the size of a dialog
3038 * unit. It should also be used by other pieces of code that need to know
3039 * the size of a dialog unit in logical units without having access to the
3040 * window handle of the dialog.
3041 * Windows caches the font metrics from this function, but we don't and
3042 * there doesn't appear to be an immediate advantage to do so.
3045 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3047 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3050 static const WCHAR alphabet[] = {
3051 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3052 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3053 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3055 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3057 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3059 if (height) *height = sz.cy;
3060 return (sz.cx / 26 + 1) / 2;
3063 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3065 FIXME("(%d): stub\n", fEnableEUDC);