4 * Copyright 1993 Alexandre Julliard
6 * Copyright 2002,2003 Shachar Shemesh
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include "wine/port.h"
36 #include "gdi_private.h"
37 #include "wine/unicode.h"
38 #include "wine/debug.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(font);
41 WINE_DECLARE_DEBUG_CHANNEL(gdi);
43 /* Device -> World size conversion */
45 /* Performs a device to world transformation on the specified width (which
46 * is in integer format).
48 static inline INT INTERNAL_XDSTOWS(DC *dc, INT width)
52 /* Perform operation with floating point */
53 floatWidth = (FLOAT)width * dc->xformVport2World.eM11;
54 /* Round to integers */
55 return GDI_ROUND(floatWidth);
58 /* Performs a device to world transformation on the specified size (which
59 * is in integer format).
61 static inline INT INTERNAL_YDSTOWS(DC *dc, INT height)
65 /* Perform operation with floating point */
66 floatHeight = (FLOAT)height * dc->xformVport2World.eM22;
67 /* Round to integers */
68 return GDI_ROUND(floatHeight);
71 static inline INT INTERNAL_XWSTODS(DC *dc, INT width)
74 pt[0].x = pt[0].y = 0;
77 LPtoDP(dc->hSelf, pt, 2);
78 return pt[1].x - pt[0].x;
81 static inline INT INTERNAL_YWSTODS(DC *dc, INT height)
84 pt[0].x = pt[0].y = 0;
87 LPtoDP(dc->hSelf, pt, 2);
88 return pt[1].y - pt[0].y;
91 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, void *obj, HDC hdc );
92 static INT FONT_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
93 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
94 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
95 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj );
97 static const struct gdi_obj_funcs font_funcs =
99 FONT_SelectObject, /* pSelectObject */
100 FONT_GetObject16, /* pGetObject16 */
101 FONT_GetObjectA, /* pGetObjectA */
102 FONT_GetObjectW, /* pGetObjectW */
103 NULL, /* pUnrealizeObject */
104 FONT_DeleteObject /* pDeleteObject */
107 #define ENUM_UNICODE 0x00000001
108 #define ENUM_CALLED 0x00000002
118 LPLOGFONT16 lpLogFontParam;
119 FONTENUMPROC16 lpEnumFunc;
122 LPNEWTEXTMETRICEX16 lpTextMetric;
123 LPENUMLOGFONTEX16 lpLogFont;
124 SEGPTR segTextMetric;
134 LPLOGFONTW lpLogFontParam;
135 FONTENUMPROCW lpEnumFunc;
144 * For TranslateCharsetInfo
146 #define FS(x) {{0,0,0,0},{0x1<<(x),0}}
147 #define MAXTCIINDEX 32
148 static const CHARSETINFO FONT_tci[MAXTCIINDEX] = {
150 { ANSI_CHARSET, 1252, FS(0)},
151 { EASTEUROPE_CHARSET, 1250, FS(1)},
152 { RUSSIAN_CHARSET, 1251, FS(2)},
153 { GREEK_CHARSET, 1253, FS(3)},
154 { TURKISH_CHARSET, 1254, FS(4)},
155 { HEBREW_CHARSET, 1255, FS(5)},
156 { ARABIC_CHARSET, 1256, FS(6)},
157 { BALTIC_CHARSET, 1257, FS(7)},
158 { VIETNAMESE_CHARSET, 1258, FS(8)},
159 /* reserved by ANSI */
160 { DEFAULT_CHARSET, 0, FS(0)},
161 { DEFAULT_CHARSET, 0, FS(0)},
162 { DEFAULT_CHARSET, 0, FS(0)},
163 { DEFAULT_CHARSET, 0, FS(0)},
164 { DEFAULT_CHARSET, 0, FS(0)},
165 { DEFAULT_CHARSET, 0, FS(0)},
166 { DEFAULT_CHARSET, 0, FS(0)},
168 { THAI_CHARSET, 874, FS(16)},
169 { SHIFTJIS_CHARSET, 932, FS(17)},
170 { GB2312_CHARSET, 936, FS(18)},
171 { HANGEUL_CHARSET, 949, FS(19)},
172 { CHINESEBIG5_CHARSET, 950, FS(20)},
173 { JOHAB_CHARSET, 1361, FS(21)},
174 /* reserved for alternate ANSI and OEM */
175 { DEFAULT_CHARSET, 0, FS(0)},
176 { DEFAULT_CHARSET, 0, FS(0)},
177 { DEFAULT_CHARSET, 0, FS(0)},
178 { DEFAULT_CHARSET, 0, FS(0)},
179 { DEFAULT_CHARSET, 0, FS(0)},
180 { DEFAULT_CHARSET, 0, FS(0)},
181 { DEFAULT_CHARSET, 0, FS(0)},
182 { DEFAULT_CHARSET, 0, FS(0)},
183 /* reserved for system */
184 { DEFAULT_CHARSET, 0, FS(0)},
185 { SYMBOL_CHARSET, CP_SYMBOL, FS(31)},
188 /***********************************************************************
189 * LOGFONT conversion functions.
191 static void FONT_LogFontWTo16( const LOGFONTW* font32, LPLOGFONT16 font16 )
193 font16->lfHeight = font32->lfHeight;
194 font16->lfWidth = font32->lfWidth;
195 font16->lfEscapement = font32->lfEscapement;
196 font16->lfOrientation = font32->lfOrientation;
197 font16->lfWeight = font32->lfWeight;
198 font16->lfItalic = font32->lfItalic;
199 font16->lfUnderline = font32->lfUnderline;
200 font16->lfStrikeOut = font32->lfStrikeOut;
201 font16->lfCharSet = font32->lfCharSet;
202 font16->lfOutPrecision = font32->lfOutPrecision;
203 font16->lfClipPrecision = font32->lfClipPrecision;
204 font16->lfQuality = font32->lfQuality;
205 font16->lfPitchAndFamily = font32->lfPitchAndFamily;
206 WideCharToMultiByte( CP_ACP, 0, font32->lfFaceName, -1,
207 font16->lfFaceName, LF_FACESIZE, NULL, NULL );
208 font16->lfFaceName[LF_FACESIZE-1] = 0;
211 static void FONT_LogFont16ToW( const LOGFONT16 *font16, LPLOGFONTW font32 )
213 font32->lfHeight = font16->lfHeight;
214 font32->lfWidth = font16->lfWidth;
215 font32->lfEscapement = font16->lfEscapement;
216 font32->lfOrientation = font16->lfOrientation;
217 font32->lfWeight = font16->lfWeight;
218 font32->lfItalic = font16->lfItalic;
219 font32->lfUnderline = font16->lfUnderline;
220 font32->lfStrikeOut = font16->lfStrikeOut;
221 font32->lfCharSet = font16->lfCharSet;
222 font32->lfOutPrecision = font16->lfOutPrecision;
223 font32->lfClipPrecision = font16->lfClipPrecision;
224 font32->lfQuality = font16->lfQuality;
225 font32->lfPitchAndFamily = font16->lfPitchAndFamily;
226 MultiByteToWideChar( CP_ACP, 0, font16->lfFaceName, -1, font32->lfFaceName, LF_FACESIZE );
227 font32->lfFaceName[LF_FACESIZE-1] = 0;
230 static void FONT_LogFontAToW( const LOGFONTA *fontA, LPLOGFONTW fontW )
232 memcpy(fontW, fontA, sizeof(LOGFONTA) - LF_FACESIZE);
233 MultiByteToWideChar(CP_ACP, 0, fontA->lfFaceName, -1, fontW->lfFaceName,
235 fontW->lfFaceName[LF_FACESIZE-1] = 0;
238 static void FONT_LogFontWToA( const LOGFONTW *fontW, LPLOGFONTA fontA )
240 memcpy(fontA, fontW, sizeof(LOGFONTA) - LF_FACESIZE);
241 WideCharToMultiByte(CP_ACP, 0, fontW->lfFaceName, -1, fontA->lfFaceName,
242 LF_FACESIZE, NULL, NULL);
243 fontA->lfFaceName[LF_FACESIZE-1] = 0;
246 static void FONT_EnumLogFontExWTo16( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEX16 font16 )
248 FONT_LogFontWTo16( (LPLOGFONTW)fontW, (LPLOGFONT16)font16);
250 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
251 (LPSTR) font16->elfFullName, LF_FULLFACESIZE, NULL, NULL );
252 font16->elfFullName[LF_FULLFACESIZE-1] = '\0';
253 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
254 (LPSTR) font16->elfStyle, LF_FACESIZE, NULL, NULL );
255 font16->elfStyle[LF_FACESIZE-1] = '\0';
256 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
257 (LPSTR) font16->elfScript, LF_FACESIZE, NULL, NULL );
258 font16->elfScript[LF_FACESIZE-1] = '\0';
261 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEXA fontA )
263 FONT_LogFontWToA( (LPLOGFONTW)fontW, (LPLOGFONTA)fontA);
265 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
266 (LPSTR) fontA->elfFullName, LF_FULLFACESIZE, NULL, NULL );
267 fontA->elfFullName[LF_FULLFACESIZE-1] = '\0';
268 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
269 (LPSTR) fontA->elfStyle, LF_FACESIZE, NULL, NULL );
270 fontA->elfStyle[LF_FACESIZE-1] = '\0';
271 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
272 (LPSTR) fontA->elfScript, LF_FACESIZE, NULL, NULL );
273 fontA->elfScript[LF_FACESIZE-1] = '\0';
276 /***********************************************************************
277 * TEXTMETRIC conversion functions.
279 static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
281 ptmA->tmHeight = ptmW->tmHeight;
282 ptmA->tmAscent = ptmW->tmAscent;
283 ptmA->tmDescent = ptmW->tmDescent;
284 ptmA->tmInternalLeading = ptmW->tmInternalLeading;
285 ptmA->tmExternalLeading = ptmW->tmExternalLeading;
286 ptmA->tmAveCharWidth = ptmW->tmAveCharWidth;
287 ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth;
288 ptmA->tmWeight = ptmW->tmWeight;
289 ptmA->tmOverhang = ptmW->tmOverhang;
290 ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX;
291 ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
292 ptmA->tmFirstChar = ptmW->tmFirstChar > 255 ? 255 : ptmW->tmFirstChar;
293 ptmA->tmLastChar = ptmW->tmLastChar > 255 ? 255 : ptmW->tmLastChar;
294 ptmA->tmDefaultChar = ptmW->tmDefaultChar > 255 ? 255 : ptmW->tmDefaultChar;
295 ptmA->tmBreakChar = ptmW->tmBreakChar > 255 ? 255 : ptmW->tmBreakChar;
296 ptmA->tmItalic = ptmW->tmItalic;
297 ptmA->tmUnderlined = ptmW->tmUnderlined;
298 ptmA->tmStruckOut = ptmW->tmStruckOut;
299 ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
300 ptmA->tmCharSet = ptmW->tmCharSet;
304 static void FONT_NewTextMetricExWTo16(const NEWTEXTMETRICEXW *ptmW, LPNEWTEXTMETRICEX16 ptm16 )
306 ptm16->ntmTm.tmHeight = ptmW->ntmTm.tmHeight;
307 ptm16->ntmTm.tmAscent = ptmW->ntmTm.tmAscent;
308 ptm16->ntmTm.tmDescent = ptmW->ntmTm.tmDescent;
309 ptm16->ntmTm.tmInternalLeading = ptmW->ntmTm.tmInternalLeading;
310 ptm16->ntmTm.tmExternalLeading = ptmW->ntmTm.tmExternalLeading;
311 ptm16->ntmTm.tmAveCharWidth = ptmW->ntmTm.tmAveCharWidth;
312 ptm16->ntmTm.tmMaxCharWidth = ptmW->ntmTm.tmMaxCharWidth;
313 ptm16->ntmTm.tmWeight = ptmW->ntmTm.tmWeight;
314 ptm16->ntmTm.tmOverhang = ptmW->ntmTm.tmOverhang;
315 ptm16->ntmTm.tmDigitizedAspectX = ptmW->ntmTm.tmDigitizedAspectX;
316 ptm16->ntmTm.tmDigitizedAspectY = ptmW->ntmTm.tmDigitizedAspectY;
317 ptm16->ntmTm.tmFirstChar = ptmW->ntmTm.tmFirstChar > 255 ? 255 : ptmW->ntmTm.tmFirstChar;
318 ptm16->ntmTm.tmLastChar = ptmW->ntmTm.tmLastChar > 255 ? 255 : ptmW->ntmTm.tmLastChar;
319 ptm16->ntmTm.tmDefaultChar = ptmW->ntmTm.tmDefaultChar > 255 ? 255 : ptmW->ntmTm.tmDefaultChar;
320 ptm16->ntmTm.tmBreakChar = ptmW->ntmTm.tmBreakChar > 255 ? 255 : ptmW->ntmTm.tmBreakChar;
321 ptm16->ntmTm.tmItalic = ptmW->ntmTm.tmItalic;
322 ptm16->ntmTm.tmUnderlined = ptmW->ntmTm.tmUnderlined;
323 ptm16->ntmTm.tmStruckOut = ptmW->ntmTm.tmStruckOut;
324 ptm16->ntmTm.tmPitchAndFamily = ptmW->ntmTm.tmPitchAndFamily;
325 ptm16->ntmTm.tmCharSet = ptmW->ntmTm.tmCharSet;
326 ptm16->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
327 ptm16->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
328 ptm16->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
329 ptm16->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
330 memcpy(&ptm16->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
333 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW *ptmW, NEWTEXTMETRICEXA *ptmA )
335 FONT_TextMetricWToA((LPTEXTMETRICW)ptmW, (LPTEXTMETRICA)ptmA);
336 ptmA->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
337 ptmA->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
338 ptmA->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
339 ptmA->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
340 memcpy(&ptmA->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
344 /***********************************************************************
347 * Returns a Unicode translation of str. If count is -1 then str is
348 * assumed to be '\0' terminated, otherwise it contains the number of
349 * bytes to convert. If plenW is non-NULL, on return it will point to
350 * the number of WCHARs that have been written. The caller should free
351 * the returned LPWSTR from the process heap itself.
353 static LPWSTR FONT_mbtowc(LPCSTR str, INT count, INT *plenW)
359 if(count == -1) count = strlen(str);
360 lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
361 strW = HeapAlloc(GetProcessHeap(), 0, lenW*sizeof(WCHAR));
362 MultiByteToWideChar(cp, 0, str, count, strW, lenW);
363 TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW));
364 if(plenW) *plenW = lenW;
369 /***********************************************************************
370 * CreateFontIndirectA (GDI32.@)
372 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *plfA )
377 FONT_LogFontAToW( plfA, &lfW );
378 return CreateFontIndirectW( &lfW );
380 return CreateFontIndirectW( NULL );
384 /***********************************************************************
385 * CreateFontIndirectW (GDI32.@)
387 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
394 if ((fontPtr = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC,
395 (HGDIOBJ *)&hFont, &font_funcs )))
397 static const WCHAR ItalicW[] = {' ','I','t','a','l','i','c','\0'};
398 static const WCHAR BoldW[] = {' ','B','o','l','d','\0'};
399 WCHAR *pFaceNameItalicSuffix, *pFaceNameBoldSuffix;
400 WCHAR* pFaceNameSuffix = NULL;
402 memcpy( &fontPtr->logfont, plf, sizeof(LOGFONTW) );
404 TRACE("(%ld %ld %ld %ld %x %d %x %d %d) %s %s %s %s => %p\n",
405 plf->lfHeight, plf->lfWidth,
406 plf->lfEscapement, plf->lfOrientation,
407 plf->lfPitchAndFamily,
408 plf->lfOutPrecision, plf->lfClipPrecision,
409 plf->lfQuality, plf->lfCharSet,
410 debugstr_w(plf->lfFaceName),
411 plf->lfWeight > 400 ? "Bold" : "",
412 plf->lfItalic ? "Italic" : "",
413 plf->lfUnderline ? "Underline" : "", hFont);
415 if (plf->lfEscapement != plf->lfOrientation) {
416 /* this should really depend on whether GM_ADVANCED is set */
417 fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
418 WARN("orientation angle %f set to "
419 "escapement angle %f for new font %p\n",
420 plf->lfOrientation/10., plf->lfEscapement/10., hFont);
423 pFaceNameItalicSuffix = strstrW(fontPtr->logfont.lfFaceName, ItalicW);
424 if (pFaceNameItalicSuffix) {
425 fontPtr->logfont.lfItalic = TRUE;
426 pFaceNameSuffix = pFaceNameItalicSuffix;
429 pFaceNameBoldSuffix = strstrW(fontPtr->logfont.lfFaceName, BoldW);
430 if (pFaceNameBoldSuffix) {
431 if (fontPtr->logfont.lfWeight < FW_BOLD) {
432 fontPtr->logfont.lfWeight = FW_BOLD;
434 if (!pFaceNameSuffix ||
435 (pFaceNameBoldSuffix < pFaceNameSuffix)) {
436 pFaceNameSuffix = pFaceNameBoldSuffix;
440 if (pFaceNameSuffix) *pFaceNameSuffix = 0;
442 GDI_ReleaseObj( hFont );
445 else WARN("(NULL) => NULL\n");
450 /*************************************************************************
451 * CreateFontA (GDI32.@)
453 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
454 INT orient, INT weight, DWORD italic,
455 DWORD underline, DWORD strikeout, DWORD charset,
456 DWORD outpres, DWORD clippres, DWORD quality,
457 DWORD pitch, LPCSTR name )
461 logfont.lfHeight = height;
462 logfont.lfWidth = width;
463 logfont.lfEscapement = esc;
464 logfont.lfOrientation = orient;
465 logfont.lfWeight = weight;
466 logfont.lfItalic = italic;
467 logfont.lfUnderline = underline;
468 logfont.lfStrikeOut = strikeout;
469 logfont.lfCharSet = charset;
470 logfont.lfOutPrecision = outpres;
471 logfont.lfClipPrecision = clippres;
472 logfont.lfQuality = quality;
473 logfont.lfPitchAndFamily = pitch;
476 lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
478 logfont.lfFaceName[0] = '\0';
480 return CreateFontIndirectA( &logfont );
483 /*************************************************************************
484 * CreateFontW (GDI32.@)
486 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
487 INT orient, INT weight, DWORD italic,
488 DWORD underline, DWORD strikeout, DWORD charset,
489 DWORD outpres, DWORD clippres, DWORD quality,
490 DWORD pitch, LPCWSTR name )
494 logfont.lfHeight = height;
495 logfont.lfWidth = width;
496 logfont.lfEscapement = esc;
497 logfont.lfOrientation = orient;
498 logfont.lfWeight = weight;
499 logfont.lfItalic = italic;
500 logfont.lfUnderline = underline;
501 logfont.lfStrikeOut = strikeout;
502 logfont.lfCharSet = charset;
503 logfont.lfOutPrecision = outpres;
504 logfont.lfClipPrecision = clippres;
505 logfont.lfQuality = quality;
506 logfont.lfPitchAndFamily = pitch;
509 lstrcpynW(logfont.lfFaceName, name,
510 sizeof(logfont.lfFaceName) / sizeof(WCHAR));
512 logfont.lfFaceName[0] = '\0';
514 return CreateFontIndirectW( &logfont );
518 /***********************************************************************
521 * If the driver supports vector fonts we create a gdi font first and
522 * then call the driver to give it a chance to supply its own device
523 * font. If the driver wants to do this it returns TRUE and we can
524 * delete the gdi font, if the driver wants to use the gdi font it
525 * should return FALSE, to signal an error return GDI_ERROR. For
526 * drivers that don't support vector fonts they must supply their own
529 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, void *obj, HDC hdc )
532 DC *dc = DC_GetDCPtr( hdc );
536 if (dc->hFont != handle || dc->gdiFont == NULL)
538 if(GetDeviceCaps(dc->hSelf, TEXTCAPS) & TC_VA_ABLE)
539 dc->gdiFont = WineEngCreateFontInstance(dc, handle);
542 if (dc->funcs->pSelectFont) ret = dc->funcs->pSelectFont( dc->physDev, handle, dc->gdiFont );
544 if (ret && dc->gdiFont) dc->gdiFont = 0;
546 if (ret == HGDI_ERROR)
547 ret = 0; /* SelectObject returns 0 on error */
553 GDI_ReleaseObj( hdc );
558 /***********************************************************************
561 static INT FONT_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
566 FONT_LogFontWTo16( &font->logfont, &lf16 );
568 if (count > sizeof(LOGFONT16)) count = sizeof(LOGFONT16);
569 memcpy( buffer, &lf16, count );
573 /***********************************************************************
576 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
583 FONT_LogFontWToA( &font->logfont, &lfA );
585 if (count > sizeof(lfA)) count = sizeof(lfA);
586 memcpy( buffer, &lfA, count );
590 /***********************************************************************
593 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
597 return sizeof(LOGFONTW);
598 if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
599 memcpy( buffer, &font->logfont, count );
604 /***********************************************************************
607 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj )
609 WineEngDestroyFontInstance( handle );
610 return GDI_FreeObject( handle, obj );
614 /***********************************************************************
615 * FONT_EnumInstance16
617 * Called by the device driver layer to pass font info
618 * down to the application.
620 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
621 * We have to use other types because of the FONTENUMPROCW definition.
623 static INT CALLBACK FONT_EnumInstance16( const LOGFONTW *plf, const TEXTMETRICW *ptm,
624 DWORD fType, LPARAM lp )
626 fontEnum16 *pfe = (fontEnum16*)lp;
630 if( pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
631 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet )
636 FONT_EnumLogFontExWTo16((const ENUMLOGFONTEXW *)plf, pfe->lpLogFont);
637 FONT_NewTextMetricExWTo16((const NEWTEXTMETRICEXW *)ptm, pfe->lpTextMetric);
638 pfe->dwFlags |= ENUM_CALLED;
639 GDI_ReleaseObj( pfe->hdc ); /* release the GDI lock */
641 args[6] = SELECTOROF(pfe->segLogFont);
642 args[5] = OFFSETOF(pfe->segLogFont);
643 args[4] = SELECTOROF(pfe->segTextMetric);
644 args[3] = OFFSETOF(pfe->segTextMetric);
646 args[1] = HIWORD(pfe->lpData);
647 args[0] = LOWORD(pfe->lpData);
648 WOWCallback16Ex( (DWORD)pfe->lpEnumFunc, WCB16_PASCAL, sizeof(args), args, &result );
649 ret = LOWORD(result);
651 /* get the lock again and make sure the DC is still valid */
652 dc = DC_GetDCPtr( pfe->hdc );
653 if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
655 if (dc) GDI_ReleaseObj( pfe->hdc );
656 pfe->hdc = 0; /* make sure we don't try to release it later on */
663 /***********************************************************************
666 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
667 * We have to use other types because of the FONTENUMPROCW definition.
669 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
670 DWORD fType, LPARAM lp )
672 fontEnum32 *pfe = (fontEnum32*)lp;
676 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
677 if((pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
678 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
679 (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
681 /* convert font metrics */
682 ENUMLOGFONTEXA logfont;
683 NEWTEXTMETRICEXA tmA;
685 pfe->dwFlags |= ENUM_CALLED;
686 if (!(pfe->dwFlags & ENUM_UNICODE))
688 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
689 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
690 plf = (LOGFONTW *)&logfont.elfLogFont;
691 ptm = (TEXTMETRICW *)&tmA;
693 GDI_ReleaseObj( pfe->hdc ); /* release the GDI lock */
695 ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
697 /* get the lock again and make sure the DC is still valid */
698 dc = DC_GetDCPtr( pfe->hdc );
699 if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
701 if (dc) GDI_ReleaseObj( pfe->hdc );
702 pfe->hdc = 0; /* make sure we don't try to release it later on */
709 /***********************************************************************
710 * EnumFontFamiliesEx (GDI.613)
712 INT16 WINAPI EnumFontFamiliesEx16( HDC16 hDC, LPLOGFONT16 plf,
713 FONTENUMPROC16 efproc, LPARAM lParam,
718 DC* dc = DC_GetDCPtr( HDC_32(hDC) );
719 NEWTEXTMETRICEX16 tm16;
720 ENUMLOGFONTEX16 lf16;
725 FONT_LogFont16ToW(plf, &lfW);
727 fe16.hdc = HDC_32(hDC);
729 fe16.physDev = dc->physDev;
730 fe16.lpLogFontParam = plf;
731 fe16.lpEnumFunc = efproc;
732 fe16.lpData = lParam;
733 fe16.lpTextMetric = &tm16;
734 fe16.lpLogFont = &lf16;
735 fe16.segTextMetric = MapLS( &tm16 );
736 fe16.segLogFont = MapLS( &lf16 );
739 enum_gdi_fonts = GetDeviceCaps(fe16.hdc, TEXTCAPS) & TC_VA_ABLE;
741 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
748 ret = WineEngEnumFonts( &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
749 fe16.dwFlags &= ~ENUM_CALLED;
750 if (ret && dc->funcs->pEnumDeviceFonts) {
751 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
752 if(fe16.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
756 UnMapLS( fe16.segTextMetric );
757 UnMapLS( fe16.segLogFont );
758 if (fe16.hdc) GDI_ReleaseObj( fe16.hdc );
762 /***********************************************************************
763 * FONT_EnumFontFamiliesEx
765 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf,
766 FONTENUMPROCW efproc,
767 LPARAM lParam, DWORD dwUnicode)
770 DC *dc = DC_GetDCPtr( hDC );
776 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName),
778 fe32.lpLogFontParam = plf;
779 fe32.lpEnumFunc = efproc;
780 fe32.lpData = lParam;
781 fe32.dwFlags = dwUnicode;
784 fe32.physDev = dc->physDev;
786 enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE;
788 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
795 ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
796 fe32.dwFlags &= ~ENUM_CALLED;
797 if (ret && dc->funcs->pEnumDeviceFonts) {
798 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, plf, FONT_EnumInstance, (LPARAM)&fe32 );
799 if(fe32.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
803 if (fe32.hdc) GDI_ReleaseObj( fe32.hdc );
807 /***********************************************************************
808 * EnumFontFamiliesExW (GDI32.@)
810 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
811 FONTENUMPROCW efproc,
812 LPARAM lParam, DWORD dwFlags )
814 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, ENUM_UNICODE );
817 /***********************************************************************
818 * EnumFontFamiliesExA (GDI32.@)
820 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
821 FONTENUMPROCA efproc,
822 LPARAM lParam, DWORD dwFlags)
825 FONT_LogFontAToW( plf, &lfW );
827 return FONT_EnumFontFamiliesEx( hDC, &lfW, (FONTENUMPROCW)efproc, lParam, 0);
830 /***********************************************************************
831 * EnumFontFamilies (GDI.330)
833 INT16 WINAPI EnumFontFamilies16( HDC16 hDC, LPCSTR lpFamily,
834 FONTENUMPROC16 efproc, LPARAM lpData )
838 lf.lfCharSet = DEFAULT_CHARSET;
839 if( lpFamily ) lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
840 else lf.lfFaceName[0] = '\0';
842 return EnumFontFamiliesEx16( hDC, &lf, efproc, lpData, 0 );
845 /***********************************************************************
846 * EnumFontFamiliesA (GDI32.@)
848 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
849 FONTENUMPROCA efproc, LPARAM lpData )
853 lf.lfCharSet = DEFAULT_CHARSET;
854 if( lpFamily ) lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
855 else lf.lfFaceName[0] = lf.lfFaceName[1] = '\0';
857 return EnumFontFamiliesExA( hDC, &lf, efproc, lpData, 0 );
860 /***********************************************************************
861 * EnumFontFamiliesW (GDI32.@)
863 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
864 FONTENUMPROCW efproc, LPARAM lpData )
868 lf.lfCharSet = DEFAULT_CHARSET;
869 if( lpFamily ) lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
870 else lf.lfFaceName[0] = 0;
872 return EnumFontFamiliesExW( hDC, &lf, efproc, lpData, 0 );
875 /***********************************************************************
878 INT16 WINAPI EnumFonts16( HDC16 hDC, LPCSTR lpName, FONTENUMPROC16 efproc,
881 return EnumFontFamilies16( hDC, lpName, efproc, lpData );
884 /***********************************************************************
885 * EnumFontsA (GDI32.@)
887 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
890 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
893 /***********************************************************************
894 * EnumFontsW (GDI32.@)
896 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
899 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
903 /***********************************************************************
904 * GetTextCharacterExtra (GDI32.@)
906 INT WINAPI GetTextCharacterExtra( HDC hdc )
909 DC *dc = DC_GetDCPtr( hdc );
910 if (!dc) return 0x80000000;
912 GDI_ReleaseObj( hdc );
917 /***********************************************************************
918 * SetTextCharacterExtra (GDI32.@)
920 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
923 DC * dc = DC_GetDCPtr( hdc );
924 if (!dc) return 0x80000000;
925 if (dc->funcs->pSetTextCharacterExtra)
926 prev = dc->funcs->pSetTextCharacterExtra( dc->physDev, extra );
929 prev = dc->charExtra;
930 dc->charExtra = extra;
932 GDI_ReleaseObj( hdc );
937 /***********************************************************************
938 * SetTextJustification (GDI32.@)
940 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
943 DC * dc = DC_GetDCPtr( hdc );
944 if (!dc) return FALSE;
945 if (dc->funcs->pSetTextJustification)
946 ret = dc->funcs->pSetTextJustification( dc->physDev, extra, breaks );
949 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
950 if (!extra) breaks = 0;
953 dc->breakExtra = extra / breaks;
954 dc->breakRem = extra - (breaks * dc->breakExtra);
962 GDI_ReleaseObj( hdc );
967 /***********************************************************************
968 * GetTextFaceA (GDI32.@)
970 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
972 INT res = GetTextFaceW(hdc, 0, NULL);
973 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
974 GetTextFaceW( hdc, res, nameW );
978 if (count && !WideCharToMultiByte( CP_ACP, 0, nameW, -1, name, count, NULL, NULL))
983 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
984 HeapFree( GetProcessHeap(), 0, nameW );
988 /***********************************************************************
989 * GetTextFaceW (GDI32.@)
991 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
996 DC * dc = DC_GetDCPtr( hdc );
1000 ret = WineEngGetTextFace(dc->gdiFont, count, name);
1001 else if ((font = (FONTOBJ *) GDI_GetObjPtr( dc->hFont, FONT_MAGIC )))
1005 lstrcpynW( name, font->logfont.lfFaceName, count );
1006 ret = strlenW(name);
1008 else ret = strlenW(font->logfont.lfFaceName) + 1;
1009 GDI_ReleaseObj( dc->hFont );
1011 GDI_ReleaseObj( hdc );
1016 /***********************************************************************
1017 * GetTextExtentPoint32A (GDI32.@)
1019 * See GetTextExtentPoint32W.
1021 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
1026 LPWSTR p = FONT_mbtowc(str, count, &wlen);
1029 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
1030 HeapFree( GetProcessHeap(), 0, p );
1033 TRACE("(%p %s %d %p): returning %ld x %ld\n",
1034 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
1039 /***********************************************************************
1040 * GetTextExtentPoint32W [GDI32.@]
1042 * Computes width/height for a string.
1044 * Computes width and height of the specified string.
1050 BOOL WINAPI GetTextExtentPoint32W(
1051 HDC hdc, /* [in] Handle of device context */
1052 LPCWSTR str, /* [in] Address of text string */
1053 INT count, /* [in] Number of characters in string */
1054 LPSIZE size) /* [out] Address of structure for string size */
1057 DC * dc = DC_GetDCPtr( hdc );
1058 if (!dc) return FALSE;
1061 ret = WineEngGetTextExtentPoint(dc->gdiFont, str, count, size);
1062 else if(dc->funcs->pGetTextExtentPoint)
1063 ret = dc->funcs->pGetTextExtentPoint( dc->physDev, str, count, size );
1067 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1068 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1069 size->cx += count * dc->charExtra + dc->breakRem;
1072 GDI_ReleaseObj( hdc );
1074 TRACE("(%p %s %d %p): returning %ld x %ld\n",
1075 hdc, debugstr_wn (str, count), count, size, size->cx, size->cy );
1079 /***********************************************************************
1080 * GetTextExtentPointI [GDI32.@]
1082 * Computes width and height of the array of glyph indices.
1088 BOOL WINAPI GetTextExtentPointI(
1089 HDC hdc, /* [in] Handle of device context */
1090 const WORD *indices, /* [in] Address of glyph index array */
1091 INT count, /* [in] Number of glyphs in array */
1092 LPSIZE size) /* [out] Address of structure for string size */
1095 DC * dc = DC_GetDCPtr( hdc );
1096 if (!dc) return FALSE;
1099 ret = WineEngGetTextExtentPointI(dc->gdiFont, indices, count, size);
1100 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1101 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1102 size->cx += count * dc->charExtra;
1104 else if(dc->funcs->pGetTextExtentPoint) {
1105 FIXME("calling GetTextExtentPoint\n");
1106 ret = dc->funcs->pGetTextExtentPoint( dc->physDev, (LPCWSTR)indices, count, size );
1109 GDI_ReleaseObj( hdc );
1111 TRACE("(%p %p %d %p): returning %ld x %ld\n",
1112 hdc, indices, count, size, size->cx, size->cy );
1117 /***********************************************************************
1118 * GetTextExtentPointA (GDI32.@)
1120 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
1123 TRACE("not bug compatible.\n");
1124 return GetTextExtentPoint32A( hdc, str, count, size );
1127 /***********************************************************************
1128 * GetTextExtentPointW (GDI32.@)
1130 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1133 TRACE("not bug compatible.\n");
1134 return GetTextExtentPoint32W( hdc, str, count, size );
1138 /***********************************************************************
1139 * GetTextExtentExPointA (GDI32.@)
1141 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1142 INT maxExt, LPINT lpnFit,
1143 LPINT alpDx, LPSIZE size )
1147 LPWSTR p = FONT_mbtowc(str, count, &wlen);
1148 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, alpDx, size);
1149 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1150 HeapFree( GetProcessHeap(), 0, p );
1155 /***********************************************************************
1156 * GetTextExtentExPointW (GDI32.@)
1158 * Return the size of the string as it would be if it was output properly by
1161 * This should include
1162 * - Intercharacter spacing
1163 * - justification spacing (not yet done)
1164 * - kerning? see below
1166 * Kerning. Since kerning would be carried out by the rendering code it should
1167 * be done by the driver. However they don't support it yet. Also I am not
1168 * yet persuaded that (certainly under Win95) any kerning is actually done.
1170 * str: According to MSDN this should be null-terminated. That is not true; a
1171 * null will not terminate it early.
1172 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1173 * than count. I have seen it be either the size of the full string or
1174 * 1 less than the size of the full string. I have not seen it bear any
1175 * resemblance to the portion that would fit.
1176 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1177 * trailing intercharacter spacing and any trailing justification.
1180 * Currently we do this by measuring each character etc. We should do it by
1181 * passing the request to the driver, perhaps by extending the
1182 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1183 * thinking about kerning issues and rounding issues in the justification.
1186 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1187 INT maxExt, LPINT lpnFit,
1188 LPINT alpDx, LPSIZE size )
1190 int index, nFit, extent;
1194 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1196 size->cx = size->cy = nFit = extent = 0;
1197 for(index = 0; index < count; index++)
1199 if(!GetTextExtentPoint32W( hdc, str, index + 1, &tSize )) goto done;
1200 /* GetTextExtentPoint includes intercharacter spacing. */
1201 /* FIXME - justification needs doing yet. Remember that the base
1202 * data will not be in logical coordinates.
1205 if( !lpnFit || extent <= maxExt )
1206 /* It is allowed to be equal. */
1209 if( alpDx ) alpDx[index] = extent;
1211 if( tSize.cy > size->cy ) size->cy = tSize.cy;
1214 if(lpnFit) *lpnFit = nFit;
1217 TRACE("returning %d %ld x %ld\n",nFit,size->cx,size->cy);
1223 /***********************************************************************
1224 * GetTextMetricsA (GDI32.@)
1226 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1230 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1231 FONT_TextMetricWToA( &tm32, metrics );
1235 /***********************************************************************
1236 * GetTextMetricsW (GDI32.@)
1238 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1241 DC * dc = DC_GetDCPtr( hdc );
1242 if (!dc) return FALSE;
1245 ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1246 else if (dc->funcs->pGetTextMetrics)
1247 ret = dc->funcs->pGetTextMetrics( dc->physDev, metrics );
1251 /* device layer returns values in device units
1252 * therefore we have to convert them to logical */
1254 #define WDPTOLP(x) ((x<0)? \
1255 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1256 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1257 #define HDPTOLP(y) ((y<0)? \
1258 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1259 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1261 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1262 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1263 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1264 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1265 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1266 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1267 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1268 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1272 TRACE("text metrics:\n"
1273 " Weight = %03li\t FirstChar = %i\t AveCharWidth = %li\n"
1274 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %li\n"
1275 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %li\n"
1276 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1277 " PitchAndFamily = %02x\n"
1278 " --------------------\n"
1279 " InternalLeading = %li\n"
1283 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1284 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1285 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1286 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1287 metrics->tmPitchAndFamily,
1288 metrics->tmInternalLeading,
1291 metrics->tmHeight );
1293 GDI_ReleaseObj( hdc );
1298 /***********************************************************************
1299 * GetOutlineTextMetrics [GDI.308] Gets metrics for TrueType fonts.
1302 * lpOTM should be LPOUTLINETEXTMETRIC
1305 * Success: Non-zero or size of required buffer
1308 UINT16 WINAPI GetOutlineTextMetrics16(
1309 HDC16 hdc, /* [in] Handle of device context */
1310 UINT16 cbData, /* [in] Size of metric data array */
1311 LPOUTLINETEXTMETRIC16 lpOTM) /* [out] Address of metric data array */
1313 FIXME("(%04x,%04x,%p): stub\n", hdc,cbData,lpOTM);
1318 /***********************************************************************
1319 * GetOutlineTextMetricsA (GDI32.@)
1320 * Gets metrics for TrueType fonts.
1323 * If the supplied buffer isn't big enough Windows partially fills it up to
1324 * its given length and returns that length.
1327 * Success: Non-zero or size of required buffer
1330 UINT WINAPI GetOutlineTextMetricsA(
1331 HDC hdc, /* [in] Handle of device context */
1332 UINT cbData, /* [in] Size of metric data array */
1333 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1335 char buf[512], *ptr;
1337 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1338 OUTLINETEXTMETRICA *output = lpOTM;
1341 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1343 if(ret > sizeof(buf))
1344 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1345 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1347 needed = sizeof(OUTLINETEXTMETRICA);
1348 if(lpOTMW->otmpFamilyName)
1349 needed += WideCharToMultiByte(CP_ACP, 0,
1350 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1351 NULL, 0, NULL, NULL);
1352 if(lpOTMW->otmpFaceName)
1353 needed += WideCharToMultiByte(CP_ACP, 0,
1354 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1355 NULL, 0, NULL, NULL);
1356 if(lpOTMW->otmpStyleName)
1357 needed += WideCharToMultiByte(CP_ACP, 0,
1358 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1359 NULL, 0, NULL, NULL);
1360 if(lpOTMW->otmpFullName)
1361 needed += WideCharToMultiByte(CP_ACP, 0,
1362 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1363 NULL, 0, NULL, NULL);
1370 TRACE("needed = %d\n", needed);
1372 /* Since the supplied buffer isn't big enough, we'll alloc one
1373 that is and memcpy the first cbData bytes into the lpOTM at
1375 output = HeapAlloc(GetProcessHeap(), 0, needed);
1377 ret = output->otmSize = min(needed, cbData);
1378 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1379 output->otmFiller = 0;
1380 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1381 output->otmfsSelection = lpOTMW->otmfsSelection;
1382 output->otmfsType = lpOTMW->otmfsType;
1383 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1384 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1385 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1386 output->otmEMSquare = lpOTMW->otmEMSquare;
1387 output->otmAscent = lpOTMW->otmAscent;
1388 output->otmDescent = lpOTMW->otmDescent;
1389 output->otmLineGap = lpOTMW->otmLineGap;
1390 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1391 output->otmsXHeight = lpOTMW->otmsXHeight;
1392 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1393 output->otmMacAscent = lpOTMW->otmMacAscent;
1394 output->otmMacDescent = lpOTMW->otmMacDescent;
1395 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1396 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1397 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1398 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1399 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1400 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1401 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1402 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1403 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1404 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1407 ptr = (char*)(output + 1);
1408 left = needed - sizeof(*output);
1410 if(lpOTMW->otmpFamilyName) {
1411 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1412 len = WideCharToMultiByte(CP_ACP, 0,
1413 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1414 ptr, left, NULL, NULL);
1418 output->otmpFamilyName = 0;
1420 if(lpOTMW->otmpFaceName) {
1421 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1422 len = WideCharToMultiByte(CP_ACP, 0,
1423 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1424 ptr, left, NULL, NULL);
1428 output->otmpFaceName = 0;
1430 if(lpOTMW->otmpStyleName) {
1431 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1432 len = WideCharToMultiByte(CP_ACP, 0,
1433 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1434 ptr, left, NULL, NULL);
1438 output->otmpStyleName = 0;
1440 if(lpOTMW->otmpFullName) {
1441 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1442 len = WideCharToMultiByte(CP_ACP, 0,
1443 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1444 ptr, left, NULL, NULL);
1447 output->otmpFullName = 0;
1451 if(output != lpOTM) {
1452 memcpy(lpOTM, output, cbData);
1453 HeapFree(GetProcessHeap(), 0, output);
1457 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1458 HeapFree(GetProcessHeap(), 0, lpOTMW);
1464 /***********************************************************************
1465 * GetOutlineTextMetricsW [GDI32.@]
1467 UINT WINAPI GetOutlineTextMetricsW(
1468 HDC hdc, /* [in] Handle of device context */
1469 UINT cbData, /* [in] Size of metric data array */
1470 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1472 DC *dc = DC_GetDCPtr( hdc );
1473 OUTLINETEXTMETRICW *output = lpOTM;
1476 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1480 ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, output);
1483 output = HeapAlloc(GetProcessHeap(), 0, ret);
1484 WineEngGetOutlineTextMetrics(dc->gdiFont, ret, output);
1487 #define WDPTOLP(x) ((x<0)? \
1488 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1489 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1490 #define HDPTOLP(y) ((y<0)? \
1491 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1492 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1494 output->otmTextMetrics.tmHeight = HDPTOLP(output->otmTextMetrics.tmHeight);
1495 output->otmTextMetrics.tmAscent = HDPTOLP(output->otmTextMetrics.tmAscent);
1496 output->otmTextMetrics.tmDescent = HDPTOLP(output->otmTextMetrics.tmDescent);
1497 output->otmTextMetrics.tmInternalLeading = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1498 output->otmTextMetrics.tmExternalLeading = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1499 output->otmTextMetrics.tmAveCharWidth = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1500 output->otmTextMetrics.tmMaxCharWidth = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1501 output->otmTextMetrics.tmOverhang = WDPTOLP(output->otmTextMetrics.tmOverhang);
1502 output->otmAscent = HDPTOLP(output->otmAscent);
1503 output->otmDescent = HDPTOLP(output->otmDescent);
1504 output->otmLineGap = HDPTOLP(output->otmLineGap);
1505 output->otmsCapEmHeight = HDPTOLP(output->otmsCapEmHeight);
1506 output->otmsXHeight = HDPTOLP(output->otmsXHeight);
1507 output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1508 output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1509 output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1510 output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1511 output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1512 output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1513 output->otmMacLineGap = HDPTOLP(output->otmMacLineGap);
1514 output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1515 output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1516 output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1517 output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1518 output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1519 output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1520 output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1521 output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1522 output->otmsStrikeoutSize = HDPTOLP(output->otmsStrikeoutSize);
1523 output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1524 output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1525 output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1528 if(output != lpOTM) {
1529 memcpy(lpOTM, output, cbData);
1530 HeapFree(GetProcessHeap(), 0, output);
1536 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1537 but really this should just be a return 0. */
1539 ret = sizeof(*lpOTM);
1544 memset(lpOTM, 0, ret);
1545 lpOTM->otmSize = sizeof(*lpOTM);
1546 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1548 Further fill of the structure not implemented,
1549 Needs real values for the structure members
1554 GDI_ReleaseObj(hdc);
1559 /***********************************************************************
1560 * GetCharWidthW (GDI32.@)
1561 * GetCharWidth32W (GDI32.@)
1563 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1568 DC * dc = DC_GetDCPtr( hdc );
1569 if (!dc) return FALSE;
1572 ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1573 else if (dc->funcs->pGetCharWidth)
1574 ret = dc->funcs->pGetCharWidth( dc->physDev, firstChar, lastChar, buffer);
1578 /* convert device units to logical */
1579 for( i = firstChar; i <= lastChar; i++, buffer++ )
1580 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1583 GDI_ReleaseObj( hdc );
1588 /***********************************************************************
1589 * GetCharWidthA (GDI32.@)
1590 * GetCharWidth32A (GDI32.@)
1592 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1595 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1600 if(count <= 0) return FALSE;
1602 str = HeapAlloc(GetProcessHeap(), 0, count);
1603 for(i = 0; i < count; i++)
1604 str[i] = (BYTE)(firstChar + i);
1606 wstr = FONT_mbtowc(str, count, &wlen);
1608 for(i = 0; i < wlen; i++)
1610 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1618 HeapFree(GetProcessHeap(), 0, str);
1619 HeapFree(GetProcessHeap(), 0, wstr);
1625 /***********************************************************************
1626 * ExtTextOutA (GDI32.@)
1630 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1631 const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1638 if (flags & ETO_GLYPH_INDEX)
1639 return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
1641 p = FONT_mbtowc(str, count, &wlen);
1644 unsigned int i = 0, j = 0;
1646 lpDxW = HeapAlloc( GetProcessHeap(), 0, wlen*sizeof(INT));
1648 if(IsDBCSLeadByte(str[i])) {
1649 lpDxW[j++] = lpDx[i] + lpDx[i+1];
1652 lpDxW[j++] = lpDx[i];
1658 ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1660 HeapFree( GetProcessHeap(), 0, p );
1661 HeapFree( GetProcessHeap(), 0, lpDxW );
1666 /***********************************************************************
1667 * ExtTextOutW (GDI32.@)
1669 * Draws text using the currently selected font, background color, and text color.
1673 * x,y [I] coordinates of string
1675 * ETO_GRAYED - undocumented on MSDN
1676 * ETO_OPAQUE - use background color for fill the rectangle
1677 * ETO_CLIPPED - clipping text to the rectangle
1678 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1679 * than encoded characters. Implies ETO_IGNORELANGUAGE
1680 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1681 * Affects BiDi ordering
1682 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1683 * ETO_PDY - unimplemented
1684 * ETO_NUMERICSLATIN - unimplemented always assumed -
1685 * do not translate numbers into locale representations
1686 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1687 * lprect [I] dimensions for clipping or/and opaquing
1688 * str [I] text string
1689 * count [I] number of symbols in string
1690 * lpDx [I] optional parameter with distance between drawing characters
1696 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1697 const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1700 LPWSTR reordered_str = (LPWSTR)str;
1701 WORD *glyphs = NULL;
1702 UINT align = GetTextAlign( hdc );
1706 double cosEsc, sinEsc;
1707 INT *deltas = NULL, char_extra;
1710 BOOL done_extents = FALSE;
1711 INT width, xwidth = 0, ywidth = 0;
1713 DC * dc = DC_GetDCUpdate( hdc );
1715 if (!dc) return FALSE;
1717 if (flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY))
1718 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY unimplemented\n");
1720 if (!dc->funcs->pExtTextOut && !PATH_IsPathOpen(dc->path))
1722 GDI_ReleaseObj( hdc );
1726 type = GetObjectType(hdc);
1727 if(type == OBJ_METADC || type == OBJ_ENHMETADC)
1729 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, flags, lprect, str, count, lpDx);
1730 GDI_ReleaseObj( hdc );
1734 if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && BidiAvail && count > 0 )
1736 reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1738 BIDI_Reorder( str, count, GCP_REORDER,
1739 ((flags&ETO_RTLREADING)!=0 || (GetTextAlign(hdc)&TA_RTLREADING)!=0)?
1740 WINE_GCPW_FORCE_RTL:WINE_GCPW_FORCE_LTR,
1741 reordered_str, count, NULL );
1743 flags |= ETO_IGNORELANGUAGE;
1746 TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc, x, y, flags,
1747 lprect, debugstr_wn(str, count), count, lpDx);
1749 if(flags & ETO_GLYPH_INDEX)
1750 glyphs = reordered_str;
1753 TRACE("rect: %ld,%ld - %ld,%ld\n", lprect->left, lprect->top, lprect->right,
1755 TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
1757 if(align & TA_UPDATECP)
1759 GetCurrentPositionEx( hdc, &pt );
1764 GetTextMetricsW(hdc, &tm);
1765 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1767 if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
1768 lf.lfEscapement = 0;
1770 if(lf.lfEscapement != 0)
1772 cosEsc = cos(lf.lfEscapement * M_PI / 1800);
1773 sinEsc = sin(lf.lfEscapement * M_PI / 1800);
1781 if(flags & (ETO_CLIPPED | ETO_OPAQUE))
1785 if(flags & ETO_CLIPPED) goto done;
1786 if(flags & ETO_GLYPH_INDEX)
1787 GetTextExtentPointI(hdc, glyphs, count, &sz);
1789 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1791 done_extents = TRUE;
1794 rc.right = x + sz.cx;
1795 rc.bottom = y + sz.cy;
1802 LPtoDP(hdc, (POINT*)&rc, 2);
1804 if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
1805 if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
1808 if ((flags & ETO_OPAQUE) && !PATH_IsPathOpen(dc->path))
1809 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1819 LPtoDP(hdc, &pt, 1);
1823 char_extra = GetTextCharacterExtra(hdc);
1825 if(char_extra || dc->breakExtra || lpDx)
1829 deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT));
1830 for(i = 0; i < count; i++)
1833 deltas[i] = lpDx[i] + char_extra;
1836 if(flags & ETO_GLYPH_INDEX)
1837 GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
1839 GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
1841 deltas[i] = tmpsz.cx;
1844 if (!(flags & ETO_GLYPH_INDEX) && dc->breakExtra && reordered_str[i] == tm.tmBreakChar)
1846 deltas[i] = deltas[i] + dc->breakExtra;
1848 deltas[i] = INTERNAL_XWSTODS(dc, deltas[i]);
1856 if(flags & ETO_GLYPH_INDEX)
1857 GetTextExtentPointI(hdc, glyphs, count, &sz);
1859 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1860 done_extents = TRUE;
1862 width = INTERNAL_XWSTODS(dc, sz.cx);
1864 xwidth = width * cosEsc;
1865 ywidth = width * sinEsc;
1867 tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
1868 tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
1869 switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
1872 if (align & TA_UPDATECP)
1876 DPtoLP(hdc, &pt, 1);
1877 MoveToEx(hdc, pt.x, pt.y, NULL);
1889 if (align & TA_UPDATECP)
1893 DPtoLP(hdc, &pt, 1);
1894 MoveToEx(hdc, pt.x, pt.y, NULL);
1899 switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
1902 y += tm.tmAscent * cosEsc;
1903 x += tm.tmAscent * sinEsc;
1907 y -= tm.tmDescent * cosEsc;
1908 x -= tm.tmDescent * sinEsc;
1915 if (GetBkMode(hdc) != TRANSPARENT && !PATH_IsPathOpen(dc->path))
1917 if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
1919 if(!(flags & ETO_OPAQUE) || x < rc.left || x + width >= rc.right ||
1920 y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
1924 rc.right = x + width;
1925 rc.top = y - tm.tmAscent;
1926 rc.bottom = y + tm.tmDescent;
1927 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1932 if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
1934 HFONT orig_font = dc->hFont, cur_font;
1936 INT span = 0, *offsets = NULL, i;
1938 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
1939 for(i = 0; i < count; i++)
1941 WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
1942 if(cur_font != dc->hFont)
1947 offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
1952 for(j = 1; j < count; j++)
1954 GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
1955 offsets[j] = offsets[j-1] + INTERNAL_XWSTODS(dc, tmpsz.cx);
1960 for(j = 1; j < count; j++)
1961 offsets[j] = offsets[j-1] + deltas[j];
1966 if (PATH_IsPathOpen(dc->path))
1967 ret = PATH_ExtTextOut(dc, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
1968 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
1969 glyphs, span, deltas ? deltas + i - span : NULL);
1971 dc->funcs->pExtTextOut(dc->physDev, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
1972 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
1973 glyphs, span, deltas ? deltas + i - span : NULL);
1976 SelectObject(hdc, cur_font);
1978 glyphs[span++] = glyph;
1982 if (PATH_IsPathOpen(dc->path))
1983 ret = PATH_ExtTextOut(dc, x + (offsets ? offsets[count - span] * cosEsc : 0),
1984 y - (offsets ? offsets[count - span] * sinEsc : 0),
1985 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
1986 glyphs, span, deltas ? deltas + count - span : NULL);
1988 ret = dc->funcs->pExtTextOut(dc->physDev, x + (offsets ? offsets[count - span] * cosEsc : 0),
1989 y - (offsets ? offsets[count - span] * sinEsc : 0),
1990 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
1991 glyphs, span, deltas ? deltas + count - span : NULL);
1992 SelectObject(hdc, orig_font);
1993 HeapFree(GetProcessHeap(), 0, offsets);
1999 if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
2001 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2002 GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
2003 flags |= ETO_GLYPH_INDEX;
2006 if (PATH_IsPathOpen(dc->path))
2007 ret = PATH_ExtTextOut(dc, x, y, (flags & ~ETO_OPAQUE), &rc,
2008 glyphs ? glyphs : reordered_str, count, deltas);
2010 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, (flags & ~ETO_OPAQUE), &rc,
2011 glyphs ? glyphs : reordered_str, count, deltas);
2015 HeapFree(GetProcessHeap(), 0, deltas);
2016 if(glyphs != reordered_str)
2017 HeapFree(GetProcessHeap(), 0, glyphs);
2018 if(reordered_str != str)
2019 HeapFree(GetProcessHeap(), 0, reordered_str);
2021 GDI_ReleaseObj( hdc );
2023 if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2025 int underlinePos, strikeoutPos;
2026 int underlineWidth, strikeoutWidth;
2027 UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2028 OUTLINETEXTMETRICW* otm = NULL;
2033 underlineWidth = tm.tmAscent / 20 + 1;
2034 strikeoutPos = tm.tmAscent / 2;
2035 strikeoutWidth = underlineWidth;
2039 otm = HeapAlloc(GetProcessHeap(), 0, size);
2040 GetOutlineTextMetricsW(hdc, size, otm);
2041 underlinePos = otm->otmsUnderscorePosition;
2042 underlineWidth = otm->otmsUnderscoreSize;
2043 strikeoutPos = otm->otmsStrikeoutPosition;
2044 strikeoutWidth = otm->otmsStrikeoutSize;
2045 HeapFree(GetProcessHeap(), 0, otm);
2048 if (PATH_IsPathOpen(dc->path))
2052 HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2054 hbrush = SelectObject(hdc, hbrush);
2055 hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2059 pts[0].x = x - underlinePos * sinEsc;
2060 pts[0].y = y - underlinePos * cosEsc;
2061 pts[1].x = x + xwidth - underlinePos * sinEsc;
2062 pts[1].y = y - ywidth - underlinePos * cosEsc;
2063 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2064 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2065 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2066 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2067 pts[4].x = pts[0].x;
2068 pts[4].y = pts[0].y;
2069 DPtoLP(hdc, pts, 5);
2070 Polygon(hdc, pts, 5);
2075 pts[0].x = x - strikeoutPos * sinEsc;
2076 pts[0].y = y - strikeoutPos * cosEsc;
2077 pts[1].x = x + xwidth - strikeoutPos * sinEsc;
2078 pts[1].y = y - ywidth - strikeoutPos * cosEsc;
2079 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2080 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2081 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2082 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2083 pts[4].x = pts[0].x;
2084 pts[4].y = pts[0].y;
2085 DPtoLP(hdc, pts, 5);
2086 Polygon(hdc, pts, 5);
2089 SelectObject(hdc, hpen);
2090 hbrush = SelectObject(hdc, hbrush);
2091 DeleteObject(hbrush);
2095 POINT pts[2], oldpt;
2100 hpen = CreatePen(PS_SOLID, underlineWidth, GetTextColor(hdc));
2101 hpen = SelectObject(hdc, hpen);
2104 pts[1].x = x + xwidth;
2105 pts[1].y = y - ywidth;
2106 DPtoLP(hdc, pts, 2);
2107 MoveToEx(hdc, pts[0].x - underlinePos * sinEsc, pts[0].y - underlinePos * cosEsc, &oldpt);
2108 LineTo(hdc, pts[1].x - underlinePos * sinEsc, pts[1].y - underlinePos * cosEsc);
2109 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2110 DeleteObject(SelectObject(hdc, hpen));
2115 hpen = CreatePen(PS_SOLID, strikeoutWidth, GetTextColor(hdc));
2116 hpen = SelectObject(hdc, hpen);
2119 pts[1].x = x + xwidth;
2120 pts[1].y = y - ywidth;
2121 DPtoLP(hdc, pts, 2);
2122 MoveToEx(hdc, pts[0].x - strikeoutPos * sinEsc, pts[0].y - strikeoutPos * cosEsc, &oldpt);
2123 LineTo(hdc, pts[1].x - strikeoutPos * sinEsc, pts[1].y - strikeoutPos * cosEsc);
2124 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2125 DeleteObject(SelectObject(hdc, hpen));
2134 /***********************************************************************
2135 * TextOutA (GDI32.@)
2137 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2139 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2143 /***********************************************************************
2144 * TextOutW (GDI32.@)
2146 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2148 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2152 /***********************************************************************
2153 * PolyTextOutA (GDI32.@)
2157 BOOL WINAPI PolyTextOutA ( HDC hdc, /* [in] Handle to device context */
2158 PPOLYTEXTA pptxt, /* [in] Array of strings */
2159 INT cStrings ) /* [in] Number of strings in array */
2161 for (; cStrings>0; cStrings--, pptxt++)
2162 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2169 /***********************************************************************
2170 * PolyTextOutW (GDI32.@)
2172 * Draw several Strings
2178 BOOL WINAPI PolyTextOutW ( HDC hdc, /* [in] Handle to device context */
2179 PPOLYTEXTW pptxt, /* [in] Array of strings */
2180 INT cStrings ) /* [in] Number of strings in array */
2182 for (; cStrings>0; cStrings--, pptxt++)
2183 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2189 /* FIXME: all following APIs ******************************************/
2192 /***********************************************************************
2193 * SetMapperFlags (GDI32.@)
2195 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
2197 DC *dc = DC_GetDCPtr( hDC );
2200 if(dc->funcs->pSetMapperFlags)
2202 ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
2203 /* FIXME: ret is just a success flag, we should return a proper value */
2206 FIXME("(%p, 0x%08lx): stub - harmless\n", hDC, dwFlag);
2207 GDI_ReleaseObj( hDC );
2211 /***********************************************************************
2212 * GetAspectRatioFilterEx (GDI.486)
2214 BOOL16 WINAPI GetAspectRatioFilterEx16( HDC16 hdc, LPSIZE16 pAspectRatio )
2216 FIXME("(%04x, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2220 /***********************************************************************
2221 * GetAspectRatioFilterEx (GDI32.@)
2223 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2225 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2230 /***********************************************************************
2231 * GetCharABCWidthsA (GDI32.@)
2233 * See GetCharABCWidthsW.
2235 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2238 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
2243 if(count <= 0) return FALSE;
2245 str = HeapAlloc(GetProcessHeap(), 0, count);
2246 for(i = 0; i < count; i++)
2247 str[i] = (BYTE)(firstChar + i);
2249 wstr = FONT_mbtowc(str, count, &wlen);
2251 for(i = 0; i < wlen; i++)
2253 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2261 HeapFree(GetProcessHeap(), 0, str);
2262 HeapFree(GetProcessHeap(), 0, wstr);
2268 /******************************************************************************
2269 * GetCharABCWidthsW [GDI32.@]
2271 * Retrieves widths of characters in range.
2274 * hdc [I] Handle of device context
2275 * firstChar [I] First character in range to query
2276 * lastChar [I] Last character in range to query
2277 * abc [O] Address of character-width structure
2280 * Only works with TrueType fonts
2286 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2289 DC *dc = DC_GetDCPtr(hdc);
2293 if (!dc) return FALSE;
2296 ret = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
2302 /* convert device units to logical */
2303 for( i = firstChar; i <= lastChar; i++, abc++ ) {
2304 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2305 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2306 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2311 GDI_ReleaseObj(hdc);
2316 /******************************************************************************
2317 * GetCharABCWidthsI [GDI32.@]
2319 * Retrieves widths of characters in range.
2322 * hdc [I] Handle of device context
2323 * firstChar [I] First glyphs in range to query
2324 * count [I] Last glyphs in range to query
2325 * pgi [i] Array of glyphs to query
2326 * abc [O] Address of character-width structure
2329 * Only works with TrueType fonts
2335 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2336 LPWORD pgi, LPABC abc)
2338 DC *dc = DC_GetDCPtr(hdc);
2342 if (!dc) return FALSE;
2345 ret = WineEngGetCharABCWidthsI( dc->gdiFont, firstChar, count, pgi, abc );
2351 /* convert device units to logical */
2352 for( i = firstChar; i <= count; 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 * GetGlyphOutlineA (GDI32.@)
2368 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2369 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2370 LPVOID lpBuffer, const MAT2 *lpmat2 )
2376 if(!(fuFormat & GGO_GLYPH_INDEX)) {
2379 if(uChar > 0xff) { /* but, 2 bytes character only */
2381 mbchs[0] = (uChar & 0xff00) >> 8;
2382 mbchs[1] = (uChar & 0xff);
2385 mbchs[0] = (uChar & 0xff);
2387 p = FONT_mbtowc(mbchs, len, NULL);
2391 ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
2393 HeapFree(GetProcessHeap(), 0, p);
2397 /***********************************************************************
2398 * GetGlyphOutlineW (GDI32.@)
2400 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2401 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2402 LPVOID lpBuffer, const MAT2 *lpmat2 )
2404 DC *dc = DC_GetDCPtr(hdc);
2407 TRACE("(%p, %04x, %04x, %p, %ld, %p, %p)\n",
2408 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2410 if(!dc) return GDI_ERROR;
2413 ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
2414 cbBuffer, lpBuffer, lpmat2);
2418 GDI_ReleaseObj(hdc);
2423 /***********************************************************************
2424 * CreateScalableFontResourceA (GDI32.@)
2426 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2427 LPCSTR lpszResourceFile,
2428 LPCSTR lpszFontFile,
2429 LPCSTR lpszCurrentPath )
2433 /* fHidden=1 - only visible for the calling app, read-only, not
2434 * enumbered with EnumFonts/EnumFontFamilies
2435 * lpszCurrentPath can be NULL
2437 FIXME("(%ld,%s,%s,%s): stub\n",
2438 fHidden, debugstr_a(lpszResourceFile), debugstr_a(lpszFontFile),
2439 debugstr_a(lpszCurrentPath) );
2441 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2442 if ((f = CreateFileA(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2444 SetLastError(ERROR_FILE_EXISTS);
2447 return FALSE; /* create failed */
2450 /***********************************************************************
2451 * CreateScalableFontResourceW (GDI32.@)
2453 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2454 LPCWSTR lpszResourceFile,
2455 LPCWSTR lpszFontFile,
2456 LPCWSTR lpszCurrentPath )
2458 FIXME("(%ld,%p,%p,%p): stub\n",
2459 fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
2460 return FALSE; /* create failed */
2463 /*************************************************************************
2464 * GetKerningPairsA (GDI32.@)
2466 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2467 LPKERNINGPAIR lpKerningPairs )
2469 return GetKerningPairsW( hDC, cPairs, lpKerningPairs );
2473 /*************************************************************************
2474 * GetKerningPairsW (GDI32.@)
2476 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2477 LPKERNINGPAIR lpKerningPairs )
2480 FIXME("(%p,%ld,%p): almost empty stub!\n", hDC, cPairs, lpKerningPairs);
2482 if(!lpKerningPairs) /* return the number of kerning pairs */
2485 for (i = 0; i < cPairs; i++)
2486 lpKerningPairs[i].iKernAmount = 0;
2490 /*************************************************************************
2491 * TranslateCharsetInfo [GDI32.@]
2493 * Fills a CHARSETINFO structure for a character set, code page, or
2494 * font. This allows making the correspondance between different labelings
2495 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2496 * of the same encoding.
2498 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2499 * only one codepage should be set in *lpSrc.
2502 * TRUE on success, FALSE on failure.
2505 BOOL WINAPI TranslateCharsetInfo(
2506 LPDWORD lpSrc, /* [in]
2507 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2508 if flags == TCI_SRCCHARSET: a character set value
2509 if flags == TCI_SRCCODEPAGE: a code page value
2511 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2512 DWORD flags /* [in] determines interpretation of lpSrc */)
2516 case TCI_SRCFONTSIG:
2517 while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
2519 case TCI_SRCCODEPAGE:
2520 while ((UINT) (lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
2522 case TCI_SRCCHARSET:
2523 while ((UINT) (lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
2528 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2529 memcpy(lpCs, &FONT_tci[index], sizeof(CHARSETINFO));
2533 /*************************************************************************
2534 * GetFontLanguageInfo (GDI32.@)
2536 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2538 FONTSIGNATURE fontsig;
2539 static const DWORD GCP_DBCS_MASK=0x003F0000,
2540 GCP_DIACRITIC_MASK=0x00000000,
2541 FLI_GLYPHS_MASK=0x00000000,
2542 GCP_GLYPHSHAPE_MASK=0x00000040,
2543 GCP_KASHIDA_MASK=0x00000000,
2544 GCP_LIGATE_MASK=0x00000000,
2545 GCP_USEKERNING_MASK=0x00000000,
2546 GCP_REORDER_MASK=0x00000060;
2550 GetTextCharsetInfo( hdc, &fontsig, 0 );
2551 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2553 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2556 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2557 result|=GCP_DIACRITIC;
2559 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2562 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2563 result|=GCP_GLYPHSHAPE;
2565 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2566 result|=GCP_KASHIDA;
2568 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2571 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2572 result|=GCP_USEKERNING;
2574 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2575 if( GetTextAlign( hdc) & TA_RTLREADING )
2576 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2577 result|=GCP_REORDER;
2583 /*************************************************************************
2584 * GetFontData [GDI32.@]
2586 * Retrieve data for TrueType font.
2590 * success: Number of bytes returned
2591 * failure: GDI_ERROR
2595 * Calls SetLastError()
2598 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2599 LPVOID buffer, DWORD length)
2601 DC *dc = DC_GetDCPtr(hdc);
2602 DWORD ret = GDI_ERROR;
2604 if(!dc) return GDI_ERROR;
2607 ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2609 GDI_ReleaseObj(hdc);
2613 /*************************************************************************
2614 * GetGlyphIndicesA [GDI32.@]
2616 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2617 LPWORD pgi, DWORD flags)
2623 TRACE("(%p, %s, %d, %p, 0x%lx)\n",
2624 hdc, debugstr_an(lpstr, count), count, pgi, flags);
2626 lpstrW = FONT_mbtowc(lpstr, count, &countW);
2627 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2628 HeapFree(GetProcessHeap(), 0, lpstrW);
2633 /*************************************************************************
2634 * GetGlyphIndicesW [GDI32.@]
2636 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2637 LPWORD pgi, DWORD flags)
2639 DC *dc = DC_GetDCPtr(hdc);
2640 DWORD ret = GDI_ERROR;
2642 TRACE("(%p, %s, %d, %p, 0x%lx)\n",
2643 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2645 if(!dc) return GDI_ERROR;
2648 ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2650 GDI_ReleaseObj(hdc);
2654 /*************************************************************************
2655 * GetCharacterPlacementA [GDI32.@]
2657 * See GetCharacterPlacementW.
2660 * the web browser control of ie4 calls this with dwFlags=0
2663 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2664 INT nMaxExtent, GCP_RESULTSA *lpResults,
2669 GCP_RESULTSW resultsW;
2672 TRACE("%s, %d, %d, 0x%08lx\n",
2673 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2675 /* both structs are equal in size */
2676 memcpy(&resultsW, lpResults, sizeof(resultsW));
2678 lpStringW = FONT_mbtowc(lpString, uCount, &uCountW);
2679 if(lpResults->lpOutString)
2680 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2682 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2684 lpResults->nGlyphs = resultsW.nGlyphs;
2685 lpResults->nMaxFit = resultsW.nMaxFit;
2687 if(lpResults->lpOutString) {
2688 WideCharToMultiByte(CP_ACP, 0, resultsW.lpOutString, uCountW,
2689 lpResults->lpOutString, uCount, NULL, NULL );
2692 HeapFree(GetProcessHeap(), 0, lpStringW);
2693 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2698 /*************************************************************************
2699 * GetCharacterPlacementW [GDI32.@]
2701 * Retrieve information about a string. This includes the width, reordering,
2702 * Glyphing and so on.
2706 * The width and height of the string if successful, 0 if failed.
2710 * All flags except GCP_REORDER are not yet implemented.
2711 * Reordering is not 100% complient to the Windows BiDi method.
2712 * Caret positioning is not yet implemented for BiDi.
2713 * Classes are not yet implemented.
2717 GetCharacterPlacementW(
2718 HDC hdc, /* [in] Device context for which the rendering is to be done */
2719 LPCWSTR lpString, /* [in] The string for which information is to be returned */
2720 INT uCount, /* [in] Number of WORDS in string. */
2721 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
2722 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2723 DWORD dwFlags /* [in] Flags specifying how to process the string */
2730 TRACE("%s, %d, %d, 0x%08lx\n",
2731 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2733 TRACE("lStructSize=%ld, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2734 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2735 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2736 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2737 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2739 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08lx ignored\n", dwFlags);
2740 if(lpResults->lpClass) FIXME("classes not implemented\n");
2741 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2742 FIXME("Caret positions for complex scripts not implemented\n");
2744 nSet = (UINT)uCount;
2745 if(nSet > lpResults->nGlyphs)
2746 nSet = lpResults->nGlyphs;
2748 /* return number of initialized fields */
2749 lpResults->nGlyphs = nSet;
2751 if((dwFlags&GCP_REORDER)==0 || !BidiAvail)
2753 /* Treat the case where no special handling was requested in a fastpath way */
2754 /* copy will do if the GCP_REORDER flag is not set */
2755 if(lpResults->lpOutString)
2756 memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
2758 if(lpResults->lpOrder)
2760 for(i = 0; i < nSet; i++)
2761 lpResults->lpOrder[i] = i;
2765 BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
2766 nSet, lpResults->lpOrder );
2769 /* FIXME: Will use the placement chars */
2770 if (lpResults->lpDx)
2773 for (i = 0; i < nSet; i++)
2775 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
2776 lpResults->lpDx[i]= c;
2780 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
2784 lpResults->lpCaretPos[0] = 0;
2785 for (i = 1; i < nSet; i++)
2786 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
2787 lpResults->lpCaretPos[i] = (pos += size.cx);
2790 if(lpResults->lpGlyphs)
2791 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
2793 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
2794 ret = MAKELONG(size.cx, size.cy);
2799 /*************************************************************************
2800 * GetCharABCWidthsFloatA [GDI32.@]
2802 * See GetCharABCWidthsFloatW.
2804 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
2806 INT i, wlen, count = (INT)(last - first + 1);
2811 if (count <= 0) return FALSE;
2813 str = HeapAlloc(GetProcessHeap(), 0, count);
2815 for(i = 0; i < count; i++)
2816 str[i] = (BYTE)(first + i);
2818 wstr = FONT_mbtowc(str, count, &wlen);
2820 for (i = 0; i < wlen; i++)
2822 if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
2830 HeapFree( GetProcessHeap(), 0, str );
2831 HeapFree( GetProcessHeap(), 0, wstr );
2836 /*************************************************************************
2837 * GetCharABCWidthsFloatW [GDI32.@]
2839 * Retrieves widths of a range of characters.
2842 * hdc [I] Handle to device context.
2843 * first [I] First character in range to query.
2844 * last [I] Last character in range to query.
2845 * abcf [O] Array of LPABCFLOAT structures.
2852 * Only works with TrueType fonts. It also doesn't return real
2853 * floats but converted integers because it's implemented on
2854 * top of GetCharABCWidthsW.
2856 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
2859 unsigned int i, size = sizeof(ABC) * (last - first + 1);
2862 TRACE("%p, %d, %d, %p - partial stub\n", hdc, first, last, abcf);
2864 abc = HeapAlloc( GetProcessHeap(), 0, size );
2865 if (!abc) return FALSE;
2867 ret = GetCharABCWidthsW( hdc, first, last, abc );
2870 for (i = first; i <= last; i++, abc++, abcf++)
2872 abcf->abcfA = abc->abcA;
2873 abcf->abcfB = abc->abcB;
2874 abcf->abcfC = abc->abcC;
2877 HeapFree( GetProcessHeap(), 0, abc );
2881 /*************************************************************************
2882 * GetCharWidthFloatA [GDI32.@]
2884 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
2885 UINT iLastChar, PFLOAT pxBuffer)
2887 FIXME_(gdi)("GetCharWidthFloatA, stub\n");
2891 /*************************************************************************
2892 * GetCharWidthFloatW [GDI32.@]
2894 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
2895 UINT iLastChar, PFLOAT pxBuffer)
2897 FIXME_(gdi)("GetCharWidthFloatW, stub\n");
2902 /***********************************************************************
2904 * Font Resource API *
2906 ***********************************************************************/
2908 /***********************************************************************
2909 * AddFontResourceA (GDI32.@)
2911 INT WINAPI AddFontResourceA( LPCSTR str )
2913 return AddFontResourceExA( str, 0, NULL);
2916 /***********************************************************************
2917 * AddFontResourceW (GDI32.@)
2919 INT WINAPI AddFontResourceW( LPCWSTR str )
2921 return AddFontResourceExW(str, 0, NULL);
2925 /***********************************************************************
2926 * AddFontResourceExA (GDI32.@)
2928 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
2930 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
2931 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2934 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
2935 ret = AddFontResourceExW(strW, fl, pdv);
2936 HeapFree(GetProcessHeap(), 0, strW);
2940 /***********************************************************************
2941 * AddFontResourceExW (GDI32.@)
2943 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
2945 return WineEngAddFontResourceEx(str, fl, pdv);
2948 /***********************************************************************
2949 * RemoveFontResourceA (GDI32.@)
2951 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
2953 return RemoveFontResourceExA(str, 0, 0);
2956 /***********************************************************************
2957 * RemoveFontResourceW (GDI32.@)
2959 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
2961 return RemoveFontResourceExW(str, 0, 0);
2964 /***********************************************************************
2965 * AddFontMemResourceEx (GDI32.@)
2967 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
2969 FIXME("(%p,%08lx,%p,%p): stub\n", pbFont, cbFont, pdv, pcFonts);
2973 /***********************************************************************
2974 * RemoveFontResourceExA (GDI32.@)
2976 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
2978 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
2979 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2982 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
2983 ret = RemoveFontResourceExW(strW, fl, pdv);
2984 HeapFree(GetProcessHeap(), 0, strW);
2988 /***********************************************************************
2989 * RemoveFontResourceExW (GDI32.@)
2991 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
2993 return WineEngRemoveFontResourceEx(str, fl, pdv);
2996 /***********************************************************************
2997 * GetTextCharset (GDI32.@)
2999 UINT WINAPI GetTextCharset(HDC hdc)
3001 /* MSDN docs say this is equivalent */
3002 return GetTextCharsetInfo(hdc, NULL, 0);
3005 /***********************************************************************
3006 * GetTextCharsetInfo (GDI32.@)
3008 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3010 UINT ret = DEFAULT_CHARSET;
3011 DC *dc = DC_GetDCPtr(hdc);
3016 ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
3018 GDI_ReleaseObj(hdc);
3021 if (ret == DEFAULT_CHARSET && fs)
3022 memset(fs, 0, sizeof(FONTSIGNATURE));
3026 /***********************************************************************
3027 * GdiGetCharDimensions (GDI32.@)
3029 * Gets the average width of the characters in the English alphabet.
3032 * hdc [I] Handle to the device context to measure on.
3033 * lptm [O] Pointer to memory to store the text metrics into.
3034 * height [O] On exit, the maximum height of characters in the English alphabet.
3037 * The average width of characters in the English alphabet.
3040 * This function is used by the dialog manager to get the size of a dialog
3041 * unit. It should also be used by other pieces of code that need to know
3042 * the size of a dialog unit in logical units without having access to the
3043 * window handle of the dialog.
3044 * Windows caches the font metrics from this function, but we don't and
3045 * there doesn't appear to be an immediate advantage to do so.
3048 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3050 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3053 static const WCHAR alphabet[] = {
3054 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3055 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3056 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3058 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3060 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3062 if (height) *height = sz.cy;
3063 return (sz.cx / 26 + 1) / 2;
3066 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3068 FIXME("(%d): stub\n", fEnableEUDC);