4 * Copyright 1993 Alexandre Julliard
6 * Copyright 2002,2003 Shachar Shemesh
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "wine/port.h"
35 #include "gdi_private.h"
36 #include "wine/unicode.h"
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(font);
41 /* Device -> World size conversion */
43 /* Performs a device to world transformation on the specified width (which
44 * is in integer format).
46 static inline INT INTERNAL_XDSTOWS(DC *dc, INT width)
50 /* Perform operation with floating point */
51 floatWidth = (FLOAT)width * dc->xformVport2World.eM11;
52 /* Round to integers */
53 return GDI_ROUND(floatWidth);
56 /* Performs a device to world transformation on the specified size (which
57 * is in integer format).
59 static inline INT INTERNAL_YDSTOWS(DC *dc, INT height)
63 /* Perform operation with floating point */
64 floatHeight = (FLOAT)height * dc->xformVport2World.eM22;
65 /* Round to integers */
66 return GDI_ROUND(floatHeight);
69 static inline INT INTERNAL_XWSTODS(DC *dc, INT width)
72 pt[0].x = pt[0].y = 0;
75 LPtoDP(dc->hSelf, pt, 2);
76 return pt[1].x - pt[0].x;
79 static inline INT INTERNAL_YWSTODS(DC *dc, INT height)
82 pt[0].x = pt[0].y = 0;
85 LPtoDP(dc->hSelf, pt, 2);
86 return pt[1].y - pt[0].y;
89 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, void *obj, HDC hdc );
90 static INT FONT_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
91 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
92 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
93 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj );
95 static const struct gdi_obj_funcs font_funcs =
97 FONT_SelectObject, /* pSelectObject */
98 FONT_GetObject16, /* pGetObject16 */
99 FONT_GetObjectA, /* pGetObjectA */
100 FONT_GetObjectW, /* pGetObjectW */
101 NULL, /* pUnrealizeObject */
102 FONT_DeleteObject /* pDeleteObject */
105 #define ENUM_UNICODE 0x00000001
106 #define ENUM_CALLED 0x00000002
116 LPLOGFONT16 lpLogFontParam;
117 FONTENUMPROC16 lpEnumFunc;
120 LPNEWTEXTMETRICEX16 lpTextMetric;
121 LPENUMLOGFONTEX16 lpLogFont;
122 SEGPTR segTextMetric;
132 LPLOGFONTW lpLogFontParam;
133 FONTENUMPROCW lpEnumFunc;
142 * For TranslateCharsetInfo
144 #define FS(x) {{0,0,0,0},{0x1<<(x),0}}
145 #define MAXTCIINDEX 32
146 static const CHARSETINFO FONT_tci[MAXTCIINDEX] = {
148 { ANSI_CHARSET, 1252, FS(0)},
149 { EASTEUROPE_CHARSET, 1250, FS(1)},
150 { RUSSIAN_CHARSET, 1251, FS(2)},
151 { GREEK_CHARSET, 1253, FS(3)},
152 { TURKISH_CHARSET, 1254, FS(4)},
153 { HEBREW_CHARSET, 1255, FS(5)},
154 { ARABIC_CHARSET, 1256, FS(6)},
155 { BALTIC_CHARSET, 1257, FS(7)},
156 { VIETNAMESE_CHARSET, 1258, FS(8)},
157 /* reserved by ANSI */
158 { DEFAULT_CHARSET, 0, FS(0)},
159 { DEFAULT_CHARSET, 0, FS(0)},
160 { DEFAULT_CHARSET, 0, FS(0)},
161 { DEFAULT_CHARSET, 0, FS(0)},
162 { DEFAULT_CHARSET, 0, FS(0)},
163 { DEFAULT_CHARSET, 0, FS(0)},
164 { DEFAULT_CHARSET, 0, FS(0)},
166 { THAI_CHARSET, 874, FS(16)},
167 { SHIFTJIS_CHARSET, 932, FS(17)},
168 { GB2312_CHARSET, 936, FS(18)},
169 { HANGEUL_CHARSET, 949, FS(19)},
170 { CHINESEBIG5_CHARSET, 950, FS(20)},
171 { JOHAB_CHARSET, 1361, FS(21)},
172 /* reserved for alternate ANSI and OEM */
173 { DEFAULT_CHARSET, 0, FS(0)},
174 { DEFAULT_CHARSET, 0, FS(0)},
175 { DEFAULT_CHARSET, 0, FS(0)},
176 { DEFAULT_CHARSET, 0, FS(0)},
177 { DEFAULT_CHARSET, 0, FS(0)},
178 { DEFAULT_CHARSET, 0, FS(0)},
179 { DEFAULT_CHARSET, 0, FS(0)},
180 { DEFAULT_CHARSET, 0, FS(0)},
181 /* reserved for system */
182 { DEFAULT_CHARSET, 0, FS(0)},
183 { SYMBOL_CHARSET, CP_SYMBOL, FS(31)},
186 /***********************************************************************
187 * LOGFONT conversion functions.
189 static void FONT_LogFontWTo16( const LOGFONTW* font32, LPLOGFONT16 font16 )
191 font16->lfHeight = font32->lfHeight;
192 font16->lfWidth = font32->lfWidth;
193 font16->lfEscapement = font32->lfEscapement;
194 font16->lfOrientation = font32->lfOrientation;
195 font16->lfWeight = font32->lfWeight;
196 font16->lfItalic = font32->lfItalic;
197 font16->lfUnderline = font32->lfUnderline;
198 font16->lfStrikeOut = font32->lfStrikeOut;
199 font16->lfCharSet = font32->lfCharSet;
200 font16->lfOutPrecision = font32->lfOutPrecision;
201 font16->lfClipPrecision = font32->lfClipPrecision;
202 font16->lfQuality = font32->lfQuality;
203 font16->lfPitchAndFamily = font32->lfPitchAndFamily;
204 WideCharToMultiByte( CP_ACP, 0, font32->lfFaceName, -1,
205 font16->lfFaceName, LF_FACESIZE, NULL, NULL );
206 font16->lfFaceName[LF_FACESIZE-1] = 0;
209 static void FONT_LogFont16ToW( const LOGFONT16 *font16, LPLOGFONTW font32 )
211 font32->lfHeight = font16->lfHeight;
212 font32->lfWidth = font16->lfWidth;
213 font32->lfEscapement = font16->lfEscapement;
214 font32->lfOrientation = font16->lfOrientation;
215 font32->lfWeight = font16->lfWeight;
216 font32->lfItalic = font16->lfItalic;
217 font32->lfUnderline = font16->lfUnderline;
218 font32->lfStrikeOut = font16->lfStrikeOut;
219 font32->lfCharSet = font16->lfCharSet;
220 font32->lfOutPrecision = font16->lfOutPrecision;
221 font32->lfClipPrecision = font16->lfClipPrecision;
222 font32->lfQuality = font16->lfQuality;
223 font32->lfPitchAndFamily = font16->lfPitchAndFamily;
224 MultiByteToWideChar( CP_ACP, 0, font16->lfFaceName, -1, font32->lfFaceName, LF_FACESIZE );
225 font32->lfFaceName[LF_FACESIZE-1] = 0;
228 static void FONT_LogFontAToW( const LOGFONTA *fontA, LPLOGFONTW fontW )
230 memcpy(fontW, fontA, sizeof(LOGFONTA) - LF_FACESIZE);
231 MultiByteToWideChar(CP_ACP, 0, fontA->lfFaceName, -1, fontW->lfFaceName,
233 fontW->lfFaceName[LF_FACESIZE-1] = 0;
236 static void FONT_LogFontWToA( const LOGFONTW *fontW, LPLOGFONTA fontA )
238 memcpy(fontA, fontW, sizeof(LOGFONTA) - LF_FACESIZE);
239 WideCharToMultiByte(CP_ACP, 0, fontW->lfFaceName, -1, fontA->lfFaceName,
240 LF_FACESIZE, NULL, NULL);
241 fontA->lfFaceName[LF_FACESIZE-1] = 0;
244 static void FONT_EnumLogFontExWTo16( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEX16 font16 )
246 FONT_LogFontWTo16( (const LOGFONTW *)fontW, (LPLOGFONT16)font16);
248 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
249 (LPSTR) font16->elfFullName, LF_FULLFACESIZE, NULL, NULL );
250 font16->elfFullName[LF_FULLFACESIZE-1] = '\0';
251 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
252 (LPSTR) font16->elfStyle, LF_FACESIZE, NULL, NULL );
253 font16->elfStyle[LF_FACESIZE-1] = '\0';
254 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
255 (LPSTR) font16->elfScript, LF_FACESIZE, NULL, NULL );
256 font16->elfScript[LF_FACESIZE-1] = '\0';
259 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEXA fontA )
261 FONT_LogFontWToA( (const LOGFONTW *)fontW, (LPLOGFONTA)fontA);
263 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
264 (LPSTR) fontA->elfFullName, LF_FULLFACESIZE, NULL, NULL );
265 fontA->elfFullName[LF_FULLFACESIZE-1] = '\0';
266 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
267 (LPSTR) fontA->elfStyle, LF_FACESIZE, NULL, NULL );
268 fontA->elfStyle[LF_FACESIZE-1] = '\0';
269 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
270 (LPSTR) fontA->elfScript, LF_FACESIZE, NULL, NULL );
271 fontA->elfScript[LF_FACESIZE-1] = '\0';
274 /***********************************************************************
275 * TEXTMETRIC conversion functions.
277 static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
279 ptmA->tmHeight = ptmW->tmHeight;
280 ptmA->tmAscent = ptmW->tmAscent;
281 ptmA->tmDescent = ptmW->tmDescent;
282 ptmA->tmInternalLeading = ptmW->tmInternalLeading;
283 ptmA->tmExternalLeading = ptmW->tmExternalLeading;
284 ptmA->tmAveCharWidth = ptmW->tmAveCharWidth;
285 ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth;
286 ptmA->tmWeight = ptmW->tmWeight;
287 ptmA->tmOverhang = ptmW->tmOverhang;
288 ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX;
289 ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
290 ptmA->tmFirstChar = ptmW->tmFirstChar > 255 ? 255 : ptmW->tmFirstChar;
291 ptmA->tmLastChar = ptmW->tmLastChar > 255 ? 255 : ptmW->tmLastChar;
292 ptmA->tmDefaultChar = ptmW->tmDefaultChar > 255 ? 255 : ptmW->tmDefaultChar;
293 ptmA->tmBreakChar = ptmW->tmBreakChar > 255 ? 255 : ptmW->tmBreakChar;
294 ptmA->tmItalic = ptmW->tmItalic;
295 ptmA->tmUnderlined = ptmW->tmUnderlined;
296 ptmA->tmStruckOut = ptmW->tmStruckOut;
297 ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
298 ptmA->tmCharSet = ptmW->tmCharSet;
302 static void FONT_NewTextMetricExWTo16(const NEWTEXTMETRICEXW *ptmW, LPNEWTEXTMETRICEX16 ptm16 )
304 ptm16->ntmTm.tmHeight = ptmW->ntmTm.tmHeight;
305 ptm16->ntmTm.tmAscent = ptmW->ntmTm.tmAscent;
306 ptm16->ntmTm.tmDescent = ptmW->ntmTm.tmDescent;
307 ptm16->ntmTm.tmInternalLeading = ptmW->ntmTm.tmInternalLeading;
308 ptm16->ntmTm.tmExternalLeading = ptmW->ntmTm.tmExternalLeading;
309 ptm16->ntmTm.tmAveCharWidth = ptmW->ntmTm.tmAveCharWidth;
310 ptm16->ntmTm.tmMaxCharWidth = ptmW->ntmTm.tmMaxCharWidth;
311 ptm16->ntmTm.tmWeight = ptmW->ntmTm.tmWeight;
312 ptm16->ntmTm.tmOverhang = ptmW->ntmTm.tmOverhang;
313 ptm16->ntmTm.tmDigitizedAspectX = ptmW->ntmTm.tmDigitizedAspectX;
314 ptm16->ntmTm.tmDigitizedAspectY = ptmW->ntmTm.tmDigitizedAspectY;
315 ptm16->ntmTm.tmFirstChar = ptmW->ntmTm.tmFirstChar > 255 ? 255 : ptmW->ntmTm.tmFirstChar;
316 ptm16->ntmTm.tmLastChar = ptmW->ntmTm.tmLastChar > 255 ? 255 : ptmW->ntmTm.tmLastChar;
317 ptm16->ntmTm.tmDefaultChar = ptmW->ntmTm.tmDefaultChar > 255 ? 255 : ptmW->ntmTm.tmDefaultChar;
318 ptm16->ntmTm.tmBreakChar = ptmW->ntmTm.tmBreakChar > 255 ? 255 : ptmW->ntmTm.tmBreakChar;
319 ptm16->ntmTm.tmItalic = ptmW->ntmTm.tmItalic;
320 ptm16->ntmTm.tmUnderlined = ptmW->ntmTm.tmUnderlined;
321 ptm16->ntmTm.tmStruckOut = ptmW->ntmTm.tmStruckOut;
322 ptm16->ntmTm.tmPitchAndFamily = ptmW->ntmTm.tmPitchAndFamily;
323 ptm16->ntmTm.tmCharSet = ptmW->ntmTm.tmCharSet;
324 ptm16->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
325 ptm16->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
326 ptm16->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
327 ptm16->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
328 memcpy(&ptm16->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
331 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW *ptmW, NEWTEXTMETRICEXA *ptmA )
333 FONT_TextMetricWToA((const TEXTMETRICW *)ptmW, (LPTEXTMETRICA)ptmA);
334 ptmA->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
335 ptmA->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
336 ptmA->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
337 ptmA->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
338 memcpy(&ptmA->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
342 /***********************************************************************
345 * Returns a Unicode translation of str. If count is -1 then str is
346 * assumed to be '\0' terminated, otherwise it contains the number of
347 * bytes to convert. If plenW is non-NULL, on return it will point to
348 * the number of WCHARs that have been written. The caller should free
349 * the returned LPWSTR from the process heap itself.
351 static LPWSTR FONT_mbtowc(LPCSTR str, INT count, INT *plenW)
357 if(count == -1) count = strlen(str);
358 lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
359 strW = HeapAlloc(GetProcessHeap(), 0, lenW*sizeof(WCHAR));
360 MultiByteToWideChar(cp, 0, str, count, strW, lenW);
361 TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW));
362 if(plenW) *plenW = lenW;
367 /***********************************************************************
368 * CreateFontIndirectA (GDI32.@)
370 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *plfA )
375 FONT_LogFontAToW( plfA, &lfW );
376 return CreateFontIndirectW( &lfW );
378 return CreateFontIndirectW( NULL );
382 /***********************************************************************
383 * CreateFontIndirectW (GDI32.@)
385 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
392 if ((fontPtr = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC,
393 (HGDIOBJ *)&hFont, &font_funcs )))
395 static const WCHAR ItalicW[] = {' ','I','t','a','l','i','c','\0'};
396 static const WCHAR BoldW[] = {' ','B','o','l','d','\0'};
397 WCHAR *pFaceNameItalicSuffix, *pFaceNameBoldSuffix;
398 WCHAR* pFaceNameSuffix = NULL;
400 memcpy( &fontPtr->logfont, plf, sizeof(LOGFONTW) );
402 TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
403 plf->lfHeight, plf->lfWidth,
404 plf->lfEscapement, plf->lfOrientation,
405 plf->lfPitchAndFamily,
406 plf->lfOutPrecision, plf->lfClipPrecision,
407 plf->lfQuality, plf->lfCharSet,
408 debugstr_w(plf->lfFaceName),
409 plf->lfWeight > 400 ? "Bold" : "",
410 plf->lfItalic ? "Italic" : "",
411 plf->lfUnderline ? "Underline" : "", hFont);
413 if (plf->lfEscapement != plf->lfOrientation) {
414 /* this should really depend on whether GM_ADVANCED is set */
415 fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
416 WARN("orientation angle %f set to "
417 "escapement angle %f for new font %p\n",
418 plf->lfOrientation/10., plf->lfEscapement/10., hFont);
421 pFaceNameItalicSuffix = strstrW(fontPtr->logfont.lfFaceName, ItalicW);
422 if (pFaceNameItalicSuffix) {
423 fontPtr->logfont.lfItalic = TRUE;
424 pFaceNameSuffix = pFaceNameItalicSuffix;
427 pFaceNameBoldSuffix = strstrW(fontPtr->logfont.lfFaceName, BoldW);
428 if (pFaceNameBoldSuffix) {
429 if (fontPtr->logfont.lfWeight < FW_BOLD) {
430 fontPtr->logfont.lfWeight = FW_BOLD;
432 if (!pFaceNameSuffix ||
433 (pFaceNameBoldSuffix < pFaceNameSuffix)) {
434 pFaceNameSuffix = pFaceNameBoldSuffix;
438 if (pFaceNameSuffix) *pFaceNameSuffix = 0;
440 GDI_ReleaseObj( hFont );
443 else WARN("(NULL) => NULL\n");
448 /*************************************************************************
449 * CreateFontA (GDI32.@)
451 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
452 INT orient, INT weight, DWORD italic,
453 DWORD underline, DWORD strikeout, DWORD charset,
454 DWORD outpres, DWORD clippres, DWORD quality,
455 DWORD pitch, LPCSTR name )
459 logfont.lfHeight = height;
460 logfont.lfWidth = width;
461 logfont.lfEscapement = esc;
462 logfont.lfOrientation = orient;
463 logfont.lfWeight = weight;
464 logfont.lfItalic = italic;
465 logfont.lfUnderline = underline;
466 logfont.lfStrikeOut = strikeout;
467 logfont.lfCharSet = charset;
468 logfont.lfOutPrecision = outpres;
469 logfont.lfClipPrecision = clippres;
470 logfont.lfQuality = quality;
471 logfont.lfPitchAndFamily = pitch;
474 lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
476 logfont.lfFaceName[0] = '\0';
478 return CreateFontIndirectA( &logfont );
481 /*************************************************************************
482 * CreateFontW (GDI32.@)
484 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
485 INT orient, INT weight, DWORD italic,
486 DWORD underline, DWORD strikeout, DWORD charset,
487 DWORD outpres, DWORD clippres, DWORD quality,
488 DWORD pitch, LPCWSTR name )
492 logfont.lfHeight = height;
493 logfont.lfWidth = width;
494 logfont.lfEscapement = esc;
495 logfont.lfOrientation = orient;
496 logfont.lfWeight = weight;
497 logfont.lfItalic = italic;
498 logfont.lfUnderline = underline;
499 logfont.lfStrikeOut = strikeout;
500 logfont.lfCharSet = charset;
501 logfont.lfOutPrecision = outpres;
502 logfont.lfClipPrecision = clippres;
503 logfont.lfQuality = quality;
504 logfont.lfPitchAndFamily = pitch;
507 lstrcpynW(logfont.lfFaceName, name,
508 sizeof(logfont.lfFaceName) / sizeof(WCHAR));
510 logfont.lfFaceName[0] = '\0';
512 return CreateFontIndirectW( &logfont );
516 /***********************************************************************
519 * If the driver supports vector fonts we create a gdi font first and
520 * then call the driver to give it a chance to supply its own device
521 * font. If the driver wants to do this it returns TRUE and we can
522 * delete the gdi font, if the driver wants to use the gdi font it
523 * should return FALSE, to signal an error return GDI_ERROR. For
524 * drivers that don't support vector fonts they must supply their own
527 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, void *obj, HDC hdc )
530 DC *dc = DC_GetDCPtr( hdc );
534 if (dc->hFont != handle || dc->gdiFont == NULL)
536 if(GetDeviceCaps(dc->hSelf, TEXTCAPS) & TC_VA_ABLE)
537 dc->gdiFont = WineEngCreateFontInstance(dc, handle);
540 if (dc->funcs->pSelectFont) ret = dc->funcs->pSelectFont( dc->physDev, handle, dc->gdiFont );
542 if (ret && dc->gdiFont) dc->gdiFont = 0;
544 if (ret == HGDI_ERROR)
545 ret = 0; /* SelectObject returns 0 on error */
551 GDI_ReleaseObj( hdc );
556 /***********************************************************************
559 static INT FONT_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
564 FONT_LogFontWTo16( &font->logfont, &lf16 );
566 if (count > sizeof(LOGFONT16)) count = sizeof(LOGFONT16);
567 memcpy( buffer, &lf16, count );
571 /***********************************************************************
574 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
581 FONT_LogFontWToA( &font->logfont, &lfA );
583 if (count > sizeof(lfA)) count = sizeof(lfA);
584 memcpy( buffer, &lfA, count );
588 /***********************************************************************
591 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
595 return sizeof(LOGFONTW);
596 if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
597 memcpy( buffer, &font->logfont, count );
602 /***********************************************************************
605 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj )
607 WineEngDestroyFontInstance( handle );
608 return GDI_FreeObject( handle, obj );
612 /***********************************************************************
613 * FONT_EnumInstance16
615 * Called by the device driver layer to pass font info
616 * down to the application.
618 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
619 * We have to use other types because of the FONTENUMPROCW definition.
621 static INT CALLBACK FONT_EnumInstance16( const LOGFONTW *plf, const TEXTMETRICW *ptm,
622 DWORD fType, LPARAM lp )
624 fontEnum16 *pfe = (fontEnum16*)lp;
628 if( pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
629 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet )
634 FONT_EnumLogFontExWTo16((const ENUMLOGFONTEXW *)plf, pfe->lpLogFont);
635 FONT_NewTextMetricExWTo16((const NEWTEXTMETRICEXW *)ptm, pfe->lpTextMetric);
636 pfe->dwFlags |= ENUM_CALLED;
637 GDI_ReleaseObj( pfe->hdc ); /* release the GDI lock */
639 args[6] = SELECTOROF(pfe->segLogFont);
640 args[5] = OFFSETOF(pfe->segLogFont);
641 args[4] = SELECTOROF(pfe->segTextMetric);
642 args[3] = OFFSETOF(pfe->segTextMetric);
644 args[1] = HIWORD(pfe->lpData);
645 args[0] = LOWORD(pfe->lpData);
646 WOWCallback16Ex( (DWORD)pfe->lpEnumFunc, WCB16_PASCAL, sizeof(args), args, &result );
647 ret = LOWORD(result);
649 /* get the lock again and make sure the DC is still valid */
650 dc = DC_GetDCPtr( pfe->hdc );
651 if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
653 if (dc) GDI_ReleaseObj( pfe->hdc );
654 pfe->hdc = 0; /* make sure we don't try to release it later on */
661 /***********************************************************************
664 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
665 * We have to use other types because of the FONTENUMPROCW definition.
667 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
668 DWORD fType, LPARAM lp )
670 fontEnum32 *pfe = (fontEnum32*)lp;
674 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
675 if((pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
676 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
677 (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
679 /* convert font metrics */
680 ENUMLOGFONTEXA logfont;
681 NEWTEXTMETRICEXA tmA;
683 pfe->dwFlags |= ENUM_CALLED;
684 if (!(pfe->dwFlags & ENUM_UNICODE))
686 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
687 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
688 plf = (LOGFONTW *)&logfont.elfLogFont;
689 ptm = (TEXTMETRICW *)&tmA;
691 GDI_ReleaseObj( pfe->hdc ); /* release the GDI lock */
693 ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
695 /* get the lock again and make sure the DC is still valid */
696 dc = DC_GetDCPtr( pfe->hdc );
697 if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
699 if (dc) GDI_ReleaseObj( pfe->hdc );
700 pfe->hdc = 0; /* make sure we don't try to release it later on */
707 /***********************************************************************
708 * EnumFontFamiliesEx (GDI.613)
710 INT16 WINAPI EnumFontFamiliesEx16( HDC16 hDC, LPLOGFONT16 plf,
711 FONTENUMPROC16 efproc, LPARAM lParam,
716 DC* dc = DC_GetDCPtr( HDC_32(hDC) );
717 NEWTEXTMETRICEX16 tm16;
718 ENUMLOGFONTEX16 lf16;
723 FONT_LogFont16ToW(plf, &lfW);
725 fe16.hdc = HDC_32(hDC);
727 fe16.physDev = dc->physDev;
728 fe16.lpLogFontParam = plf;
729 fe16.lpEnumFunc = efproc;
730 fe16.lpData = lParam;
731 fe16.lpTextMetric = &tm16;
732 fe16.lpLogFont = &lf16;
733 fe16.segTextMetric = MapLS( &tm16 );
734 fe16.segLogFont = MapLS( &lf16 );
737 enum_gdi_fonts = GetDeviceCaps(fe16.hdc, TEXTCAPS) & TC_VA_ABLE;
739 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
746 ret = WineEngEnumFonts( &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
747 fe16.dwFlags &= ~ENUM_CALLED;
748 if (ret && dc->funcs->pEnumDeviceFonts) {
749 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
750 if(fe16.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
754 UnMapLS( fe16.segTextMetric );
755 UnMapLS( fe16.segLogFont );
756 if (fe16.hdc) GDI_ReleaseObj( fe16.hdc );
760 /***********************************************************************
761 * FONT_EnumFontFamiliesEx
763 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf,
764 FONTENUMPROCW efproc,
765 LPARAM lParam, DWORD dwUnicode)
768 DC *dc = DC_GetDCPtr( hDC );
774 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName),
776 fe32.lpLogFontParam = plf;
777 fe32.lpEnumFunc = efproc;
778 fe32.lpData = lParam;
779 fe32.dwFlags = dwUnicode;
782 fe32.physDev = dc->physDev;
784 enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE;
786 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
793 ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
794 fe32.dwFlags &= ~ENUM_CALLED;
795 if (ret && dc->funcs->pEnumDeviceFonts) {
796 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, plf, FONT_EnumInstance, (LPARAM)&fe32 );
797 if(fe32.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
801 if (fe32.hdc) GDI_ReleaseObj( fe32.hdc );
805 /***********************************************************************
806 * EnumFontFamiliesExW (GDI32.@)
808 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
809 FONTENUMPROCW efproc,
810 LPARAM lParam, DWORD dwFlags )
812 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, ENUM_UNICODE );
815 /***********************************************************************
816 * EnumFontFamiliesExA (GDI32.@)
818 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
819 FONTENUMPROCA efproc,
820 LPARAM lParam, DWORD dwFlags)
823 FONT_LogFontAToW( plf, &lfW );
825 return FONT_EnumFontFamiliesEx( hDC, &lfW, (FONTENUMPROCW)efproc, lParam, 0);
828 /***********************************************************************
829 * EnumFontFamilies (GDI.330)
831 INT16 WINAPI EnumFontFamilies16( HDC16 hDC, LPCSTR lpFamily,
832 FONTENUMPROC16 efproc, LPARAM lpData )
836 lf.lfCharSet = DEFAULT_CHARSET;
837 if( lpFamily ) lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
838 else lf.lfFaceName[0] = '\0';
840 return EnumFontFamiliesEx16( hDC, &lf, efproc, lpData, 0 );
843 /***********************************************************************
844 * EnumFontFamiliesA (GDI32.@)
846 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
847 FONTENUMPROCA efproc, LPARAM lpData )
851 lf.lfCharSet = DEFAULT_CHARSET;
852 if( lpFamily ) lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
853 else lf.lfFaceName[0] = lf.lfFaceName[1] = '\0';
855 return EnumFontFamiliesExA( hDC, &lf, efproc, lpData, 0 );
858 /***********************************************************************
859 * EnumFontFamiliesW (GDI32.@)
861 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
862 FONTENUMPROCW efproc, LPARAM lpData )
866 lf.lfCharSet = DEFAULT_CHARSET;
867 if( lpFamily ) lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
868 else lf.lfFaceName[0] = 0;
870 return EnumFontFamiliesExW( hDC, &lf, efproc, lpData, 0 );
873 /***********************************************************************
876 INT16 WINAPI EnumFonts16( HDC16 hDC, LPCSTR lpName, FONTENUMPROC16 efproc,
879 return EnumFontFamilies16( hDC, lpName, efproc, lpData );
882 /***********************************************************************
883 * EnumFontsA (GDI32.@)
885 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
888 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
891 /***********************************************************************
892 * EnumFontsW (GDI32.@)
894 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
897 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
901 /***********************************************************************
902 * GetTextCharacterExtra (GDI32.@)
904 INT WINAPI GetTextCharacterExtra( HDC hdc )
907 DC *dc = DC_GetDCPtr( hdc );
908 if (!dc) return 0x80000000;
910 GDI_ReleaseObj( hdc );
915 /***********************************************************************
916 * SetTextCharacterExtra (GDI32.@)
918 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
921 DC * dc = DC_GetDCPtr( hdc );
922 if (!dc) return 0x80000000;
923 if (dc->funcs->pSetTextCharacterExtra)
924 prev = dc->funcs->pSetTextCharacterExtra( dc->physDev, extra );
927 prev = dc->charExtra;
928 dc->charExtra = extra;
930 GDI_ReleaseObj( hdc );
935 /***********************************************************************
936 * SetTextJustification (GDI32.@)
938 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
941 DC * dc = DC_GetDCPtr( hdc );
942 if (!dc) return FALSE;
943 if (dc->funcs->pSetTextJustification)
944 ret = dc->funcs->pSetTextJustification( dc->physDev, extra, breaks );
947 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
948 if (!extra) breaks = 0;
951 dc->breakExtra = extra / breaks;
952 dc->breakRem = extra - (breaks * dc->breakExtra);
960 GDI_ReleaseObj( hdc );
965 /***********************************************************************
966 * GetTextFaceA (GDI32.@)
968 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
970 INT res = GetTextFaceW(hdc, 0, NULL);
971 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
972 GetTextFaceW( hdc, res, nameW );
976 if (count && !WideCharToMultiByte( CP_ACP, 0, nameW, -1, name, count, NULL, NULL))
981 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
982 HeapFree( GetProcessHeap(), 0, nameW );
986 /***********************************************************************
987 * GetTextFaceW (GDI32.@)
989 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
994 DC * dc = DC_GetDCPtr( hdc );
998 ret = WineEngGetTextFace(dc->gdiFont, count, name);
999 else if ((font = (FONTOBJ *) GDI_GetObjPtr( dc->hFont, FONT_MAGIC )))
1003 lstrcpynW( name, font->logfont.lfFaceName, count );
1004 ret = strlenW(name);
1006 else ret = strlenW(font->logfont.lfFaceName) + 1;
1007 GDI_ReleaseObj( dc->hFont );
1009 GDI_ReleaseObj( hdc );
1014 /***********************************************************************
1015 * GetTextExtentPoint32A (GDI32.@)
1017 * See GetTextExtentPoint32W.
1019 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
1024 LPWSTR p = FONT_mbtowc(str, count, &wlen);
1027 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
1028 HeapFree( GetProcessHeap(), 0, p );
1031 TRACE("(%p %s %d %p): returning %d x %d\n",
1032 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
1037 /***********************************************************************
1038 * GetTextExtentPoint32W [GDI32.@]
1040 * Computes width/height for a string.
1042 * Computes width and height of the specified string.
1048 BOOL WINAPI GetTextExtentPoint32W(
1049 HDC hdc, /* [in] Handle of device context */
1050 LPCWSTR str, /* [in] Address of text string */
1051 INT count, /* [in] Number of characters in string */
1052 LPSIZE size) /* [out] Address of structure for string size */
1054 return GetTextExtentExPointW(hdc, str, count, 0, NULL, NULL, size);
1057 /***********************************************************************
1058 * GetTextExtentPointI [GDI32.@]
1060 * Computes width and height of the array of glyph indices.
1066 BOOL WINAPI GetTextExtentPointI(
1067 HDC hdc, /* [in] Handle of device context */
1068 const WORD *indices, /* [in] Address of glyph index array */
1069 INT count, /* [in] Number of glyphs in array */
1070 LPSIZE size) /* [out] Address of structure for string size */
1073 DC * dc = DC_GetDCPtr( hdc );
1074 if (!dc) return FALSE;
1077 ret = WineEngGetTextExtentPointI(dc->gdiFont, indices, count, size);
1078 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1079 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1080 size->cx += count * dc->charExtra;
1082 else if(dc->funcs->pGetTextExtentExPoint) {
1083 FIXME("calling GetTextExtentExPoint\n");
1084 ret = dc->funcs->pGetTextExtentExPoint( dc->physDev, (LPCWSTR)indices,
1085 count, 0, NULL, NULL, size );
1088 GDI_ReleaseObj( hdc );
1090 TRACE("(%p %p %d %p): returning %d x %d\n",
1091 hdc, indices, count, size, size->cx, size->cy );
1096 /***********************************************************************
1097 * GetTextExtentPointA (GDI32.@)
1099 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
1102 TRACE("not bug compatible.\n");
1103 return GetTextExtentPoint32A( hdc, str, count, size );
1106 /***********************************************************************
1107 * GetTextExtentPointW (GDI32.@)
1109 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1112 TRACE("not bug compatible.\n");
1113 return GetTextExtentPoint32W( hdc, str, count, size );
1117 /***********************************************************************
1118 * GetTextExtentExPointA (GDI32.@)
1120 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1121 INT maxExt, LPINT lpnFit,
1122 LPINT alpDx, LPSIZE size )
1130 NULL == (walpDx = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT))))
1133 p = FONT_mbtowc(str, count, &wlen);
1134 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
1137 INT n = lpnFit ? *lpnFit : wlen;
1139 for(i = 0, j = 0; i < n; i++, j++)
1141 alpDx[j] = walpDx[i];
1142 if (IsDBCSLeadByte(str[j])) alpDx[++j] = walpDx[i];
1145 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1146 HeapFree( GetProcessHeap(), 0, p );
1147 HeapFree( GetProcessHeap(), 0, walpDx );
1152 /***********************************************************************
1153 * GetTextExtentExPointW (GDI32.@)
1155 * Return the size of the string as it would be if it was output properly by
1158 * This should include
1159 * - Intercharacter spacing
1160 * - justification spacing (not yet done)
1161 * - kerning? see below
1163 * Kerning. Since kerning would be carried out by the rendering code it should
1164 * be done by the driver. However they don't support it yet. Also I am not
1165 * yet persuaded that (certainly under Win95) any kerning is actually done.
1167 * str: According to MSDN this should be null-terminated. That is not true; a
1168 * null will not terminate it early.
1169 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1170 * than count. I have seen it be either the size of the full string or
1171 * 1 less than the size of the full string. I have not seen it bear any
1172 * resemblance to the portion that would fit.
1173 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1174 * trailing intercharacter spacing and any trailing justification.
1177 * Currently we do this by measuring each character etc. We should do it by
1178 * passing the request to the driver, perhaps by extending the
1179 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1180 * thinking about kerning issues and rounding issues in the justification.
1183 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1184 INT maxExt, LPINT lpnFit,
1185 LPINT alpDx, LPSIZE size )
1192 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1194 dc = DC_GetDCPtr(hdc);
1198 /* If we need to calculate nFit, then we need the partial extents even if
1199 the user hasn't provided us with an array. */
1202 dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]);
1205 GDI_ReleaseObj(hdc);
1206 SetLastError(ERROR_OUTOFMEMORY);
1214 ret = WineEngGetTextExtentExPoint(dc->gdiFont, str, count,
1215 0, NULL, dxs, size);
1216 else if (dc->funcs->pGetTextExtentExPoint)
1217 ret = dc->funcs->pGetTextExtentExPoint(dc->physDev, str, count,
1218 0, NULL, dxs, size);
1220 /* Perform device size to world size transformations. */
1223 INT extra = dc->charExtra, breakRem = dc->breakRem;
1228 for (i = 0; i < count; ++i)
1230 dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
1231 dxs[i] += (i+1) * extra + breakRem;
1232 if (dxs[i] <= maxExt)
1236 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1237 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1238 size->cx += count * extra + breakRem;
1245 HeapFree(GetProcessHeap(), 0, dxs);
1247 GDI_ReleaseObj( hdc );
1249 TRACE("returning %d %d x %d\n",nFit,size->cx,size->cy);
1253 /***********************************************************************
1254 * GetTextMetricsA (GDI32.@)
1256 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1260 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1261 FONT_TextMetricWToA( &tm32, metrics );
1265 /***********************************************************************
1266 * GetTextMetricsW (GDI32.@)
1268 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1271 DC * dc = DC_GetDCPtr( hdc );
1272 if (!dc) return FALSE;
1275 ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1276 else if (dc->funcs->pGetTextMetrics)
1277 ret = dc->funcs->pGetTextMetrics( dc->physDev, metrics );
1281 /* device layer returns values in device units
1282 * therefore we have to convert them to logical */
1284 #define WDPTOLP(x) ((x<0)? \
1285 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1286 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1287 #define HDPTOLP(y) ((y<0)? \
1288 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1289 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1291 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1292 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1293 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1294 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1295 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1296 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1297 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1298 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1302 TRACE("text metrics:\n"
1303 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1304 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1305 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1306 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1307 " PitchAndFamily = %02x\n"
1308 " --------------------\n"
1309 " InternalLeading = %i\n"
1313 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1314 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1315 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1316 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1317 metrics->tmPitchAndFamily,
1318 metrics->tmInternalLeading,
1321 metrics->tmHeight );
1323 GDI_ReleaseObj( hdc );
1328 /***********************************************************************
1329 * GetOutlineTextMetrics [GDI.308] Gets metrics for TrueType fonts.
1332 * lpOTM should be LPOUTLINETEXTMETRIC
1335 * Success: Non-zero or size of required buffer
1338 UINT16 WINAPI GetOutlineTextMetrics16(
1339 HDC16 hdc, /* [in] Handle of device context */
1340 UINT16 cbData, /* [in] Size of metric data array */
1341 LPOUTLINETEXTMETRIC16 lpOTM) /* [out] Address of metric data array */
1343 FIXME("(%04x,%04x,%p): stub\n", hdc,cbData,lpOTM);
1348 /***********************************************************************
1349 * GetOutlineTextMetricsA (GDI32.@)
1350 * Gets metrics for TrueType fonts.
1353 * If the supplied buffer isn't big enough Windows partially fills it up to
1354 * its given length and returns that length.
1357 * Success: Non-zero or size of required buffer
1360 UINT WINAPI GetOutlineTextMetricsA(
1361 HDC hdc, /* [in] Handle of device context */
1362 UINT cbData, /* [in] Size of metric data array */
1363 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1365 char buf[512], *ptr;
1367 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1368 OUTLINETEXTMETRICA *output = lpOTM;
1371 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1373 if(ret > sizeof(buf))
1374 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1375 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1377 needed = sizeof(OUTLINETEXTMETRICA);
1378 if(lpOTMW->otmpFamilyName)
1379 needed += WideCharToMultiByte(CP_ACP, 0,
1380 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1381 NULL, 0, NULL, NULL);
1382 if(lpOTMW->otmpFaceName)
1383 needed += WideCharToMultiByte(CP_ACP, 0,
1384 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1385 NULL, 0, NULL, NULL);
1386 if(lpOTMW->otmpStyleName)
1387 needed += WideCharToMultiByte(CP_ACP, 0,
1388 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1389 NULL, 0, NULL, NULL);
1390 if(lpOTMW->otmpFullName)
1391 needed += WideCharToMultiByte(CP_ACP, 0,
1392 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1393 NULL, 0, NULL, NULL);
1400 TRACE("needed = %d\n", needed);
1402 /* Since the supplied buffer isn't big enough, we'll alloc one
1403 that is and memcpy the first cbData bytes into the lpOTM at
1405 output = HeapAlloc(GetProcessHeap(), 0, needed);
1407 ret = output->otmSize = min(needed, cbData);
1408 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1409 output->otmFiller = 0;
1410 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1411 output->otmfsSelection = lpOTMW->otmfsSelection;
1412 output->otmfsType = lpOTMW->otmfsType;
1413 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1414 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1415 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1416 output->otmEMSquare = lpOTMW->otmEMSquare;
1417 output->otmAscent = lpOTMW->otmAscent;
1418 output->otmDescent = lpOTMW->otmDescent;
1419 output->otmLineGap = lpOTMW->otmLineGap;
1420 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1421 output->otmsXHeight = lpOTMW->otmsXHeight;
1422 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1423 output->otmMacAscent = lpOTMW->otmMacAscent;
1424 output->otmMacDescent = lpOTMW->otmMacDescent;
1425 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1426 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1427 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1428 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1429 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1430 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1431 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1432 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1433 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1434 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1437 ptr = (char*)(output + 1);
1438 left = needed - sizeof(*output);
1440 if(lpOTMW->otmpFamilyName) {
1441 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1442 len = WideCharToMultiByte(CP_ACP, 0,
1443 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1444 ptr, left, NULL, NULL);
1448 output->otmpFamilyName = 0;
1450 if(lpOTMW->otmpFaceName) {
1451 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1452 len = WideCharToMultiByte(CP_ACP, 0,
1453 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1454 ptr, left, NULL, NULL);
1458 output->otmpFaceName = 0;
1460 if(lpOTMW->otmpStyleName) {
1461 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1462 len = WideCharToMultiByte(CP_ACP, 0,
1463 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1464 ptr, left, NULL, NULL);
1468 output->otmpStyleName = 0;
1470 if(lpOTMW->otmpFullName) {
1471 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1472 len = WideCharToMultiByte(CP_ACP, 0,
1473 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1474 ptr, left, NULL, NULL);
1477 output->otmpFullName = 0;
1481 if(output != lpOTM) {
1482 memcpy(lpOTM, output, cbData);
1483 HeapFree(GetProcessHeap(), 0, output);
1485 /* check if the string offsets really fit into the provided size */
1486 /* FIXME: should we check string length as well? */
1487 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1488 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1490 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1491 lpOTM->otmpFaceName = 0; /* doesn't fit */
1493 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1494 lpOTM->otmpStyleName = 0; /* doesn't fit */
1496 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1497 lpOTM->otmpFullName = 0; /* doesn't fit */
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(str, count, &wlen);
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 )
1682 if (flags & ETO_GLYPH_INDEX)
1683 return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
1685 p = FONT_mbtowc(str, count, &wlen);
1688 unsigned int i = 0, j = 0;
1690 lpDxW = HeapAlloc( GetProcessHeap(), 0, wlen*sizeof(INT));
1692 if(IsDBCSLeadByte(str[i])) {
1693 lpDxW[j++] = lpDx[i] + lpDx[i+1];
1696 lpDxW[j++] = lpDx[i];
1702 ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1704 HeapFree( GetProcessHeap(), 0, p );
1705 HeapFree( GetProcessHeap(), 0, lpDxW );
1710 /***********************************************************************
1711 * ExtTextOutW (GDI32.@)
1713 * Draws text using the currently selected font, background color, and text color.
1717 * x,y [I] coordinates of string
1719 * ETO_GRAYED - undocumented on MSDN
1720 * ETO_OPAQUE - use background color for fill the rectangle
1721 * ETO_CLIPPED - clipping text to the rectangle
1722 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1723 * than encoded characters. Implies ETO_IGNORELANGUAGE
1724 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1725 * Affects BiDi ordering
1726 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1727 * ETO_PDY - unimplemented
1728 * ETO_NUMERICSLATIN - unimplemented always assumed -
1729 * do not translate numbers into locale representations
1730 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1731 * lprect [I] dimensions for clipping or/and opaquing
1732 * str [I] text string
1733 * count [I] number of symbols in string
1734 * lpDx [I] optional parameter with distance between drawing characters
1740 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1741 const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1744 LPWSTR reordered_str = (LPWSTR)str;
1745 WORD *glyphs = NULL;
1746 UINT align = GetTextAlign( hdc );
1750 double cosEsc, sinEsc;
1751 INT *deltas = NULL, char_extra;
1754 BOOL done_extents = FALSE;
1755 INT width, xwidth = 0, ywidth = 0;
1757 DC * dc = DC_GetDCUpdate( hdc );
1759 if (!dc) return FALSE;
1761 if (flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY))
1762 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY unimplemented\n");
1764 if (!dc->funcs->pExtTextOut && !PATH_IsPathOpen(dc->path))
1766 GDI_ReleaseObj( hdc );
1770 type = GetObjectType(hdc);
1771 if(type == OBJ_METADC || type == OBJ_ENHMETADC)
1773 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, flags, lprect, str, count, lpDx);
1774 GDI_ReleaseObj( hdc );
1779 flags &= ~ETO_CLIPPED;
1781 if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && BidiAvail && count > 0 )
1783 reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1785 BIDI_Reorder( str, count, GCP_REORDER,
1786 ((flags&ETO_RTLREADING)!=0 || (GetTextAlign(hdc)&TA_RTLREADING)!=0)?
1787 WINE_GCPW_FORCE_RTL:WINE_GCPW_FORCE_LTR,
1788 reordered_str, count, NULL );
1790 flags |= ETO_IGNORELANGUAGE;
1793 TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc, x, y, flags,
1794 lprect, debugstr_wn(str, count), count, lpDx);
1796 if(flags & ETO_GLYPH_INDEX)
1797 glyphs = reordered_str;
1800 TRACE("rect: %d,%d - %d,%d\n", lprect->left, lprect->top, lprect->right,
1802 TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
1804 if(align & TA_UPDATECP)
1806 GetCurrentPositionEx( hdc, &pt );
1811 GetTextMetricsW(hdc, &tm);
1812 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1814 if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
1815 lf.lfEscapement = 0;
1817 if(lf.lfEscapement != 0)
1819 cosEsc = cos(lf.lfEscapement * M_PI / 1800);
1820 sinEsc = sin(lf.lfEscapement * M_PI / 1800);
1828 if(flags & (ETO_CLIPPED | ETO_OPAQUE))
1832 if(flags & ETO_GLYPH_INDEX)
1833 GetTextExtentPointI(hdc, glyphs, count, &sz);
1835 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1837 done_extents = TRUE;
1840 rc.right = x + sz.cx;
1841 rc.bottom = y + sz.cy;
1848 LPtoDP(hdc, (POINT*)&rc, 2);
1850 if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
1851 if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
1854 if ((flags & ETO_OPAQUE) && !PATH_IsPathOpen(dc->path))
1855 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1865 LPtoDP(hdc, &pt, 1);
1869 char_extra = GetTextCharacterExtra(hdc);
1871 if(char_extra || dc->breakExtra || lpDx)
1875 deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT));
1876 for(i = 0; i < count; i++)
1878 if(lpDx && (flags & ETO_PDY))
1879 deltas[i] = lpDx[i*2] + char_extra;
1881 deltas[i] = lpDx[i] + char_extra;
1884 if(flags & ETO_GLYPH_INDEX)
1885 GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
1887 GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
1889 deltas[i] = tmpsz.cx;
1892 if (!(flags & ETO_GLYPH_INDEX) && dc->breakExtra && reordered_str[i] == tm.tmBreakChar)
1894 deltas[i] = deltas[i] + dc->breakExtra;
1896 deltas[i] = INTERNAL_XWSTODS(dc, deltas[i]);
1904 if(flags & ETO_GLYPH_INDEX)
1905 GetTextExtentPointI(hdc, glyphs, count, &sz);
1907 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1908 done_extents = TRUE;
1910 width = INTERNAL_XWSTODS(dc, sz.cx);
1912 xwidth = width * cosEsc;
1913 ywidth = width * sinEsc;
1915 tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
1916 tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
1917 switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
1920 if (align & TA_UPDATECP)
1924 DPtoLP(hdc, &pt, 1);
1925 MoveToEx(hdc, pt.x, pt.y, NULL);
1937 if (align & TA_UPDATECP)
1941 DPtoLP(hdc, &pt, 1);
1942 MoveToEx(hdc, pt.x, pt.y, NULL);
1947 switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
1950 y += tm.tmAscent * cosEsc;
1951 x += tm.tmAscent * sinEsc;
1955 y -= tm.tmDescent * cosEsc;
1956 x -= tm.tmDescent * sinEsc;
1963 if (GetBkMode(hdc) != TRANSPARENT && !PATH_IsPathOpen(dc->path))
1965 if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
1967 if(!(flags & ETO_OPAQUE) || x < rc.left || x + width >= rc.right ||
1968 y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
1972 rc.right = x + width;
1973 rc.top = y - tm.tmAscent;
1974 rc.bottom = y + tm.tmDescent;
1975 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1980 if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
1982 HFONT orig_font = dc->hFont, cur_font;
1984 INT span = 0, *offsets = NULL, i;
1986 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
1987 for(i = 0; i < count; i++)
1989 WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
1990 if(cur_font != dc->hFont)
1995 offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
2000 for(j = 1; j < count; j++)
2002 GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
2003 offsets[j] = offsets[j-1] + INTERNAL_XWSTODS(dc, tmpsz.cx);
2008 for(j = 1; j < count; j++)
2009 offsets[j] = offsets[j-1] + deltas[j];
2014 if (PATH_IsPathOpen(dc->path))
2015 ret = PATH_ExtTextOut(dc, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
2016 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2017 glyphs, span, deltas ? deltas + i - span : NULL);
2019 dc->funcs->pExtTextOut(dc->physDev, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
2020 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2021 glyphs, span, deltas ? deltas + i - span : NULL);
2024 SelectObject(hdc, cur_font);
2026 glyphs[span++] = glyph;
2030 if (PATH_IsPathOpen(dc->path))
2031 ret = PATH_ExtTextOut(dc, x + (offsets ? offsets[count - span] * cosEsc : 0),
2032 y - (offsets ? offsets[count - span] * sinEsc : 0),
2033 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2034 glyphs, span, deltas ? deltas + count - span : NULL);
2036 ret = dc->funcs->pExtTextOut(dc->physDev, x + (offsets ? offsets[count - span] * cosEsc : 0),
2037 y - (offsets ? offsets[count - span] * sinEsc : 0),
2038 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2039 glyphs, span, deltas ? deltas + count - span : NULL);
2040 SelectObject(hdc, orig_font);
2041 HeapFree(GetProcessHeap(), 0, offsets);
2047 if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
2049 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2050 GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
2051 flags |= ETO_GLYPH_INDEX;
2054 if (PATH_IsPathOpen(dc->path))
2055 ret = PATH_ExtTextOut(dc, x, y, (flags & ~ETO_OPAQUE), &rc,
2056 glyphs ? glyphs : reordered_str, count, deltas);
2058 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, (flags & ~ETO_OPAQUE), &rc,
2059 glyphs ? glyphs : reordered_str, count, deltas);
2063 HeapFree(GetProcessHeap(), 0, deltas);
2064 if(glyphs != reordered_str)
2065 HeapFree(GetProcessHeap(), 0, glyphs);
2066 if(reordered_str != str)
2067 HeapFree(GetProcessHeap(), 0, reordered_str);
2069 GDI_ReleaseObj( hdc );
2071 if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2073 int underlinePos, strikeoutPos;
2074 int underlineWidth, strikeoutWidth;
2075 UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2076 OUTLINETEXTMETRICW* otm = NULL;
2081 underlineWidth = tm.tmAscent / 20 + 1;
2082 strikeoutPos = tm.tmAscent / 2;
2083 strikeoutWidth = underlineWidth;
2087 otm = HeapAlloc(GetProcessHeap(), 0, size);
2088 GetOutlineTextMetricsW(hdc, size, otm);
2089 underlinePos = otm->otmsUnderscorePosition;
2090 underlineWidth = otm->otmsUnderscoreSize;
2091 strikeoutPos = otm->otmsStrikeoutPosition;
2092 strikeoutWidth = otm->otmsStrikeoutSize;
2093 HeapFree(GetProcessHeap(), 0, otm);
2096 if (PATH_IsPathOpen(dc->path))
2100 HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2102 hbrush = SelectObject(hdc, hbrush);
2103 hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2107 pts[0].x = x - underlinePos * sinEsc;
2108 pts[0].y = y - underlinePos * cosEsc;
2109 pts[1].x = x + xwidth - underlinePos * sinEsc;
2110 pts[1].y = y - ywidth - underlinePos * cosEsc;
2111 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2112 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2113 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2114 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2115 pts[4].x = pts[0].x;
2116 pts[4].y = pts[0].y;
2117 DPtoLP(hdc, pts, 5);
2118 Polygon(hdc, pts, 5);
2123 pts[0].x = x - strikeoutPos * sinEsc;
2124 pts[0].y = y - strikeoutPos * cosEsc;
2125 pts[1].x = x + xwidth - strikeoutPos * sinEsc;
2126 pts[1].y = y - ywidth - strikeoutPos * cosEsc;
2127 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2128 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2129 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2130 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2131 pts[4].x = pts[0].x;
2132 pts[4].y = pts[0].y;
2133 DPtoLP(hdc, pts, 5);
2134 Polygon(hdc, pts, 5);
2137 SelectObject(hdc, hpen);
2138 hbrush = SelectObject(hdc, hbrush);
2139 DeleteObject(hbrush);
2143 POINT pts[2], oldpt;
2148 hpen = CreatePen(PS_SOLID, underlineWidth, GetTextColor(hdc));
2149 hpen = SelectObject(hdc, hpen);
2152 pts[1].x = x + xwidth;
2153 pts[1].y = y - ywidth;
2154 DPtoLP(hdc, pts, 2);
2155 MoveToEx(hdc, pts[0].x - underlinePos * sinEsc, pts[0].y - underlinePos * cosEsc, &oldpt);
2156 LineTo(hdc, pts[1].x - underlinePos * sinEsc, pts[1].y - underlinePos * cosEsc);
2157 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2158 DeleteObject(SelectObject(hdc, hpen));
2163 hpen = CreatePen(PS_SOLID, strikeoutWidth, GetTextColor(hdc));
2164 hpen = SelectObject(hdc, hpen);
2167 pts[1].x = x + xwidth;
2168 pts[1].y = y - ywidth;
2169 DPtoLP(hdc, pts, 2);
2170 MoveToEx(hdc, pts[0].x - strikeoutPos * sinEsc, pts[0].y - strikeoutPos * cosEsc, &oldpt);
2171 LineTo(hdc, pts[1].x - strikeoutPos * sinEsc, pts[1].y - strikeoutPos * cosEsc);
2172 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2173 DeleteObject(SelectObject(hdc, hpen));
2182 /***********************************************************************
2183 * TextOutA (GDI32.@)
2185 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2187 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2191 /***********************************************************************
2192 * TextOutW (GDI32.@)
2194 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2196 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2200 /***********************************************************************
2201 * PolyTextOutA (GDI32.@)
2205 BOOL WINAPI PolyTextOutA ( HDC hdc, /* [in] Handle to device context */
2206 PPOLYTEXTA pptxt, /* [in] Array of strings */
2207 INT cStrings ) /* [in] Number of strings in array */
2209 for (; cStrings>0; cStrings--, pptxt++)
2210 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2217 /***********************************************************************
2218 * PolyTextOutW (GDI32.@)
2220 * Draw several Strings
2226 BOOL WINAPI PolyTextOutW ( HDC hdc, /* [in] Handle to device context */
2227 PPOLYTEXTW pptxt, /* [in] Array of strings */
2228 INT cStrings ) /* [in] Number of strings in array */
2230 for (; cStrings>0; cStrings--, pptxt++)
2231 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2237 /* FIXME: all following APIs ******************************************/
2240 /***********************************************************************
2241 * SetMapperFlags (GDI32.@)
2243 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
2245 DC *dc = DC_GetDCPtr( hDC );
2248 if(dc->funcs->pSetMapperFlags)
2250 ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
2251 /* FIXME: ret is just a success flag, we should return a proper value */
2254 FIXME("(%p, 0x%08x): stub - harmless\n", hDC, dwFlag);
2255 GDI_ReleaseObj( hDC );
2259 /***********************************************************************
2260 * GetAspectRatioFilterEx (GDI.486)
2262 BOOL16 WINAPI GetAspectRatioFilterEx16( HDC16 hdc, LPSIZE16 pAspectRatio )
2264 FIXME("(%04x, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2268 /***********************************************************************
2269 * GetAspectRatioFilterEx (GDI32.@)
2271 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2273 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2278 /***********************************************************************
2279 * GetCharABCWidthsA (GDI32.@)
2281 * See GetCharABCWidthsW.
2283 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2286 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
2291 if(count <= 0) return FALSE;
2293 str = HeapAlloc(GetProcessHeap(), 0, count);
2294 for(i = 0; i < count; i++)
2295 str[i] = (BYTE)(firstChar + i);
2297 wstr = FONT_mbtowc(str, count, &wlen);
2299 for(i = 0; i < wlen; i++)
2301 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2309 HeapFree(GetProcessHeap(), 0, str);
2310 HeapFree(GetProcessHeap(), 0, wstr);
2316 /******************************************************************************
2317 * GetCharABCWidthsW [GDI32.@]
2319 * Retrieves widths of characters in range.
2322 * hdc [I] Handle of device context
2323 * firstChar [I] First character in range to query
2324 * lastChar [I] Last character in range to query
2325 * abc [O] Address of character-width structure
2328 * Only works with TrueType fonts
2334 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2337 DC *dc = DC_GetDCPtr(hdc);
2341 if (!dc) return FALSE;
2344 ret = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
2350 /* convert device units to logical */
2351 for( i = firstChar; i <= lastChar; i++, abc++ ) {
2352 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2353 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2354 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2359 GDI_ReleaseObj(hdc);
2364 /******************************************************************************
2365 * GetCharABCWidthsI [GDI32.@]
2367 * Retrieves widths of characters in range.
2370 * hdc [I] Handle of device context
2371 * firstChar [I] First glyphs in range to query
2372 * count [I] Last glyphs in range to query
2373 * pgi [i] Array of glyphs to query
2374 * abc [O] Address of character-width structure
2377 * Only works with TrueType fonts
2383 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2384 LPWORD pgi, LPABC abc)
2386 DC *dc = DC_GetDCPtr(hdc);
2390 if (!dc) return FALSE;
2393 ret = WineEngGetCharABCWidthsI( dc->gdiFont, firstChar, count, pgi, abc );
2399 /* convert device units to logical */
2400 for( i = 0; i < count; i++, abc++ ) {
2401 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2402 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2403 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2408 GDI_ReleaseObj(hdc);
2413 /***********************************************************************
2414 * GetGlyphOutlineA (GDI32.@)
2416 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2417 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2418 LPVOID lpBuffer, const MAT2 *lpmat2 )
2424 if(!(fuFormat & GGO_GLYPH_INDEX)) {
2427 if(uChar > 0xff) { /* but, 2 bytes character only */
2429 mbchs[0] = (uChar & 0xff00) >> 8;
2430 mbchs[1] = (uChar & 0xff);
2433 mbchs[0] = (uChar & 0xff);
2435 p = FONT_mbtowc(mbchs, len, NULL);
2439 ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
2441 HeapFree(GetProcessHeap(), 0, p);
2445 /***********************************************************************
2446 * GetGlyphOutlineW (GDI32.@)
2448 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2449 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2450 LPVOID lpBuffer, const MAT2 *lpmat2 )
2452 DC *dc = DC_GetDCPtr(hdc);
2455 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2456 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2458 if(!dc) return GDI_ERROR;
2461 ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
2462 cbBuffer, lpBuffer, lpmat2);
2466 GDI_ReleaseObj(hdc);
2471 /***********************************************************************
2472 * CreateScalableFontResourceA (GDI32.@)
2474 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2475 LPCSTR lpszResourceFile,
2476 LPCSTR lpszFontFile,
2477 LPCSTR lpszCurrentPath )
2481 /* fHidden=1 - only visible for the calling app, read-only, not
2482 * enumbered with EnumFonts/EnumFontFamilies
2483 * lpszCurrentPath can be NULL
2485 FIXME("(%d,%s,%s,%s): stub\n",
2486 fHidden, debugstr_a(lpszResourceFile), debugstr_a(lpszFontFile),
2487 debugstr_a(lpszCurrentPath) );
2489 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2490 if ((f = CreateFileA(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2492 SetLastError(ERROR_FILE_EXISTS);
2495 return FALSE; /* create failed */
2498 /***********************************************************************
2499 * CreateScalableFontResourceW (GDI32.@)
2501 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2502 LPCWSTR lpszResourceFile,
2503 LPCWSTR lpszFontFile,
2504 LPCWSTR lpszCurrentPath )
2506 FIXME("(%d,%p,%p,%p): stub\n",
2507 fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
2508 return FALSE; /* create failed */
2511 /*************************************************************************
2512 * GetKerningPairsA (GDI32.@)
2514 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2515 LPKERNINGPAIR kern_pairA )
2520 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2521 KERNINGPAIR *kern_pairW;
2523 if (!cPairs && kern_pairA)
2525 SetLastError(ERROR_INVALID_PARAMETER);
2529 charset = GetTextCharset(hDC);
2530 if (!TranslateCharsetInfo((DWORD *)charset, &csi, TCI_SRCCHARSET))
2532 FIXME("Can't find codepage for charset %d\n", charset);
2535 if (!GetCPInfo(csi.ciACP, &cpi))
2537 FIXME("Can't find codepage %u info\n", csi.ciACP);
2540 TRACE("charset %d => codepage %u\n", charset, csi.ciACP);
2542 total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2543 if (!total_kern_pairs) return 0;
2545 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2546 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2548 for (i = 0; i < total_kern_pairs; i++)
2552 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2555 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2558 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2563 if (kern_pairs_copied >= cPairs) break;
2565 kern_pairA->wFirst = (BYTE)first;
2566 kern_pairA->wSecond = (BYTE)second;
2567 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2570 kern_pairs_copied++;
2573 HeapFree(GetProcessHeap(), 0, kern_pairW);
2575 return kern_pairs_copied;
2578 /*************************************************************************
2579 * GetKerningPairsW (GDI32.@)
2581 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2582 LPKERNINGPAIR lpKerningPairs )
2587 TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2589 if (!cPairs && lpKerningPairs)
2591 SetLastError(ERROR_INVALID_PARAMETER);
2595 dc = DC_GetDCPtr(hDC);
2599 ret = WineEngGetKerningPairs(dc->gdiFont, cPairs, lpKerningPairs);
2601 GDI_ReleaseObj(hDC);
2605 /*************************************************************************
2606 * TranslateCharsetInfo [GDI32.@]
2608 * Fills a CHARSETINFO structure for a character set, code page, or
2609 * font. This allows making the correspondance between different labelings
2610 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2611 * of the same encoding.
2613 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2614 * only one codepage should be set in *lpSrc.
2617 * TRUE on success, FALSE on failure.
2620 BOOL WINAPI TranslateCharsetInfo(
2621 LPDWORD lpSrc, /* [in]
2622 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2623 if flags == TCI_SRCCHARSET: a character set value
2624 if flags == TCI_SRCCODEPAGE: a code page value
2626 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2627 DWORD flags /* [in] determines interpretation of lpSrc */)
2631 case TCI_SRCFONTSIG:
2632 while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
2634 case TCI_SRCCODEPAGE:
2635 while ((UINT) (lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
2637 case TCI_SRCCHARSET:
2638 while ((UINT) (lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
2643 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2644 memcpy(lpCs, &FONT_tci[index], sizeof(CHARSETINFO));
2648 /*************************************************************************
2649 * GetFontLanguageInfo (GDI32.@)
2651 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2653 FONTSIGNATURE fontsig;
2654 static const DWORD GCP_DBCS_MASK=0x003F0000,
2655 GCP_DIACRITIC_MASK=0x00000000,
2656 FLI_GLYPHS_MASK=0x00000000,
2657 GCP_GLYPHSHAPE_MASK=0x00000040,
2658 GCP_KASHIDA_MASK=0x00000000,
2659 GCP_LIGATE_MASK=0x00000000,
2660 GCP_USEKERNING_MASK=0x00000000,
2661 GCP_REORDER_MASK=0x00000060;
2665 GetTextCharsetInfo( hdc, &fontsig, 0 );
2666 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2668 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2671 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2672 result|=GCP_DIACRITIC;
2674 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2677 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2678 result|=GCP_GLYPHSHAPE;
2680 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2681 result|=GCP_KASHIDA;
2683 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2686 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2687 result|=GCP_USEKERNING;
2689 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2690 if( GetTextAlign( hdc) & TA_RTLREADING )
2691 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2692 result|=GCP_REORDER;
2698 /*************************************************************************
2699 * GetFontData [GDI32.@]
2701 * Retrieve data for TrueType font.
2705 * success: Number of bytes returned
2706 * failure: GDI_ERROR
2710 * Calls SetLastError()
2713 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2714 LPVOID buffer, DWORD length)
2716 DC *dc = DC_GetDCPtr(hdc);
2717 DWORD ret = GDI_ERROR;
2719 if(!dc) return GDI_ERROR;
2722 ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2724 GDI_ReleaseObj(hdc);
2728 /*************************************************************************
2729 * GetGlyphIndicesA [GDI32.@]
2731 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2732 LPWORD pgi, DWORD flags)
2738 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2739 hdc, debugstr_an(lpstr, count), count, pgi, flags);
2741 lpstrW = FONT_mbtowc(lpstr, count, &countW);
2742 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2743 HeapFree(GetProcessHeap(), 0, lpstrW);
2748 /*************************************************************************
2749 * GetGlyphIndicesW [GDI32.@]
2751 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2752 LPWORD pgi, DWORD flags)
2754 DC *dc = DC_GetDCPtr(hdc);
2755 DWORD ret = GDI_ERROR;
2757 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2758 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2760 if(!dc) return GDI_ERROR;
2763 ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2765 GDI_ReleaseObj(hdc);
2769 /*************************************************************************
2770 * GetCharacterPlacementA [GDI32.@]
2772 * See GetCharacterPlacementW.
2775 * the web browser control of ie4 calls this with dwFlags=0
2778 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2779 INT nMaxExtent, GCP_RESULTSA *lpResults,
2784 GCP_RESULTSW resultsW;
2787 TRACE("%s, %d, %d, 0x%08x\n",
2788 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2790 /* both structs are equal in size */
2791 memcpy(&resultsW, lpResults, sizeof(resultsW));
2793 lpStringW = FONT_mbtowc(lpString, uCount, &uCountW);
2794 if(lpResults->lpOutString)
2795 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2797 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2799 lpResults->nGlyphs = resultsW.nGlyphs;
2800 lpResults->nMaxFit = resultsW.nMaxFit;
2802 if(lpResults->lpOutString) {
2803 WideCharToMultiByte(CP_ACP, 0, resultsW.lpOutString, uCountW,
2804 lpResults->lpOutString, uCount, NULL, NULL );
2807 HeapFree(GetProcessHeap(), 0, lpStringW);
2808 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2813 /*************************************************************************
2814 * GetCharacterPlacementW [GDI32.@]
2816 * Retrieve information about a string. This includes the width, reordering,
2817 * Glyphing and so on.
2821 * The width and height of the string if successful, 0 if failed.
2825 * All flags except GCP_REORDER are not yet implemented.
2826 * Reordering is not 100% complient to the Windows BiDi method.
2827 * Caret positioning is not yet implemented for BiDi.
2828 * Classes are not yet implemented.
2832 GetCharacterPlacementW(
2833 HDC hdc, /* [in] Device context for which the rendering is to be done */
2834 LPCWSTR lpString, /* [in] The string for which information is to be returned */
2835 INT uCount, /* [in] Number of WORDS in string. */
2836 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
2837 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2838 DWORD dwFlags /* [in] Flags specifying how to process the string */
2845 TRACE("%s, %d, %d, 0x%08x\n",
2846 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2848 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2849 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2850 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2851 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2852 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2854 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08x ignored\n", dwFlags);
2855 if(lpResults->lpClass) FIXME("classes not implemented\n");
2856 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2857 FIXME("Caret positions for complex scripts not implemented\n");
2859 nSet = (UINT)uCount;
2860 if(nSet > lpResults->nGlyphs)
2861 nSet = lpResults->nGlyphs;
2863 /* return number of initialized fields */
2864 lpResults->nGlyphs = nSet;
2866 if((dwFlags&GCP_REORDER)==0 || !BidiAvail)
2868 /* Treat the case where no special handling was requested in a fastpath way */
2869 /* copy will do if the GCP_REORDER flag is not set */
2870 if(lpResults->lpOutString)
2871 memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
2873 if(lpResults->lpOrder)
2875 for(i = 0; i < nSet; i++)
2876 lpResults->lpOrder[i] = i;
2880 BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
2881 nSet, lpResults->lpOrder );
2884 /* FIXME: Will use the placement chars */
2885 if (lpResults->lpDx)
2888 for (i = 0; i < nSet; i++)
2890 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
2891 lpResults->lpDx[i]= c;
2895 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
2899 lpResults->lpCaretPos[0] = 0;
2900 for (i = 1; i < nSet; i++)
2901 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
2902 lpResults->lpCaretPos[i] = (pos += size.cx);
2905 if(lpResults->lpGlyphs)
2906 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
2908 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
2909 ret = MAKELONG(size.cx, size.cy);
2914 /*************************************************************************
2915 * GetCharABCWidthsFloatA [GDI32.@]
2917 * See GetCharABCWidthsFloatW.
2919 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
2921 INT i, wlen, count = (INT)(last - first + 1);
2926 if (count <= 0) return FALSE;
2928 str = HeapAlloc(GetProcessHeap(), 0, count);
2930 for(i = 0; i < count; i++)
2931 str[i] = (BYTE)(first + i);
2933 wstr = FONT_mbtowc(str, count, &wlen);
2935 for (i = 0; i < wlen; i++)
2937 if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
2945 HeapFree( GetProcessHeap(), 0, str );
2946 HeapFree( GetProcessHeap(), 0, wstr );
2951 /*************************************************************************
2952 * GetCharABCWidthsFloatW [GDI32.@]
2954 * Retrieves widths of a range of characters.
2957 * hdc [I] Handle to device context.
2958 * first [I] First character in range to query.
2959 * last [I] Last character in range to query.
2960 * abcf [O] Array of LPABCFLOAT structures.
2967 * Only works with TrueType fonts. It also doesn't return real
2968 * floats but converted integers because it's implemented on
2969 * top of GetCharABCWidthsW.
2971 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
2974 unsigned int i, size = sizeof(ABC) * (last - first + 1);
2977 TRACE("%p, %d, %d, %p - partial stub\n", hdc, first, last, abcf);
2979 abc = HeapAlloc( GetProcessHeap(), 0, size );
2980 if (!abc) return FALSE;
2982 ret = GetCharABCWidthsW( hdc, first, last, abc );
2985 for (i = first; i <= last; i++, abc++, abcf++)
2987 abcf->abcfA = abc->abcA;
2988 abcf->abcfB = abc->abcB;
2989 abcf->abcfC = abc->abcC;
2992 HeapFree( GetProcessHeap(), 0, abc );
2996 /*************************************************************************
2997 * GetCharWidthFloatA [GDI32.@]
2999 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
3000 UINT iLastChar, PFLOAT pxBuffer)
3002 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3006 /*************************************************************************
3007 * GetCharWidthFloatW [GDI32.@]
3009 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
3010 UINT iLastChar, PFLOAT pxBuffer)
3012 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3017 /***********************************************************************
3019 * Font Resource API *
3021 ***********************************************************************/
3023 /***********************************************************************
3024 * AddFontResourceA (GDI32.@)
3026 INT WINAPI AddFontResourceA( LPCSTR str )
3028 return AddFontResourceExA( str, 0, NULL);
3031 /***********************************************************************
3032 * AddFontResourceW (GDI32.@)
3034 INT WINAPI AddFontResourceW( LPCWSTR str )
3036 return AddFontResourceExW(str, 0, NULL);
3040 /***********************************************************************
3041 * AddFontResourceExA (GDI32.@)
3043 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3045 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3046 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3049 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3050 ret = AddFontResourceExW(strW, fl, pdv);
3051 HeapFree(GetProcessHeap(), 0, strW);
3055 /***********************************************************************
3056 * AddFontResourceExW (GDI32.@)
3058 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3060 return WineEngAddFontResourceEx(str, fl, pdv);
3063 /***********************************************************************
3064 * RemoveFontResourceA (GDI32.@)
3066 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3068 return RemoveFontResourceExA(str, 0, 0);
3071 /***********************************************************************
3072 * RemoveFontResourceW (GDI32.@)
3074 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3076 return RemoveFontResourceExW(str, 0, 0);
3079 /***********************************************************************
3080 * AddFontMemResourceEx (GDI32.@)
3082 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3084 FIXME("(%p,%08x,%p,%p): stub\n", pbFont, cbFont, pdv, pcFonts);
3088 /***********************************************************************
3089 * RemoveFontResourceExA (GDI32.@)
3091 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3093 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3094 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3097 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3098 ret = RemoveFontResourceExW(strW, fl, pdv);
3099 HeapFree(GetProcessHeap(), 0, strW);
3103 /***********************************************************************
3104 * RemoveFontResourceExW (GDI32.@)
3106 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3108 return WineEngRemoveFontResourceEx(str, fl, pdv);
3111 /***********************************************************************
3112 * GetTextCharset (GDI32.@)
3114 UINT WINAPI GetTextCharset(HDC hdc)
3116 /* MSDN docs say this is equivalent */
3117 return GetTextCharsetInfo(hdc, NULL, 0);
3120 /***********************************************************************
3121 * GetTextCharsetInfo (GDI32.@)
3123 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3125 UINT ret = DEFAULT_CHARSET;
3126 DC *dc = DC_GetDCPtr(hdc);
3131 ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
3133 GDI_ReleaseObj(hdc);
3136 if (ret == DEFAULT_CHARSET && fs)
3137 memset(fs, 0, sizeof(FONTSIGNATURE));
3141 /***********************************************************************
3142 * GdiGetCharDimensions (GDI32.@)
3144 * Gets the average width of the characters in the English alphabet.
3147 * hdc [I] Handle to the device context to measure on.
3148 * lptm [O] Pointer to memory to store the text metrics into.
3149 * height [O] On exit, the maximum height of characters in the English alphabet.
3152 * The average width of characters in the English alphabet.
3155 * This function is used by the dialog manager to get the size of a dialog
3156 * unit. It should also be used by other pieces of code that need to know
3157 * the size of a dialog unit in logical units without having access to the
3158 * window handle of the dialog.
3159 * Windows caches the font metrics from this function, but we don't and
3160 * there doesn't appear to be an immediate advantage to do so.
3163 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3165 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3168 static const WCHAR alphabet[] = {
3169 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3170 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3171 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3173 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3175 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3177 if (height) *height = sz.cy;
3178 return (sz.cx / 26 + 1) / 2;
3181 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3183 FIXME("(%d): stub\n", fEnableEUDC);
3187 /***********************************************************************
3188 * GetCharWidthI (GDI32.@)
3190 * Retrieve widths of characters.
3193 * hdc [I] Handle to a device context.
3194 * first [I] First glyph in range to query.
3195 * count [I] Number of glyph indices to query.
3196 * glyphs [I] Array of glyphs to query.
3197 * buffer [O] Buffer to receive character widths.
3200 * Only works with TrueType fonts.
3206 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3211 TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3213 if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3216 if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3218 HeapFree(GetProcessHeap(), 0, abc);
3222 for (i = 0; i < count; i++)
3223 buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3225 HeapFree(GetProcessHeap(), 0, abc);
3229 /***********************************************************************
3230 * GetFontUnicodeRanges (GDI32.@)
3232 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3234 FIXME("(%p, %p): stub\n", hdc, lpgs);