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);
40 WINE_DECLARE_DEBUG_CHANNEL(gdi);
42 /* Device -> World size conversion */
44 /* Performs a device to world transformation on the specified width (which
45 * is in integer format).
47 static inline INT INTERNAL_XDSTOWS(DC *dc, INT width)
51 /* Perform operation with floating point */
52 floatWidth = (FLOAT)width * dc->xformVport2World.eM11;
53 /* Round to integers */
54 return GDI_ROUND(floatWidth);
57 /* Performs a device to world transformation on the specified size (which
58 * is in integer format).
60 static inline INT INTERNAL_YDSTOWS(DC *dc, INT height)
64 /* Perform operation with floating point */
65 floatHeight = (FLOAT)height * dc->xformVport2World.eM22;
66 /* Round to integers */
67 return GDI_ROUND(floatHeight);
70 static inline INT INTERNAL_XWSTODS(DC *dc, INT width)
73 pt[0].x = pt[0].y = 0;
76 LPtoDP(dc->hSelf, pt, 2);
77 return pt[1].x - pt[0].x;
80 static inline INT INTERNAL_YWSTODS(DC *dc, INT height)
83 pt[0].x = pt[0].y = 0;
86 LPtoDP(dc->hSelf, pt, 2);
87 return pt[1].y - pt[0].y;
90 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, void *obj, HDC hdc );
91 static INT FONT_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
92 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
93 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
94 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj );
96 static const struct gdi_obj_funcs font_funcs =
98 FONT_SelectObject, /* pSelectObject */
99 FONT_GetObject16, /* pGetObject16 */
100 FONT_GetObjectA, /* pGetObjectA */
101 FONT_GetObjectW, /* pGetObjectW */
102 NULL, /* pUnrealizeObject */
103 FONT_DeleteObject /* pDeleteObject */
106 #define ENUM_UNICODE 0x00000001
107 #define ENUM_CALLED 0x00000002
117 LPLOGFONT16 lpLogFontParam;
118 FONTENUMPROC16 lpEnumFunc;
121 LPNEWTEXTMETRICEX16 lpTextMetric;
122 LPENUMLOGFONTEX16 lpLogFont;
123 SEGPTR segTextMetric;
133 LPLOGFONTW lpLogFontParam;
134 FONTENUMPROCW lpEnumFunc;
143 * For TranslateCharsetInfo
145 #define FS(x) {{0,0,0,0},{0x1<<(x),0}}
146 #define MAXTCIINDEX 32
147 static const CHARSETINFO FONT_tci[MAXTCIINDEX] = {
149 { ANSI_CHARSET, 1252, FS(0)},
150 { EASTEUROPE_CHARSET, 1250, FS(1)},
151 { RUSSIAN_CHARSET, 1251, FS(2)},
152 { GREEK_CHARSET, 1253, FS(3)},
153 { TURKISH_CHARSET, 1254, FS(4)},
154 { HEBREW_CHARSET, 1255, FS(5)},
155 { ARABIC_CHARSET, 1256, FS(6)},
156 { BALTIC_CHARSET, 1257, FS(7)},
157 { VIETNAMESE_CHARSET, 1258, FS(8)},
158 /* reserved by ANSI */
159 { DEFAULT_CHARSET, 0, FS(0)},
160 { DEFAULT_CHARSET, 0, FS(0)},
161 { DEFAULT_CHARSET, 0, FS(0)},
162 { DEFAULT_CHARSET, 0, FS(0)},
163 { DEFAULT_CHARSET, 0, FS(0)},
164 { DEFAULT_CHARSET, 0, FS(0)},
165 { DEFAULT_CHARSET, 0, FS(0)},
167 { THAI_CHARSET, 874, FS(16)},
168 { SHIFTJIS_CHARSET, 932, FS(17)},
169 { GB2312_CHARSET, 936, FS(18)},
170 { HANGEUL_CHARSET, 949, FS(19)},
171 { CHINESEBIG5_CHARSET, 950, FS(20)},
172 { JOHAB_CHARSET, 1361, FS(21)},
173 /* reserved for alternate ANSI and OEM */
174 { DEFAULT_CHARSET, 0, FS(0)},
175 { DEFAULT_CHARSET, 0, FS(0)},
176 { DEFAULT_CHARSET, 0, FS(0)},
177 { DEFAULT_CHARSET, 0, FS(0)},
178 { DEFAULT_CHARSET, 0, FS(0)},
179 { DEFAULT_CHARSET, 0, FS(0)},
180 { DEFAULT_CHARSET, 0, FS(0)},
181 { DEFAULT_CHARSET, 0, FS(0)},
182 /* reserved for system */
183 { DEFAULT_CHARSET, 0, FS(0)},
184 { SYMBOL_CHARSET, CP_SYMBOL, FS(31)},
187 /***********************************************************************
188 * LOGFONT conversion functions.
190 static void FONT_LogFontWTo16( const LOGFONTW* font32, LPLOGFONT16 font16 )
192 font16->lfHeight = font32->lfHeight;
193 font16->lfWidth = font32->lfWidth;
194 font16->lfEscapement = font32->lfEscapement;
195 font16->lfOrientation = font32->lfOrientation;
196 font16->lfWeight = font32->lfWeight;
197 font16->lfItalic = font32->lfItalic;
198 font16->lfUnderline = font32->lfUnderline;
199 font16->lfStrikeOut = font32->lfStrikeOut;
200 font16->lfCharSet = font32->lfCharSet;
201 font16->lfOutPrecision = font32->lfOutPrecision;
202 font16->lfClipPrecision = font32->lfClipPrecision;
203 font16->lfQuality = font32->lfQuality;
204 font16->lfPitchAndFamily = font32->lfPitchAndFamily;
205 WideCharToMultiByte( CP_ACP, 0, font32->lfFaceName, -1,
206 font16->lfFaceName, LF_FACESIZE, NULL, NULL );
207 font16->lfFaceName[LF_FACESIZE-1] = 0;
210 static void FONT_LogFont16ToW( const LOGFONT16 *font16, LPLOGFONTW font32 )
212 font32->lfHeight = font16->lfHeight;
213 font32->lfWidth = font16->lfWidth;
214 font32->lfEscapement = font16->lfEscapement;
215 font32->lfOrientation = font16->lfOrientation;
216 font32->lfWeight = font16->lfWeight;
217 font32->lfItalic = font16->lfItalic;
218 font32->lfUnderline = font16->lfUnderline;
219 font32->lfStrikeOut = font16->lfStrikeOut;
220 font32->lfCharSet = font16->lfCharSet;
221 font32->lfOutPrecision = font16->lfOutPrecision;
222 font32->lfClipPrecision = font16->lfClipPrecision;
223 font32->lfQuality = font16->lfQuality;
224 font32->lfPitchAndFamily = font16->lfPitchAndFamily;
225 MultiByteToWideChar( CP_ACP, 0, font16->lfFaceName, -1, font32->lfFaceName, LF_FACESIZE );
226 font32->lfFaceName[LF_FACESIZE-1] = 0;
229 static void FONT_LogFontAToW( const LOGFONTA *fontA, LPLOGFONTW fontW )
231 memcpy(fontW, fontA, sizeof(LOGFONTA) - LF_FACESIZE);
232 MultiByteToWideChar(CP_ACP, 0, fontA->lfFaceName, -1, fontW->lfFaceName,
234 fontW->lfFaceName[LF_FACESIZE-1] = 0;
237 static void FONT_LogFontWToA( const LOGFONTW *fontW, LPLOGFONTA fontA )
239 memcpy(fontA, fontW, sizeof(LOGFONTA) - LF_FACESIZE);
240 WideCharToMultiByte(CP_ACP, 0, fontW->lfFaceName, -1, fontA->lfFaceName,
241 LF_FACESIZE, NULL, NULL);
242 fontA->lfFaceName[LF_FACESIZE-1] = 0;
245 static void FONT_EnumLogFontExWTo16( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEX16 font16 )
247 FONT_LogFontWTo16( (const LOGFONTW *)fontW, (LPLOGFONT16)font16);
249 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
250 (LPSTR) font16->elfFullName, LF_FULLFACESIZE, NULL, NULL );
251 font16->elfFullName[LF_FULLFACESIZE-1] = '\0';
252 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
253 (LPSTR) font16->elfStyle, LF_FACESIZE, NULL, NULL );
254 font16->elfStyle[LF_FACESIZE-1] = '\0';
255 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
256 (LPSTR) font16->elfScript, LF_FACESIZE, NULL, NULL );
257 font16->elfScript[LF_FACESIZE-1] = '\0';
260 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEXA fontA )
262 FONT_LogFontWToA( (const LOGFONTW *)fontW, (LPLOGFONTA)fontA);
264 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
265 (LPSTR) fontA->elfFullName, LF_FULLFACESIZE, NULL, NULL );
266 fontA->elfFullName[LF_FULLFACESIZE-1] = '\0';
267 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
268 (LPSTR) fontA->elfStyle, LF_FACESIZE, NULL, NULL );
269 fontA->elfStyle[LF_FACESIZE-1] = '\0';
270 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
271 (LPSTR) fontA->elfScript, LF_FACESIZE, NULL, NULL );
272 fontA->elfScript[LF_FACESIZE-1] = '\0';
275 /***********************************************************************
276 * TEXTMETRIC conversion functions.
278 static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
280 ptmA->tmHeight = ptmW->tmHeight;
281 ptmA->tmAscent = ptmW->tmAscent;
282 ptmA->tmDescent = ptmW->tmDescent;
283 ptmA->tmInternalLeading = ptmW->tmInternalLeading;
284 ptmA->tmExternalLeading = ptmW->tmExternalLeading;
285 ptmA->tmAveCharWidth = ptmW->tmAveCharWidth;
286 ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth;
287 ptmA->tmWeight = ptmW->tmWeight;
288 ptmA->tmOverhang = ptmW->tmOverhang;
289 ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX;
290 ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
291 ptmA->tmFirstChar = ptmW->tmFirstChar > 255 ? 255 : ptmW->tmFirstChar;
292 ptmA->tmLastChar = ptmW->tmLastChar > 255 ? 255 : ptmW->tmLastChar;
293 ptmA->tmDefaultChar = ptmW->tmDefaultChar > 255 ? 255 : ptmW->tmDefaultChar;
294 ptmA->tmBreakChar = ptmW->tmBreakChar > 255 ? 255 : ptmW->tmBreakChar;
295 ptmA->tmItalic = ptmW->tmItalic;
296 ptmA->tmUnderlined = ptmW->tmUnderlined;
297 ptmA->tmStruckOut = ptmW->tmStruckOut;
298 ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
299 ptmA->tmCharSet = ptmW->tmCharSet;
303 static void FONT_NewTextMetricExWTo16(const NEWTEXTMETRICEXW *ptmW, LPNEWTEXTMETRICEX16 ptm16 )
305 ptm16->ntmTm.tmHeight = ptmW->ntmTm.tmHeight;
306 ptm16->ntmTm.tmAscent = ptmW->ntmTm.tmAscent;
307 ptm16->ntmTm.tmDescent = ptmW->ntmTm.tmDescent;
308 ptm16->ntmTm.tmInternalLeading = ptmW->ntmTm.tmInternalLeading;
309 ptm16->ntmTm.tmExternalLeading = ptmW->ntmTm.tmExternalLeading;
310 ptm16->ntmTm.tmAveCharWidth = ptmW->ntmTm.tmAveCharWidth;
311 ptm16->ntmTm.tmMaxCharWidth = ptmW->ntmTm.tmMaxCharWidth;
312 ptm16->ntmTm.tmWeight = ptmW->ntmTm.tmWeight;
313 ptm16->ntmTm.tmOverhang = ptmW->ntmTm.tmOverhang;
314 ptm16->ntmTm.tmDigitizedAspectX = ptmW->ntmTm.tmDigitizedAspectX;
315 ptm16->ntmTm.tmDigitizedAspectY = ptmW->ntmTm.tmDigitizedAspectY;
316 ptm16->ntmTm.tmFirstChar = ptmW->ntmTm.tmFirstChar > 255 ? 255 : ptmW->ntmTm.tmFirstChar;
317 ptm16->ntmTm.tmLastChar = ptmW->ntmTm.tmLastChar > 255 ? 255 : ptmW->ntmTm.tmLastChar;
318 ptm16->ntmTm.tmDefaultChar = ptmW->ntmTm.tmDefaultChar > 255 ? 255 : ptmW->ntmTm.tmDefaultChar;
319 ptm16->ntmTm.tmBreakChar = ptmW->ntmTm.tmBreakChar > 255 ? 255 : ptmW->ntmTm.tmBreakChar;
320 ptm16->ntmTm.tmItalic = ptmW->ntmTm.tmItalic;
321 ptm16->ntmTm.tmUnderlined = ptmW->ntmTm.tmUnderlined;
322 ptm16->ntmTm.tmStruckOut = ptmW->ntmTm.tmStruckOut;
323 ptm16->ntmTm.tmPitchAndFamily = ptmW->ntmTm.tmPitchAndFamily;
324 ptm16->ntmTm.tmCharSet = ptmW->ntmTm.tmCharSet;
325 ptm16->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
326 ptm16->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
327 ptm16->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
328 ptm16->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
329 memcpy(&ptm16->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
332 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW *ptmW, NEWTEXTMETRICEXA *ptmA )
334 FONT_TextMetricWToA((const TEXTMETRICW *)ptmW, (LPTEXTMETRICA)ptmA);
335 ptmA->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
336 ptmA->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
337 ptmA->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
338 ptmA->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
339 memcpy(&ptmA->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
343 /***********************************************************************
346 * Returns a Unicode translation of str. If count is -1 then str is
347 * assumed to be '\0' terminated, otherwise it contains the number of
348 * bytes to convert. If plenW is non-NULL, on return it will point to
349 * the number of WCHARs that have been written. The caller should free
350 * the returned LPWSTR from the process heap itself.
352 static LPWSTR FONT_mbtowc(LPCSTR str, INT count, INT *plenW)
358 if(count == -1) count = strlen(str);
359 lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
360 strW = HeapAlloc(GetProcessHeap(), 0, lenW*sizeof(WCHAR));
361 MultiByteToWideChar(cp, 0, str, count, strW, lenW);
362 TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW));
363 if(plenW) *plenW = lenW;
368 /***********************************************************************
369 * CreateFontIndirectA (GDI32.@)
371 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *plfA )
376 FONT_LogFontAToW( plfA, &lfW );
377 return CreateFontIndirectW( &lfW );
379 return CreateFontIndirectW( NULL );
383 /***********************************************************************
384 * CreateFontIndirectW (GDI32.@)
386 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
393 if ((fontPtr = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC,
394 (HGDIOBJ *)&hFont, &font_funcs )))
396 static const WCHAR ItalicW[] = {' ','I','t','a','l','i','c','\0'};
397 static const WCHAR BoldW[] = {' ','B','o','l','d','\0'};
398 WCHAR *pFaceNameItalicSuffix, *pFaceNameBoldSuffix;
399 WCHAR* pFaceNameSuffix = NULL;
401 memcpy( &fontPtr->logfont, plf, sizeof(LOGFONTW) );
403 TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
404 plf->lfHeight, plf->lfWidth,
405 plf->lfEscapement, plf->lfOrientation,
406 plf->lfPitchAndFamily,
407 plf->lfOutPrecision, plf->lfClipPrecision,
408 plf->lfQuality, plf->lfCharSet,
409 debugstr_w(plf->lfFaceName),
410 plf->lfWeight > 400 ? "Bold" : "",
411 plf->lfItalic ? "Italic" : "",
412 plf->lfUnderline ? "Underline" : "", hFont);
414 if (plf->lfEscapement != plf->lfOrientation) {
415 /* this should really depend on whether GM_ADVANCED is set */
416 fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
417 WARN("orientation angle %f set to "
418 "escapement angle %f for new font %p\n",
419 plf->lfOrientation/10., plf->lfEscapement/10., hFont);
422 pFaceNameItalicSuffix = strstrW(fontPtr->logfont.lfFaceName, ItalicW);
423 if (pFaceNameItalicSuffix) {
424 fontPtr->logfont.lfItalic = TRUE;
425 pFaceNameSuffix = pFaceNameItalicSuffix;
428 pFaceNameBoldSuffix = strstrW(fontPtr->logfont.lfFaceName, BoldW);
429 if (pFaceNameBoldSuffix) {
430 if (fontPtr->logfont.lfWeight < FW_BOLD) {
431 fontPtr->logfont.lfWeight = FW_BOLD;
433 if (!pFaceNameSuffix ||
434 (pFaceNameBoldSuffix < pFaceNameSuffix)) {
435 pFaceNameSuffix = pFaceNameBoldSuffix;
439 if (pFaceNameSuffix) *pFaceNameSuffix = 0;
441 GDI_ReleaseObj( hFont );
444 else WARN("(NULL) => NULL\n");
449 /*************************************************************************
450 * CreateFontA (GDI32.@)
452 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
453 INT orient, INT weight, DWORD italic,
454 DWORD underline, DWORD strikeout, DWORD charset,
455 DWORD outpres, DWORD clippres, DWORD quality,
456 DWORD pitch, LPCSTR name )
460 logfont.lfHeight = height;
461 logfont.lfWidth = width;
462 logfont.lfEscapement = esc;
463 logfont.lfOrientation = orient;
464 logfont.lfWeight = weight;
465 logfont.lfItalic = italic;
466 logfont.lfUnderline = underline;
467 logfont.lfStrikeOut = strikeout;
468 logfont.lfCharSet = charset;
469 logfont.lfOutPrecision = outpres;
470 logfont.lfClipPrecision = clippres;
471 logfont.lfQuality = quality;
472 logfont.lfPitchAndFamily = pitch;
475 lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
477 logfont.lfFaceName[0] = '\0';
479 return CreateFontIndirectA( &logfont );
482 /*************************************************************************
483 * CreateFontW (GDI32.@)
485 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
486 INT orient, INT weight, DWORD italic,
487 DWORD underline, DWORD strikeout, DWORD charset,
488 DWORD outpres, DWORD clippres, DWORD quality,
489 DWORD pitch, LPCWSTR name )
493 logfont.lfHeight = height;
494 logfont.lfWidth = width;
495 logfont.lfEscapement = esc;
496 logfont.lfOrientation = orient;
497 logfont.lfWeight = weight;
498 logfont.lfItalic = italic;
499 logfont.lfUnderline = underline;
500 logfont.lfStrikeOut = strikeout;
501 logfont.lfCharSet = charset;
502 logfont.lfOutPrecision = outpres;
503 logfont.lfClipPrecision = clippres;
504 logfont.lfQuality = quality;
505 logfont.lfPitchAndFamily = pitch;
508 lstrcpynW(logfont.lfFaceName, name,
509 sizeof(logfont.lfFaceName) / sizeof(WCHAR));
511 logfont.lfFaceName[0] = '\0';
513 return CreateFontIndirectW( &logfont );
517 /***********************************************************************
520 * If the driver supports vector fonts we create a gdi font first and
521 * then call the driver to give it a chance to supply its own device
522 * font. If the driver wants to do this it returns TRUE and we can
523 * delete the gdi font, if the driver wants to use the gdi font it
524 * should return FALSE, to signal an error return GDI_ERROR. For
525 * drivers that don't support vector fonts they must supply their own
528 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, void *obj, HDC hdc )
531 DC *dc = DC_GetDCPtr( hdc );
535 if (dc->hFont != handle || dc->gdiFont == NULL)
537 if(GetDeviceCaps(dc->hSelf, TEXTCAPS) & TC_VA_ABLE)
538 dc->gdiFont = WineEngCreateFontInstance(dc, handle);
541 if (dc->funcs->pSelectFont) ret = dc->funcs->pSelectFont( dc->physDev, handle, dc->gdiFont );
543 if (ret && dc->gdiFont) dc->gdiFont = 0;
545 if (ret == HGDI_ERROR)
546 ret = 0; /* SelectObject returns 0 on error */
552 GDI_ReleaseObj( hdc );
557 /***********************************************************************
560 static INT FONT_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
565 FONT_LogFontWTo16( &font->logfont, &lf16 );
567 if (count > sizeof(LOGFONT16)) count = sizeof(LOGFONT16);
568 memcpy( buffer, &lf16, count );
572 /***********************************************************************
575 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
582 FONT_LogFontWToA( &font->logfont, &lfA );
584 if (count > sizeof(lfA)) count = sizeof(lfA);
585 memcpy( buffer, &lfA, count );
589 /***********************************************************************
592 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
596 return sizeof(LOGFONTW);
597 if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
598 memcpy( buffer, &font->logfont, count );
603 /***********************************************************************
606 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj )
608 WineEngDestroyFontInstance( handle );
609 return GDI_FreeObject( handle, obj );
613 /***********************************************************************
614 * FONT_EnumInstance16
616 * Called by the device driver layer to pass font info
617 * down to the application.
619 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
620 * We have to use other types because of the FONTENUMPROCW definition.
622 static INT CALLBACK FONT_EnumInstance16( const LOGFONTW *plf, const TEXTMETRICW *ptm,
623 DWORD fType, LPARAM lp )
625 fontEnum16 *pfe = (fontEnum16*)lp;
629 if( pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
630 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet )
635 FONT_EnumLogFontExWTo16((const ENUMLOGFONTEXW *)plf, pfe->lpLogFont);
636 FONT_NewTextMetricExWTo16((const NEWTEXTMETRICEXW *)ptm, pfe->lpTextMetric);
637 pfe->dwFlags |= ENUM_CALLED;
638 GDI_ReleaseObj( pfe->hdc ); /* release the GDI lock */
640 args[6] = SELECTOROF(pfe->segLogFont);
641 args[5] = OFFSETOF(pfe->segLogFont);
642 args[4] = SELECTOROF(pfe->segTextMetric);
643 args[3] = OFFSETOF(pfe->segTextMetric);
645 args[1] = HIWORD(pfe->lpData);
646 args[0] = LOWORD(pfe->lpData);
647 WOWCallback16Ex( (DWORD)pfe->lpEnumFunc, WCB16_PASCAL, sizeof(args), args, &result );
648 ret = LOWORD(result);
650 /* get the lock again and make sure the DC is still valid */
651 dc = DC_GetDCPtr( pfe->hdc );
652 if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
654 if (dc) GDI_ReleaseObj( pfe->hdc );
655 pfe->hdc = 0; /* make sure we don't try to release it later on */
662 /***********************************************************************
665 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
666 * We have to use other types because of the FONTENUMPROCW definition.
668 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
669 DWORD fType, LPARAM lp )
671 fontEnum32 *pfe = (fontEnum32*)lp;
675 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
676 if((pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
677 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
678 (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
680 /* convert font metrics */
681 ENUMLOGFONTEXA logfont;
682 NEWTEXTMETRICEXA tmA;
684 pfe->dwFlags |= ENUM_CALLED;
685 if (!(pfe->dwFlags & ENUM_UNICODE))
687 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
688 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
689 plf = (LOGFONTW *)&logfont.elfLogFont;
690 ptm = (TEXTMETRICW *)&tmA;
692 GDI_ReleaseObj( pfe->hdc ); /* release the GDI lock */
694 ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
696 /* get the lock again and make sure the DC is still valid */
697 dc = DC_GetDCPtr( pfe->hdc );
698 if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
700 if (dc) GDI_ReleaseObj( pfe->hdc );
701 pfe->hdc = 0; /* make sure we don't try to release it later on */
708 /***********************************************************************
709 * EnumFontFamiliesEx (GDI.613)
711 INT16 WINAPI EnumFontFamiliesEx16( HDC16 hDC, LPLOGFONT16 plf,
712 FONTENUMPROC16 efproc, LPARAM lParam,
717 DC* dc = DC_GetDCPtr( HDC_32(hDC) );
718 NEWTEXTMETRICEX16 tm16;
719 ENUMLOGFONTEX16 lf16;
724 FONT_LogFont16ToW(plf, &lfW);
726 fe16.hdc = HDC_32(hDC);
728 fe16.physDev = dc->physDev;
729 fe16.lpLogFontParam = plf;
730 fe16.lpEnumFunc = efproc;
731 fe16.lpData = lParam;
732 fe16.lpTextMetric = &tm16;
733 fe16.lpLogFont = &lf16;
734 fe16.segTextMetric = MapLS( &tm16 );
735 fe16.segLogFont = MapLS( &lf16 );
738 enum_gdi_fonts = GetDeviceCaps(fe16.hdc, TEXTCAPS) & TC_VA_ABLE;
740 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
747 ret = WineEngEnumFonts( &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
748 fe16.dwFlags &= ~ENUM_CALLED;
749 if (ret && dc->funcs->pEnumDeviceFonts) {
750 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
751 if(fe16.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
755 UnMapLS( fe16.segTextMetric );
756 UnMapLS( fe16.segLogFont );
757 if (fe16.hdc) GDI_ReleaseObj( fe16.hdc );
761 /***********************************************************************
762 * FONT_EnumFontFamiliesEx
764 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf,
765 FONTENUMPROCW efproc,
766 LPARAM lParam, DWORD dwUnicode)
769 DC *dc = DC_GetDCPtr( hDC );
775 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName),
777 fe32.lpLogFontParam = plf;
778 fe32.lpEnumFunc = efproc;
779 fe32.lpData = lParam;
780 fe32.dwFlags = dwUnicode;
783 fe32.physDev = dc->physDev;
785 enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE;
787 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
794 ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
795 fe32.dwFlags &= ~ENUM_CALLED;
796 if (ret && dc->funcs->pEnumDeviceFonts) {
797 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, plf, FONT_EnumInstance, (LPARAM)&fe32 );
798 if(fe32.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
802 if (fe32.hdc) GDI_ReleaseObj( fe32.hdc );
806 /***********************************************************************
807 * EnumFontFamiliesExW (GDI32.@)
809 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
810 FONTENUMPROCW efproc,
811 LPARAM lParam, DWORD dwFlags )
813 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, ENUM_UNICODE );
816 /***********************************************************************
817 * EnumFontFamiliesExA (GDI32.@)
819 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
820 FONTENUMPROCA efproc,
821 LPARAM lParam, DWORD dwFlags)
824 FONT_LogFontAToW( plf, &lfW );
826 return FONT_EnumFontFamiliesEx( hDC, &lfW, (FONTENUMPROCW)efproc, lParam, 0);
829 /***********************************************************************
830 * EnumFontFamilies (GDI.330)
832 INT16 WINAPI EnumFontFamilies16( HDC16 hDC, LPCSTR lpFamily,
833 FONTENUMPROC16 efproc, LPARAM lpData )
837 lf.lfCharSet = DEFAULT_CHARSET;
838 if( lpFamily ) lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
839 else lf.lfFaceName[0] = '\0';
841 return EnumFontFamiliesEx16( hDC, &lf, efproc, lpData, 0 );
844 /***********************************************************************
845 * EnumFontFamiliesA (GDI32.@)
847 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
848 FONTENUMPROCA efproc, LPARAM lpData )
852 lf.lfCharSet = DEFAULT_CHARSET;
853 if( lpFamily ) lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
854 else lf.lfFaceName[0] = lf.lfFaceName[1] = '\0';
856 return EnumFontFamiliesExA( hDC, &lf, efproc, lpData, 0 );
859 /***********************************************************************
860 * EnumFontFamiliesW (GDI32.@)
862 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
863 FONTENUMPROCW efproc, LPARAM lpData )
867 lf.lfCharSet = DEFAULT_CHARSET;
868 if( lpFamily ) lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
869 else lf.lfFaceName[0] = 0;
871 return EnumFontFamiliesExW( hDC, &lf, efproc, lpData, 0 );
874 /***********************************************************************
877 INT16 WINAPI EnumFonts16( HDC16 hDC, LPCSTR lpName, FONTENUMPROC16 efproc,
880 return EnumFontFamilies16( hDC, lpName, efproc, lpData );
883 /***********************************************************************
884 * EnumFontsA (GDI32.@)
886 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
889 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
892 /***********************************************************************
893 * EnumFontsW (GDI32.@)
895 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
898 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
902 /***********************************************************************
903 * GetTextCharacterExtra (GDI32.@)
905 INT WINAPI GetTextCharacterExtra( HDC hdc )
908 DC *dc = DC_GetDCPtr( hdc );
909 if (!dc) return 0x80000000;
911 GDI_ReleaseObj( hdc );
916 /***********************************************************************
917 * SetTextCharacterExtra (GDI32.@)
919 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
922 DC * dc = DC_GetDCPtr( hdc );
923 if (!dc) return 0x80000000;
924 if (dc->funcs->pSetTextCharacterExtra)
925 prev = dc->funcs->pSetTextCharacterExtra( dc->physDev, extra );
928 prev = dc->charExtra;
929 dc->charExtra = extra;
931 GDI_ReleaseObj( hdc );
936 /***********************************************************************
937 * SetTextJustification (GDI32.@)
939 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
942 DC * dc = DC_GetDCPtr( hdc );
943 if (!dc) return FALSE;
944 if (dc->funcs->pSetTextJustification)
945 ret = dc->funcs->pSetTextJustification( dc->physDev, extra, breaks );
948 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
949 if (!extra) breaks = 0;
952 dc->breakExtra = extra / breaks;
953 dc->breakRem = extra - (breaks * dc->breakExtra);
961 GDI_ReleaseObj( hdc );
966 /***********************************************************************
967 * GetTextFaceA (GDI32.@)
969 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
971 INT res = GetTextFaceW(hdc, 0, NULL);
972 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
973 GetTextFaceW( hdc, res, nameW );
977 if (count && !WideCharToMultiByte( CP_ACP, 0, nameW, -1, name, count, NULL, NULL))
982 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
983 HeapFree( GetProcessHeap(), 0, nameW );
987 /***********************************************************************
988 * GetTextFaceW (GDI32.@)
990 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
995 DC * dc = DC_GetDCPtr( hdc );
999 ret = WineEngGetTextFace(dc->gdiFont, count, name);
1000 else if ((font = (FONTOBJ *) GDI_GetObjPtr( dc->hFont, FONT_MAGIC )))
1004 lstrcpynW( name, font->logfont.lfFaceName, count );
1005 ret = strlenW(name);
1007 else ret = strlenW(font->logfont.lfFaceName) + 1;
1008 GDI_ReleaseObj( dc->hFont );
1010 GDI_ReleaseObj( hdc );
1015 /***********************************************************************
1016 * GetTextExtentPoint32A (GDI32.@)
1018 * See GetTextExtentPoint32W.
1020 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
1025 LPWSTR p = FONT_mbtowc(str, count, &wlen);
1028 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
1029 HeapFree( GetProcessHeap(), 0, p );
1032 TRACE("(%p %s %d %p): returning %d x %d\n",
1033 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
1038 /***********************************************************************
1039 * GetTextExtentPoint32W [GDI32.@]
1041 * Computes width/height for a string.
1043 * Computes width and height of the specified string.
1049 BOOL WINAPI GetTextExtentPoint32W(
1050 HDC hdc, /* [in] Handle of device context */
1051 LPCWSTR str, /* [in] Address of text string */
1052 INT count, /* [in] Number of characters in string */
1053 LPSIZE size) /* [out] Address of structure for string size */
1055 return GetTextExtentExPointW(hdc, str, count, 0, NULL, NULL, size);
1058 /***********************************************************************
1059 * GetTextExtentPointI [GDI32.@]
1061 * Computes width and height of the array of glyph indices.
1067 BOOL WINAPI GetTextExtentPointI(
1068 HDC hdc, /* [in] Handle of device context */
1069 const WORD *indices, /* [in] Address of glyph index array */
1070 INT count, /* [in] Number of glyphs in array */
1071 LPSIZE size) /* [out] Address of structure for string size */
1074 DC * dc = DC_GetDCPtr( hdc );
1075 if (!dc) return FALSE;
1078 ret = WineEngGetTextExtentPointI(dc->gdiFont, indices, count, size);
1079 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1080 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1081 size->cx += count * dc->charExtra;
1083 else if(dc->funcs->pGetTextExtentExPoint) {
1084 FIXME("calling GetTextExtentExPoint\n");
1085 ret = dc->funcs->pGetTextExtentExPoint( dc->physDev, (LPCWSTR)indices,
1086 count, 0, NULL, NULL, size );
1089 GDI_ReleaseObj( hdc );
1091 TRACE("(%p %p %d %p): returning %d x %d\n",
1092 hdc, indices, count, size, size->cx, size->cy );
1097 /***********************************************************************
1098 * GetTextExtentPointA (GDI32.@)
1100 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
1103 TRACE("not bug compatible.\n");
1104 return GetTextExtentPoint32A( hdc, str, count, size );
1107 /***********************************************************************
1108 * GetTextExtentPointW (GDI32.@)
1110 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1113 TRACE("not bug compatible.\n");
1114 return GetTextExtentPoint32W( hdc, str, count, size );
1118 /***********************************************************************
1119 * GetTextExtentExPointA (GDI32.@)
1121 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1122 INT maxExt, LPINT lpnFit,
1123 LPINT alpDx, LPSIZE size )
1131 NULL == (walpDx = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT))))
1134 p = FONT_mbtowc(str, count, &wlen);
1135 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
1138 INT n = lpnFit ? *lpnFit : wlen;
1140 for(i = 0, j = 0; i < n; i++, j++)
1142 alpDx[j] = walpDx[i];
1143 if (IsDBCSLeadByte(str[j])) alpDx[++j] = walpDx[i];
1146 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1147 HeapFree( GetProcessHeap(), 0, p );
1148 HeapFree( GetProcessHeap(), 0, walpDx );
1153 /***********************************************************************
1154 * GetTextExtentExPointW (GDI32.@)
1156 * Return the size of the string as it would be if it was output properly by
1159 * This should include
1160 * - Intercharacter spacing
1161 * - justification spacing (not yet done)
1162 * - kerning? see below
1164 * Kerning. Since kerning would be carried out by the rendering code it should
1165 * be done by the driver. However they don't support it yet. Also I am not
1166 * yet persuaded that (certainly under Win95) any kerning is actually done.
1168 * str: According to MSDN this should be null-terminated. That is not true; a
1169 * null will not terminate it early.
1170 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1171 * than count. I have seen it be either the size of the full string or
1172 * 1 less than the size of the full string. I have not seen it bear any
1173 * resemblance to the portion that would fit.
1174 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1175 * trailing intercharacter spacing and any trailing justification.
1178 * Currently we do this by measuring each character etc. We should do it by
1179 * passing the request to the driver, perhaps by extending the
1180 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1181 * thinking about kerning issues and rounding issues in the justification.
1184 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1185 INT maxExt, LPINT lpnFit,
1186 LPINT alpDx, LPSIZE size )
1193 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1195 dc = DC_GetDCPtr(hdc);
1199 /* If we need to calculate nFit, then we need the partial extents even if
1200 the user hasn't provided us with an array. */
1203 dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]);
1206 GDI_ReleaseObj(hdc);
1207 SetLastError(ERROR_OUTOFMEMORY);
1215 ret = WineEngGetTextExtentExPoint(dc->gdiFont, str, count,
1216 0, NULL, dxs, size);
1217 else if (dc->funcs->pGetTextExtentExPoint)
1218 ret = dc->funcs->pGetTextExtentExPoint(dc->physDev, str, count,
1219 0, NULL, dxs, size);
1221 /* Perform device size to world size transformations. */
1224 INT extra = dc->charExtra, breakRem = dc->breakRem;
1229 for (i = 0; i < count; ++i)
1231 dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
1232 dxs[i] += (i+1) * extra + breakRem;
1233 if (dxs[i] <= maxExt)
1237 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1238 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1239 size->cx += count * extra + breakRem;
1246 HeapFree(GetProcessHeap(), 0, dxs);
1248 GDI_ReleaseObj( hdc );
1250 TRACE("returning %d %d x %d\n",nFit,size->cx,size->cy);
1254 /***********************************************************************
1255 * GetTextMetricsA (GDI32.@)
1257 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1261 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1262 FONT_TextMetricWToA( &tm32, metrics );
1266 /***********************************************************************
1267 * GetTextMetricsW (GDI32.@)
1269 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1272 DC * dc = DC_GetDCPtr( hdc );
1273 if (!dc) return FALSE;
1276 ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1277 else if (dc->funcs->pGetTextMetrics)
1278 ret = dc->funcs->pGetTextMetrics( dc->physDev, metrics );
1282 /* device layer returns values in device units
1283 * therefore we have to convert them to logical */
1285 #define WDPTOLP(x) ((x<0)? \
1286 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1287 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1288 #define HDPTOLP(y) ((y<0)? \
1289 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1290 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1292 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1293 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1294 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1295 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1296 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1297 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1298 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1299 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1303 TRACE("text metrics:\n"
1304 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1305 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1306 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1307 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1308 " PitchAndFamily = %02x\n"
1309 " --------------------\n"
1310 " InternalLeading = %i\n"
1314 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1315 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1316 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1317 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1318 metrics->tmPitchAndFamily,
1319 metrics->tmInternalLeading,
1322 metrics->tmHeight );
1324 GDI_ReleaseObj( hdc );
1329 /***********************************************************************
1330 * GetOutlineTextMetrics [GDI.308] Gets metrics for TrueType fonts.
1333 * lpOTM should be LPOUTLINETEXTMETRIC
1336 * Success: Non-zero or size of required buffer
1339 UINT16 WINAPI GetOutlineTextMetrics16(
1340 HDC16 hdc, /* [in] Handle of device context */
1341 UINT16 cbData, /* [in] Size of metric data array */
1342 LPOUTLINETEXTMETRIC16 lpOTM) /* [out] Address of metric data array */
1344 FIXME("(%04x,%04x,%p): stub\n", hdc,cbData,lpOTM);
1349 /***********************************************************************
1350 * GetOutlineTextMetricsA (GDI32.@)
1351 * Gets metrics for TrueType fonts.
1354 * If the supplied buffer isn't big enough Windows partially fills it up to
1355 * its given length and returns that length.
1358 * Success: Non-zero or size of required buffer
1361 UINT WINAPI GetOutlineTextMetricsA(
1362 HDC hdc, /* [in] Handle of device context */
1363 UINT cbData, /* [in] Size of metric data array */
1364 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1366 char buf[512], *ptr;
1368 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1369 OUTLINETEXTMETRICA *output = lpOTM;
1372 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1374 if(ret > sizeof(buf))
1375 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1376 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1378 needed = sizeof(OUTLINETEXTMETRICA);
1379 if(lpOTMW->otmpFamilyName)
1380 needed += WideCharToMultiByte(CP_ACP, 0,
1381 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1382 NULL, 0, NULL, NULL);
1383 if(lpOTMW->otmpFaceName)
1384 needed += WideCharToMultiByte(CP_ACP, 0,
1385 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1386 NULL, 0, NULL, NULL);
1387 if(lpOTMW->otmpStyleName)
1388 needed += WideCharToMultiByte(CP_ACP, 0,
1389 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1390 NULL, 0, NULL, NULL);
1391 if(lpOTMW->otmpFullName)
1392 needed += WideCharToMultiByte(CP_ACP, 0,
1393 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1394 NULL, 0, NULL, NULL);
1401 TRACE("needed = %d\n", needed);
1403 /* Since the supplied buffer isn't big enough, we'll alloc one
1404 that is and memcpy the first cbData bytes into the lpOTM at
1406 output = HeapAlloc(GetProcessHeap(), 0, needed);
1408 ret = output->otmSize = min(needed, cbData);
1409 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1410 output->otmFiller = 0;
1411 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1412 output->otmfsSelection = lpOTMW->otmfsSelection;
1413 output->otmfsType = lpOTMW->otmfsType;
1414 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1415 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1416 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1417 output->otmEMSquare = lpOTMW->otmEMSquare;
1418 output->otmAscent = lpOTMW->otmAscent;
1419 output->otmDescent = lpOTMW->otmDescent;
1420 output->otmLineGap = lpOTMW->otmLineGap;
1421 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1422 output->otmsXHeight = lpOTMW->otmsXHeight;
1423 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1424 output->otmMacAscent = lpOTMW->otmMacAscent;
1425 output->otmMacDescent = lpOTMW->otmMacDescent;
1426 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1427 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1428 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1429 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1430 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1431 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1432 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1433 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1434 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1435 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1438 ptr = (char*)(output + 1);
1439 left = needed - sizeof(*output);
1441 if(lpOTMW->otmpFamilyName) {
1442 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1443 len = WideCharToMultiByte(CP_ACP, 0,
1444 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1445 ptr, left, NULL, NULL);
1449 output->otmpFamilyName = 0;
1451 if(lpOTMW->otmpFaceName) {
1452 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1453 len = WideCharToMultiByte(CP_ACP, 0,
1454 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1455 ptr, left, NULL, NULL);
1459 output->otmpFaceName = 0;
1461 if(lpOTMW->otmpStyleName) {
1462 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1463 len = WideCharToMultiByte(CP_ACP, 0,
1464 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1465 ptr, left, NULL, NULL);
1469 output->otmpStyleName = 0;
1471 if(lpOTMW->otmpFullName) {
1472 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1473 len = WideCharToMultiByte(CP_ACP, 0,
1474 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1475 ptr, left, NULL, NULL);
1478 output->otmpFullName = 0;
1482 if(output != lpOTM) {
1483 memcpy(lpOTM, output, cbData);
1484 HeapFree(GetProcessHeap(), 0, output);
1486 /* check if the string offsets really fit into the provided size */
1487 /* FIXME: should we check string length as well? */
1488 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1489 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1491 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1492 lpOTM->otmpFaceName = 0; /* doesn't fit */
1494 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1495 lpOTM->otmpStyleName = 0; /* doesn't fit */
1497 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1498 lpOTM->otmpFullName = 0; /* doesn't fit */
1502 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1503 HeapFree(GetProcessHeap(), 0, lpOTMW);
1509 /***********************************************************************
1510 * GetOutlineTextMetricsW [GDI32.@]
1512 UINT WINAPI GetOutlineTextMetricsW(
1513 HDC hdc, /* [in] Handle of device context */
1514 UINT cbData, /* [in] Size of metric data array */
1515 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1517 DC *dc = DC_GetDCPtr( hdc );
1518 OUTLINETEXTMETRICW *output = lpOTM;
1521 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1525 ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, output);
1528 output = HeapAlloc(GetProcessHeap(), 0, ret);
1529 WineEngGetOutlineTextMetrics(dc->gdiFont, ret, output);
1532 #define WDPTOLP(x) ((x<0)? \
1533 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1534 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1535 #define HDPTOLP(y) ((y<0)? \
1536 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1537 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1539 output->otmTextMetrics.tmHeight = HDPTOLP(output->otmTextMetrics.tmHeight);
1540 output->otmTextMetrics.tmAscent = HDPTOLP(output->otmTextMetrics.tmAscent);
1541 output->otmTextMetrics.tmDescent = HDPTOLP(output->otmTextMetrics.tmDescent);
1542 output->otmTextMetrics.tmInternalLeading = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1543 output->otmTextMetrics.tmExternalLeading = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1544 output->otmTextMetrics.tmAveCharWidth = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1545 output->otmTextMetrics.tmMaxCharWidth = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1546 output->otmTextMetrics.tmOverhang = WDPTOLP(output->otmTextMetrics.tmOverhang);
1547 output->otmAscent = HDPTOLP(output->otmAscent);
1548 output->otmDescent = HDPTOLP(output->otmDescent);
1549 output->otmLineGap = HDPTOLP(output->otmLineGap);
1550 output->otmsCapEmHeight = HDPTOLP(output->otmsCapEmHeight);
1551 output->otmsXHeight = HDPTOLP(output->otmsXHeight);
1552 output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1553 output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1554 output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1555 output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1556 output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1557 output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1558 output->otmMacLineGap = HDPTOLP(output->otmMacLineGap);
1559 output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1560 output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1561 output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1562 output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1563 output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1564 output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1565 output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1566 output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1567 output->otmsStrikeoutSize = HDPTOLP(output->otmsStrikeoutSize);
1568 output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1569 output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1570 output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1573 if(output != lpOTM) {
1574 memcpy(lpOTM, output, cbData);
1575 HeapFree(GetProcessHeap(), 0, output);
1581 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1582 but really this should just be a return 0. */
1584 ret = sizeof(*lpOTM);
1589 memset(lpOTM, 0, ret);
1590 lpOTM->otmSize = sizeof(*lpOTM);
1591 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1593 Further fill of the structure not implemented,
1594 Needs real values for the structure members
1599 GDI_ReleaseObj(hdc);
1604 /***********************************************************************
1605 * GetCharWidthW (GDI32.@)
1606 * GetCharWidth32W (GDI32.@)
1608 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1613 DC * dc = DC_GetDCPtr( hdc );
1614 if (!dc) return FALSE;
1617 ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1618 else if (dc->funcs->pGetCharWidth)
1619 ret = dc->funcs->pGetCharWidth( dc->physDev, firstChar, lastChar, buffer);
1623 /* convert device units to logical */
1624 for( i = firstChar; i <= lastChar; i++, buffer++ )
1625 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1628 GDI_ReleaseObj( hdc );
1633 /***********************************************************************
1634 * GetCharWidthA (GDI32.@)
1635 * GetCharWidth32A (GDI32.@)
1637 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1640 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1645 if(count <= 0) return FALSE;
1647 str = HeapAlloc(GetProcessHeap(), 0, count);
1648 for(i = 0; i < count; i++)
1649 str[i] = (BYTE)(firstChar + i);
1651 wstr = FONT_mbtowc(str, count, &wlen);
1653 for(i = 0; i < wlen; i++)
1655 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1663 HeapFree(GetProcessHeap(), 0, str);
1664 HeapFree(GetProcessHeap(), 0, wstr);
1670 /***********************************************************************
1671 * ExtTextOutA (GDI32.@)
1675 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1676 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(str, count, &wlen);
1689 unsigned int i = 0, j = 0;
1691 lpDxW = HeapAlloc( GetProcessHeap(), 0, wlen*sizeof(INT));
1693 if(IsDBCSLeadByte(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 );
1780 flags &= ~ETO_CLIPPED;
1782 if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && BidiAvail && count > 0 )
1784 reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1786 BIDI_Reorder( str, count, GCP_REORDER,
1787 ((flags&ETO_RTLREADING)!=0 || (GetTextAlign(hdc)&TA_RTLREADING)!=0)?
1788 WINE_GCPW_FORCE_RTL:WINE_GCPW_FORCE_LTR,
1789 reordered_str, count, NULL );
1791 flags |= ETO_IGNORELANGUAGE;
1794 TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc, x, y, flags,
1795 lprect, debugstr_wn(str, count), count, lpDx);
1797 if(flags & ETO_GLYPH_INDEX)
1798 glyphs = reordered_str;
1801 TRACE("rect: %d,%d - %d,%d\n", lprect->left, lprect->top, lprect->right,
1803 TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
1805 if(align & TA_UPDATECP)
1807 GetCurrentPositionEx( hdc, &pt );
1812 GetTextMetricsW(hdc, &tm);
1813 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1815 if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
1816 lf.lfEscapement = 0;
1818 if(lf.lfEscapement != 0)
1820 cosEsc = cos(lf.lfEscapement * M_PI / 1800);
1821 sinEsc = sin(lf.lfEscapement * M_PI / 1800);
1829 if(flags & (ETO_CLIPPED | ETO_OPAQUE))
1833 if(flags & ETO_GLYPH_INDEX)
1834 GetTextExtentPointI(hdc, glyphs, count, &sz);
1836 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1838 done_extents = TRUE;
1841 rc.right = x + sz.cx;
1842 rc.bottom = y + sz.cy;
1849 LPtoDP(hdc, (POINT*)&rc, 2);
1851 if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
1852 if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
1855 if ((flags & ETO_OPAQUE) && !PATH_IsPathOpen(dc->path))
1856 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1866 LPtoDP(hdc, &pt, 1);
1870 char_extra = GetTextCharacterExtra(hdc);
1872 if(char_extra || dc->breakExtra || lpDx)
1876 deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT));
1877 for(i = 0; i < count; i++)
1879 if(lpDx && (flags & ETO_PDY))
1880 deltas[i] = lpDx[i*2] + char_extra;
1882 deltas[i] = lpDx[i] + char_extra;
1885 if(flags & ETO_GLYPH_INDEX)
1886 GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
1888 GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
1890 deltas[i] = tmpsz.cx;
1893 if (!(flags & ETO_GLYPH_INDEX) && dc->breakExtra && reordered_str[i] == tm.tmBreakChar)
1895 deltas[i] = deltas[i] + dc->breakExtra;
1897 deltas[i] = INTERNAL_XWSTODS(dc, deltas[i]);
1905 if(flags & ETO_GLYPH_INDEX)
1906 GetTextExtentPointI(hdc, glyphs, count, &sz);
1908 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1909 done_extents = TRUE;
1911 width = INTERNAL_XWSTODS(dc, sz.cx);
1913 xwidth = width * cosEsc;
1914 ywidth = width * sinEsc;
1916 tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
1917 tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
1918 switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
1921 if (align & TA_UPDATECP)
1925 DPtoLP(hdc, &pt, 1);
1926 MoveToEx(hdc, pt.x, pt.y, NULL);
1938 if (align & TA_UPDATECP)
1942 DPtoLP(hdc, &pt, 1);
1943 MoveToEx(hdc, pt.x, pt.y, NULL);
1948 switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
1951 y += tm.tmAscent * cosEsc;
1952 x += tm.tmAscent * sinEsc;
1956 y -= tm.tmDescent * cosEsc;
1957 x -= tm.tmDescent * sinEsc;
1964 if (GetBkMode(hdc) != TRANSPARENT && !PATH_IsPathOpen(dc->path))
1966 if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
1968 if(!(flags & ETO_OPAQUE) || x < rc.left || x + width >= rc.right ||
1969 y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
1973 rc.right = x + width;
1974 rc.top = y - tm.tmAscent;
1975 rc.bottom = y + tm.tmDescent;
1976 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1981 if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
1983 HFONT orig_font = dc->hFont, cur_font;
1985 INT span = 0, *offsets = NULL, i;
1987 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
1988 for(i = 0; i < count; i++)
1990 WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
1991 if(cur_font != dc->hFont)
1996 offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
2001 for(j = 1; j < count; j++)
2003 GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
2004 offsets[j] = offsets[j-1] + INTERNAL_XWSTODS(dc, tmpsz.cx);
2009 for(j = 1; j < count; j++)
2010 offsets[j] = offsets[j-1] + deltas[j];
2015 if (PATH_IsPathOpen(dc->path))
2016 ret = PATH_ExtTextOut(dc, 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);
2020 dc->funcs->pExtTextOut(dc->physDev, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
2021 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2022 glyphs, span, deltas ? deltas + i - span : NULL);
2025 SelectObject(hdc, cur_font);
2027 glyphs[span++] = glyph;
2031 if (PATH_IsPathOpen(dc->path))
2032 ret = PATH_ExtTextOut(dc, x + (offsets ? offsets[count - span] * cosEsc : 0),
2033 y - (offsets ? offsets[count - span] * sinEsc : 0),
2034 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2035 glyphs, span, deltas ? deltas + count - span : NULL);
2037 ret = dc->funcs->pExtTextOut(dc->physDev, x + (offsets ? offsets[count - span] * cosEsc : 0),
2038 y - (offsets ? offsets[count - span] * sinEsc : 0),
2039 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2040 glyphs, span, deltas ? deltas + count - span : NULL);
2041 SelectObject(hdc, orig_font);
2042 HeapFree(GetProcessHeap(), 0, offsets);
2048 if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
2050 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2051 GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
2052 flags |= ETO_GLYPH_INDEX;
2055 if (PATH_IsPathOpen(dc->path))
2056 ret = PATH_ExtTextOut(dc, x, y, (flags & ~ETO_OPAQUE), &rc,
2057 glyphs ? glyphs : reordered_str, count, deltas);
2059 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, (flags & ~ETO_OPAQUE), &rc,
2060 glyphs ? glyphs : reordered_str, count, deltas);
2064 HeapFree(GetProcessHeap(), 0, deltas);
2065 if(glyphs != reordered_str)
2066 HeapFree(GetProcessHeap(), 0, glyphs);
2067 if(reordered_str != str)
2068 HeapFree(GetProcessHeap(), 0, reordered_str);
2070 GDI_ReleaseObj( hdc );
2072 if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2074 int underlinePos, strikeoutPos;
2075 int underlineWidth, strikeoutWidth;
2076 UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2077 OUTLINETEXTMETRICW* otm = NULL;
2082 underlineWidth = tm.tmAscent / 20 + 1;
2083 strikeoutPos = tm.tmAscent / 2;
2084 strikeoutWidth = underlineWidth;
2088 otm = HeapAlloc(GetProcessHeap(), 0, size);
2089 GetOutlineTextMetricsW(hdc, size, otm);
2090 underlinePos = otm->otmsUnderscorePosition;
2091 underlineWidth = otm->otmsUnderscoreSize;
2092 strikeoutPos = otm->otmsStrikeoutPosition;
2093 strikeoutWidth = otm->otmsStrikeoutSize;
2094 HeapFree(GetProcessHeap(), 0, otm);
2097 if (PATH_IsPathOpen(dc->path))
2101 HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2103 hbrush = SelectObject(hdc, hbrush);
2104 hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2108 pts[0].x = x - underlinePos * sinEsc;
2109 pts[0].y = y - underlinePos * cosEsc;
2110 pts[1].x = x + xwidth - underlinePos * sinEsc;
2111 pts[1].y = y - ywidth - underlinePos * cosEsc;
2112 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2113 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2114 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2115 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2116 pts[4].x = pts[0].x;
2117 pts[4].y = pts[0].y;
2118 DPtoLP(hdc, pts, 5);
2119 Polygon(hdc, pts, 5);
2124 pts[0].x = x - strikeoutPos * sinEsc;
2125 pts[0].y = y - strikeoutPos * cosEsc;
2126 pts[1].x = x + xwidth - strikeoutPos * sinEsc;
2127 pts[1].y = y - ywidth - strikeoutPos * cosEsc;
2128 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2129 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2130 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2131 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2132 pts[4].x = pts[0].x;
2133 pts[4].y = pts[0].y;
2134 DPtoLP(hdc, pts, 5);
2135 Polygon(hdc, pts, 5);
2138 SelectObject(hdc, hpen);
2139 hbrush = SelectObject(hdc, hbrush);
2140 DeleteObject(hbrush);
2144 POINT pts[2], oldpt;
2149 hpen = CreatePen(PS_SOLID, underlineWidth, GetTextColor(hdc));
2150 hpen = SelectObject(hdc, hpen);
2153 pts[1].x = x + xwidth;
2154 pts[1].y = y - ywidth;
2155 DPtoLP(hdc, pts, 2);
2156 MoveToEx(hdc, pts[0].x - underlinePos * sinEsc, pts[0].y - underlinePos * cosEsc, &oldpt);
2157 LineTo(hdc, pts[1].x - underlinePos * sinEsc, pts[1].y - underlinePos * cosEsc);
2158 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2159 DeleteObject(SelectObject(hdc, hpen));
2164 hpen = CreatePen(PS_SOLID, strikeoutWidth, GetTextColor(hdc));
2165 hpen = SelectObject(hdc, hpen);
2168 pts[1].x = x + xwidth;
2169 pts[1].y = y - ywidth;
2170 DPtoLP(hdc, pts, 2);
2171 MoveToEx(hdc, pts[0].x - strikeoutPos * sinEsc, pts[0].y - strikeoutPos * cosEsc, &oldpt);
2172 LineTo(hdc, pts[1].x - strikeoutPos * sinEsc, pts[1].y - strikeoutPos * cosEsc);
2173 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2174 DeleteObject(SelectObject(hdc, hpen));
2183 /***********************************************************************
2184 * TextOutA (GDI32.@)
2186 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2188 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2192 /***********************************************************************
2193 * TextOutW (GDI32.@)
2195 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2197 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2201 /***********************************************************************
2202 * PolyTextOutA (GDI32.@)
2206 BOOL WINAPI PolyTextOutA ( HDC hdc, /* [in] Handle to device context */
2207 PPOLYTEXTA pptxt, /* [in] Array of strings */
2208 INT cStrings ) /* [in] Number of strings in array */
2210 for (; cStrings>0; cStrings--, pptxt++)
2211 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2218 /***********************************************************************
2219 * PolyTextOutW (GDI32.@)
2221 * Draw several Strings
2227 BOOL WINAPI PolyTextOutW ( HDC hdc, /* [in] Handle to device context */
2228 PPOLYTEXTW pptxt, /* [in] Array of strings */
2229 INT cStrings ) /* [in] Number of strings in array */
2231 for (; cStrings>0; cStrings--, pptxt++)
2232 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2238 /* FIXME: all following APIs ******************************************/
2241 /***********************************************************************
2242 * SetMapperFlags (GDI32.@)
2244 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
2246 DC *dc = DC_GetDCPtr( hDC );
2249 if(dc->funcs->pSetMapperFlags)
2251 ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
2252 /* FIXME: ret is just a success flag, we should return a proper value */
2255 FIXME("(%p, 0x%08x): stub - harmless\n", hDC, dwFlag);
2256 GDI_ReleaseObj( hDC );
2260 /***********************************************************************
2261 * GetAspectRatioFilterEx (GDI.486)
2263 BOOL16 WINAPI GetAspectRatioFilterEx16( HDC16 hdc, LPSIZE16 pAspectRatio )
2265 FIXME("(%04x, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2269 /***********************************************************************
2270 * GetAspectRatioFilterEx (GDI32.@)
2272 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2274 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2279 /***********************************************************************
2280 * GetCharABCWidthsA (GDI32.@)
2282 * See GetCharABCWidthsW.
2284 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2287 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
2292 if(count <= 0) return FALSE;
2294 str = HeapAlloc(GetProcessHeap(), 0, count);
2295 for(i = 0; i < count; i++)
2296 str[i] = (BYTE)(firstChar + i);
2298 wstr = FONT_mbtowc(str, count, &wlen);
2300 for(i = 0; i < wlen; i++)
2302 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2310 HeapFree(GetProcessHeap(), 0, str);
2311 HeapFree(GetProcessHeap(), 0, wstr);
2317 /******************************************************************************
2318 * GetCharABCWidthsW [GDI32.@]
2320 * Retrieves widths of characters in range.
2323 * hdc [I] Handle of device context
2324 * firstChar [I] First character in range to query
2325 * lastChar [I] Last character in range to query
2326 * abc [O] Address of character-width structure
2329 * Only works with TrueType fonts
2335 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2338 DC *dc = DC_GetDCPtr(hdc);
2342 if (!dc) return FALSE;
2345 ret = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
2351 /* convert device units to logical */
2352 for( i = firstChar; i <= lastChar; i++, abc++ ) {
2353 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2354 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2355 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2360 GDI_ReleaseObj(hdc);
2365 /******************************************************************************
2366 * GetCharABCWidthsI [GDI32.@]
2368 * Retrieves widths of characters in range.
2371 * hdc [I] Handle of device context
2372 * firstChar [I] First glyphs in range to query
2373 * count [I] Last glyphs in range to query
2374 * pgi [i] Array of glyphs to query
2375 * abc [O] Address of character-width structure
2378 * Only works with TrueType fonts
2384 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2385 LPWORD pgi, LPABC abc)
2387 DC *dc = DC_GetDCPtr(hdc);
2391 if (!dc) return FALSE;
2394 ret = WineEngGetCharABCWidthsI( dc->gdiFont, firstChar, count, pgi, abc );
2400 /* convert device units to logical */
2401 for( i = 0; i < count; i++, abc++ ) {
2402 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2403 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2404 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2409 GDI_ReleaseObj(hdc);
2414 /***********************************************************************
2415 * GetGlyphOutlineA (GDI32.@)
2417 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2418 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2419 LPVOID lpBuffer, const MAT2 *lpmat2 )
2425 if(!(fuFormat & GGO_GLYPH_INDEX)) {
2428 if(uChar > 0xff) { /* but, 2 bytes character only */
2430 mbchs[0] = (uChar & 0xff00) >> 8;
2431 mbchs[1] = (uChar & 0xff);
2434 mbchs[0] = (uChar & 0xff);
2436 p = FONT_mbtowc(mbchs, len, NULL);
2440 ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
2442 HeapFree(GetProcessHeap(), 0, p);
2446 /***********************************************************************
2447 * GetGlyphOutlineW (GDI32.@)
2449 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2450 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2451 LPVOID lpBuffer, const MAT2 *lpmat2 )
2453 DC *dc = DC_GetDCPtr(hdc);
2456 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2457 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2459 if(!dc) return GDI_ERROR;
2462 ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
2463 cbBuffer, lpBuffer, lpmat2);
2467 GDI_ReleaseObj(hdc);
2472 /***********************************************************************
2473 * CreateScalableFontResourceA (GDI32.@)
2475 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2476 LPCSTR lpszResourceFile,
2477 LPCSTR lpszFontFile,
2478 LPCSTR lpszCurrentPath )
2482 /* fHidden=1 - only visible for the calling app, read-only, not
2483 * enumbered with EnumFonts/EnumFontFamilies
2484 * lpszCurrentPath can be NULL
2486 FIXME("(%d,%s,%s,%s): stub\n",
2487 fHidden, debugstr_a(lpszResourceFile), debugstr_a(lpszFontFile),
2488 debugstr_a(lpszCurrentPath) );
2490 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2491 if ((f = CreateFileA(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2493 SetLastError(ERROR_FILE_EXISTS);
2496 return FALSE; /* create failed */
2499 /***********************************************************************
2500 * CreateScalableFontResourceW (GDI32.@)
2502 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2503 LPCWSTR lpszResourceFile,
2504 LPCWSTR lpszFontFile,
2505 LPCWSTR lpszCurrentPath )
2507 FIXME("(%d,%p,%p,%p): stub\n",
2508 fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
2509 return FALSE; /* create failed */
2512 /*************************************************************************
2513 * GetKerningPairsA (GDI32.@)
2515 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2516 LPKERNINGPAIR kern_pairA )
2521 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2522 KERNINGPAIR *kern_pairW;
2524 if (!cPairs && kern_pairA)
2526 SetLastError(ERROR_INVALID_PARAMETER);
2530 charset = GetTextCharset(hDC);
2531 if (!TranslateCharsetInfo((DWORD *)charset, &csi, TCI_SRCCHARSET))
2533 FIXME("Can't find codepage for charset %d\n", charset);
2536 if (!GetCPInfo(csi.ciACP, &cpi))
2538 FIXME("Can't find codepage %u info\n", csi.ciACP);
2541 TRACE("charset %d => codepage %u\n", charset, csi.ciACP);
2543 total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2544 if (!total_kern_pairs) return 0;
2546 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2547 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2549 for (i = 0; i < total_kern_pairs; i++)
2553 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2556 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2559 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2564 if (kern_pairs_copied >= cPairs) break;
2566 kern_pairA->wFirst = (BYTE)first;
2567 kern_pairA->wSecond = (BYTE)second;
2568 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2571 kern_pairs_copied++;
2574 HeapFree(GetProcessHeap(), 0, kern_pairW);
2576 return kern_pairs_copied;
2579 /*************************************************************************
2580 * GetKerningPairsW (GDI32.@)
2582 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2583 LPKERNINGPAIR lpKerningPairs )
2588 TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2590 if (!cPairs && lpKerningPairs)
2592 SetLastError(ERROR_INVALID_PARAMETER);
2596 dc = DC_GetDCPtr(hDC);
2600 ret = WineEngGetKerningPairs(dc->gdiFont, cPairs, lpKerningPairs);
2602 GDI_ReleaseObj(hDC);
2606 /*************************************************************************
2607 * TranslateCharsetInfo [GDI32.@]
2609 * Fills a CHARSETINFO structure for a character set, code page, or
2610 * font. This allows making the correspondance between different labelings
2611 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2612 * of the same encoding.
2614 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2615 * only one codepage should be set in *lpSrc.
2618 * TRUE on success, FALSE on failure.
2621 BOOL WINAPI TranslateCharsetInfo(
2622 LPDWORD lpSrc, /* [in]
2623 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2624 if flags == TCI_SRCCHARSET: a character set value
2625 if flags == TCI_SRCCODEPAGE: a code page value
2627 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2628 DWORD flags /* [in] determines interpretation of lpSrc */)
2632 case TCI_SRCFONTSIG:
2633 while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
2635 case TCI_SRCCODEPAGE:
2636 while ((UINT) (lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
2638 case TCI_SRCCHARSET:
2639 while ((UINT) (lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
2644 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2645 memcpy(lpCs, &FONT_tci[index], sizeof(CHARSETINFO));
2649 /*************************************************************************
2650 * GetFontLanguageInfo (GDI32.@)
2652 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2654 FONTSIGNATURE fontsig;
2655 static const DWORD GCP_DBCS_MASK=0x003F0000,
2656 GCP_DIACRITIC_MASK=0x00000000,
2657 FLI_GLYPHS_MASK=0x00000000,
2658 GCP_GLYPHSHAPE_MASK=0x00000040,
2659 GCP_KASHIDA_MASK=0x00000000,
2660 GCP_LIGATE_MASK=0x00000000,
2661 GCP_USEKERNING_MASK=0x00000000,
2662 GCP_REORDER_MASK=0x00000060;
2666 GetTextCharsetInfo( hdc, &fontsig, 0 );
2667 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2669 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2672 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2673 result|=GCP_DIACRITIC;
2675 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2678 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2679 result|=GCP_GLYPHSHAPE;
2681 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2682 result|=GCP_KASHIDA;
2684 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2687 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2688 result|=GCP_USEKERNING;
2690 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2691 if( GetTextAlign( hdc) & TA_RTLREADING )
2692 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2693 result|=GCP_REORDER;
2699 /*************************************************************************
2700 * GetFontData [GDI32.@]
2702 * Retrieve data for TrueType font.
2706 * success: Number of bytes returned
2707 * failure: GDI_ERROR
2711 * Calls SetLastError()
2714 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2715 LPVOID buffer, DWORD length)
2717 DC *dc = DC_GetDCPtr(hdc);
2718 DWORD ret = GDI_ERROR;
2720 if(!dc) return GDI_ERROR;
2723 ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2725 GDI_ReleaseObj(hdc);
2729 /*************************************************************************
2730 * GetGlyphIndicesA [GDI32.@]
2732 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2733 LPWORD pgi, DWORD flags)
2739 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2740 hdc, debugstr_an(lpstr, count), count, pgi, flags);
2742 lpstrW = FONT_mbtowc(lpstr, count, &countW);
2743 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2744 HeapFree(GetProcessHeap(), 0, lpstrW);
2749 /*************************************************************************
2750 * GetGlyphIndicesW [GDI32.@]
2752 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2753 LPWORD pgi, DWORD flags)
2755 DC *dc = DC_GetDCPtr(hdc);
2756 DWORD ret = GDI_ERROR;
2758 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2759 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2761 if(!dc) return GDI_ERROR;
2764 ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2766 GDI_ReleaseObj(hdc);
2770 /*************************************************************************
2771 * GetCharacterPlacementA [GDI32.@]
2773 * See GetCharacterPlacementW.
2776 * the web browser control of ie4 calls this with dwFlags=0
2779 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2780 INT nMaxExtent, GCP_RESULTSA *lpResults,
2785 GCP_RESULTSW resultsW;
2788 TRACE("%s, %d, %d, 0x%08x\n",
2789 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2791 /* both structs are equal in size */
2792 memcpy(&resultsW, lpResults, sizeof(resultsW));
2794 lpStringW = FONT_mbtowc(lpString, uCount, &uCountW);
2795 if(lpResults->lpOutString)
2796 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2798 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2800 lpResults->nGlyphs = resultsW.nGlyphs;
2801 lpResults->nMaxFit = resultsW.nMaxFit;
2803 if(lpResults->lpOutString) {
2804 WideCharToMultiByte(CP_ACP, 0, resultsW.lpOutString, uCountW,
2805 lpResults->lpOutString, uCount, NULL, NULL );
2808 HeapFree(GetProcessHeap(), 0, lpStringW);
2809 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2814 /*************************************************************************
2815 * GetCharacterPlacementW [GDI32.@]
2817 * Retrieve information about a string. This includes the width, reordering,
2818 * Glyphing and so on.
2822 * The width and height of the string if successful, 0 if failed.
2826 * All flags except GCP_REORDER are not yet implemented.
2827 * Reordering is not 100% complient to the Windows BiDi method.
2828 * Caret positioning is not yet implemented for BiDi.
2829 * Classes are not yet implemented.
2833 GetCharacterPlacementW(
2834 HDC hdc, /* [in] Device context for which the rendering is to be done */
2835 LPCWSTR lpString, /* [in] The string for which information is to be returned */
2836 INT uCount, /* [in] Number of WORDS in string. */
2837 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
2838 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2839 DWORD dwFlags /* [in] Flags specifying how to process the string */
2846 TRACE("%s, %d, %d, 0x%08x\n",
2847 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2849 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2850 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2851 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2852 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2853 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2855 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08x ignored\n", dwFlags);
2856 if(lpResults->lpClass) FIXME("classes not implemented\n");
2857 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2858 FIXME("Caret positions for complex scripts not implemented\n");
2860 nSet = (UINT)uCount;
2861 if(nSet > lpResults->nGlyphs)
2862 nSet = lpResults->nGlyphs;
2864 /* return number of initialized fields */
2865 lpResults->nGlyphs = nSet;
2867 if((dwFlags&GCP_REORDER)==0 || !BidiAvail)
2869 /* Treat the case where no special handling was requested in a fastpath way */
2870 /* copy will do if the GCP_REORDER flag is not set */
2871 if(lpResults->lpOutString)
2872 memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
2874 if(lpResults->lpOrder)
2876 for(i = 0; i < nSet; i++)
2877 lpResults->lpOrder[i] = i;
2881 BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
2882 nSet, lpResults->lpOrder );
2885 /* FIXME: Will use the placement chars */
2886 if (lpResults->lpDx)
2889 for (i = 0; i < nSet; i++)
2891 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
2892 lpResults->lpDx[i]= c;
2896 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
2900 lpResults->lpCaretPos[0] = 0;
2901 for (i = 1; i < nSet; i++)
2902 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
2903 lpResults->lpCaretPos[i] = (pos += size.cx);
2906 if(lpResults->lpGlyphs)
2907 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
2909 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
2910 ret = MAKELONG(size.cx, size.cy);
2915 /*************************************************************************
2916 * GetCharABCWidthsFloatA [GDI32.@]
2918 * See GetCharABCWidthsFloatW.
2920 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
2922 INT i, wlen, count = (INT)(last - first + 1);
2927 if (count <= 0) return FALSE;
2929 str = HeapAlloc(GetProcessHeap(), 0, count);
2931 for(i = 0; i < count; i++)
2932 str[i] = (BYTE)(first + i);
2934 wstr = FONT_mbtowc(str, count, &wlen);
2936 for (i = 0; i < wlen; i++)
2938 if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
2946 HeapFree( GetProcessHeap(), 0, str );
2947 HeapFree( GetProcessHeap(), 0, wstr );
2952 /*************************************************************************
2953 * GetCharABCWidthsFloatW [GDI32.@]
2955 * Retrieves widths of a range of characters.
2958 * hdc [I] Handle to device context.
2959 * first [I] First character in range to query.
2960 * last [I] Last character in range to query.
2961 * abcf [O] Array of LPABCFLOAT structures.
2968 * Only works with TrueType fonts. It also doesn't return real
2969 * floats but converted integers because it's implemented on
2970 * top of GetCharABCWidthsW.
2972 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
2975 unsigned int i, size = sizeof(ABC) * (last - first + 1);
2978 TRACE("%p, %d, %d, %p - partial stub\n", hdc, first, last, abcf);
2980 abc = HeapAlloc( GetProcessHeap(), 0, size );
2981 if (!abc) return FALSE;
2983 ret = GetCharABCWidthsW( hdc, first, last, abc );
2986 for (i = first; i <= last; i++, abc++, abcf++)
2988 abcf->abcfA = abc->abcA;
2989 abcf->abcfB = abc->abcB;
2990 abcf->abcfC = abc->abcC;
2993 HeapFree( GetProcessHeap(), 0, abc );
2997 /*************************************************************************
2998 * GetCharWidthFloatA [GDI32.@]
3000 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
3001 UINT iLastChar, PFLOAT pxBuffer)
3003 FIXME_(gdi)("GetCharWidthFloatA, stub\n");
3007 /*************************************************************************
3008 * GetCharWidthFloatW [GDI32.@]
3010 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
3011 UINT iLastChar, PFLOAT pxBuffer)
3013 FIXME_(gdi)("GetCharWidthFloatW, stub\n");
3018 /***********************************************************************
3020 * Font Resource API *
3022 ***********************************************************************/
3024 /***********************************************************************
3025 * AddFontResourceA (GDI32.@)
3027 INT WINAPI AddFontResourceA( LPCSTR str )
3029 return AddFontResourceExA( str, 0, NULL);
3032 /***********************************************************************
3033 * AddFontResourceW (GDI32.@)
3035 INT WINAPI AddFontResourceW( LPCWSTR str )
3037 return AddFontResourceExW(str, 0, NULL);
3041 /***********************************************************************
3042 * AddFontResourceExA (GDI32.@)
3044 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3046 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3047 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3050 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3051 ret = AddFontResourceExW(strW, fl, pdv);
3052 HeapFree(GetProcessHeap(), 0, strW);
3056 /***********************************************************************
3057 * AddFontResourceExW (GDI32.@)
3059 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3061 return WineEngAddFontResourceEx(str, fl, pdv);
3064 /***********************************************************************
3065 * RemoveFontResourceA (GDI32.@)
3067 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3069 return RemoveFontResourceExA(str, 0, 0);
3072 /***********************************************************************
3073 * RemoveFontResourceW (GDI32.@)
3075 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3077 return RemoveFontResourceExW(str, 0, 0);
3080 /***********************************************************************
3081 * AddFontMemResourceEx (GDI32.@)
3083 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3085 FIXME("(%p,%08x,%p,%p): stub\n", pbFont, cbFont, pdv, pcFonts);
3089 /***********************************************************************
3090 * RemoveFontResourceExA (GDI32.@)
3092 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3094 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3095 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3098 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3099 ret = RemoveFontResourceExW(strW, fl, pdv);
3100 HeapFree(GetProcessHeap(), 0, strW);
3104 /***********************************************************************
3105 * RemoveFontResourceExW (GDI32.@)
3107 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3109 return WineEngRemoveFontResourceEx(str, fl, pdv);
3112 /***********************************************************************
3113 * GetTextCharset (GDI32.@)
3115 UINT WINAPI GetTextCharset(HDC hdc)
3117 /* MSDN docs say this is equivalent */
3118 return GetTextCharsetInfo(hdc, NULL, 0);
3121 /***********************************************************************
3122 * GetTextCharsetInfo (GDI32.@)
3124 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3126 UINT ret = DEFAULT_CHARSET;
3127 DC *dc = DC_GetDCPtr(hdc);
3132 ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
3134 GDI_ReleaseObj(hdc);
3137 if (ret == DEFAULT_CHARSET && fs)
3138 memset(fs, 0, sizeof(FONTSIGNATURE));
3142 /***********************************************************************
3143 * GdiGetCharDimensions (GDI32.@)
3145 * Gets the average width of the characters in the English alphabet.
3148 * hdc [I] Handle to the device context to measure on.
3149 * lptm [O] Pointer to memory to store the text metrics into.
3150 * height [O] On exit, the maximum height of characters in the English alphabet.
3153 * The average width of characters in the English alphabet.
3156 * This function is used by the dialog manager to get the size of a dialog
3157 * unit. It should also be used by other pieces of code that need to know
3158 * the size of a dialog unit in logical units without having access to the
3159 * window handle of the dialog.
3160 * Windows caches the font metrics from this function, but we don't and
3161 * there doesn't appear to be an immediate advantage to do so.
3164 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3166 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3169 static const WCHAR alphabet[] = {
3170 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3171 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3172 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3174 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3176 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3178 if (height) *height = sz.cy;
3179 return (sz.cx / 26 + 1) / 2;
3182 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3184 FIXME("(%d): stub\n", fEnableEUDC);
3188 /***********************************************************************
3189 * GetCharWidthI (GDI32.@)
3191 BOOL WINAPI GetCharWidthI(HDC hdc, UINT giFirst, UINT cgi, LPWORD pgi, LPINT lpBuffer)
3193 FIXME("(%p, %d, %d, %p, %p): stub\n", hdc, giFirst, cgi, pgi, lpBuffer);
3197 /***********************************************************************
3198 * GetFontUnicodeRanges (GDI32.@)
3200 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3202 FIXME("(%p, %p): stub\n", hdc, lpgs);