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"
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( (const LOGFONTW *)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( (const LOGFONTW *)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((const TEXTMETRICW *)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 */
1056 return GetTextExtentExPointW(hdc, str, count, 0, NULL, NULL, size);
1059 /***********************************************************************
1060 * GetTextExtentPointI [GDI32.@]
1062 * Computes width and height of the array of glyph indices.
1068 BOOL WINAPI GetTextExtentPointI(
1069 HDC hdc, /* [in] Handle of device context */
1070 const WORD *indices, /* [in] Address of glyph index array */
1071 INT count, /* [in] Number of glyphs in array */
1072 LPSIZE size) /* [out] Address of structure for string size */
1075 DC * dc = DC_GetDCPtr( hdc );
1076 if (!dc) return FALSE;
1079 ret = WineEngGetTextExtentPointI(dc->gdiFont, indices, count, size);
1080 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1081 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1082 size->cx += count * dc->charExtra;
1084 else if(dc->funcs->pGetTextExtentExPoint) {
1085 FIXME("calling GetTextExtentExPoint\n");
1086 ret = dc->funcs->pGetTextExtentExPoint( dc->physDev, (LPCWSTR)indices,
1087 count, 0, NULL, NULL, size );
1090 GDI_ReleaseObj( hdc );
1092 TRACE("(%p %p %d %p): returning %ld x %ld\n",
1093 hdc, indices, count, size, size->cx, size->cy );
1098 /***********************************************************************
1099 * GetTextExtentPointA (GDI32.@)
1101 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
1104 TRACE("not bug compatible.\n");
1105 return GetTextExtentPoint32A( hdc, str, count, size );
1108 /***********************************************************************
1109 * GetTextExtentPointW (GDI32.@)
1111 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1114 TRACE("not bug compatible.\n");
1115 return GetTextExtentPoint32W( hdc, str, count, size );
1119 /***********************************************************************
1120 * GetTextExtentExPointA (GDI32.@)
1122 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1123 INT maxExt, LPINT lpnFit,
1124 LPINT alpDx, LPSIZE size )
1132 NULL == (walpDx = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT))))
1135 p = FONT_mbtowc(str, count, &wlen);
1136 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
1139 INT n = lpnFit ? *lpnFit : wlen;
1141 for(i = 0, j = 0; i < n; i++, j++)
1143 alpDx[j] = walpDx[i];
1144 if (IsDBCSLeadByte(str[j])) alpDx[++j] = walpDx[i];
1147 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1148 HeapFree( GetProcessHeap(), 0, p );
1149 HeapFree( GetProcessHeap(), 0, walpDx );
1154 /***********************************************************************
1155 * GetTextExtentExPointW (GDI32.@)
1157 * Return the size of the string as it would be if it was output properly by
1160 * This should include
1161 * - Intercharacter spacing
1162 * - justification spacing (not yet done)
1163 * - kerning? see below
1165 * Kerning. Since kerning would be carried out by the rendering code it should
1166 * be done by the driver. However they don't support it yet. Also I am not
1167 * yet persuaded that (certainly under Win95) any kerning is actually done.
1169 * str: According to MSDN this should be null-terminated. That is not true; a
1170 * null will not terminate it early.
1171 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1172 * than count. I have seen it be either the size of the full string or
1173 * 1 less than the size of the full string. I have not seen it bear any
1174 * resemblance to the portion that would fit.
1175 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1176 * trailing intercharacter spacing and any trailing justification.
1179 * Currently we do this by measuring each character etc. We should do it by
1180 * passing the request to the driver, perhaps by extending the
1181 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1182 * thinking about kerning issues and rounding issues in the justification.
1185 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1186 INT maxExt, LPINT lpnFit,
1187 LPINT alpDx, LPSIZE size )
1194 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1196 dc = DC_GetDCPtr(hdc);
1200 /* If we need to calculate nFit, then we need the partial extents even if
1201 the user hasn't provided us with an array. */
1204 dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]);
1207 GDI_ReleaseObj(hdc);
1208 SetLastError(ERROR_OUTOFMEMORY);
1216 ret = WineEngGetTextExtentExPoint(dc->gdiFont, str, count,
1217 0, NULL, dxs, size);
1218 else if (dc->funcs->pGetTextExtentExPoint)
1219 ret = dc->funcs->pGetTextExtentExPoint(dc->physDev, str, count,
1220 0, NULL, dxs, size);
1222 /* Perform device size to world size transformations. */
1225 INT extra = dc->charExtra, breakRem = dc->breakRem;
1230 for (i = 0; i < count; ++i)
1232 dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
1233 dxs[i] += (i+1) * extra + breakRem;
1234 if (dxs[i] <= maxExt)
1238 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1239 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1240 size->cx += count * extra + breakRem;
1247 HeapFree(GetProcessHeap(), 0, dxs);
1249 GDI_ReleaseObj( hdc );
1251 TRACE("returning %d %ld x %ld\n",nFit,size->cx,size->cy);
1255 /***********************************************************************
1256 * GetTextMetricsA (GDI32.@)
1258 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1262 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1263 FONT_TextMetricWToA( &tm32, metrics );
1267 /***********************************************************************
1268 * GetTextMetricsW (GDI32.@)
1270 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1273 DC * dc = DC_GetDCPtr( hdc );
1274 if (!dc) return FALSE;
1277 ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1278 else if (dc->funcs->pGetTextMetrics)
1279 ret = dc->funcs->pGetTextMetrics( dc->physDev, metrics );
1283 /* device layer returns values in device units
1284 * therefore we have to convert them to logical */
1286 #define WDPTOLP(x) ((x<0)? \
1287 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1288 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1289 #define HDPTOLP(y) ((y<0)? \
1290 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1291 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1293 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1294 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1295 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1296 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1297 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1298 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1299 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1300 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1304 TRACE("text metrics:\n"
1305 " Weight = %03li\t FirstChar = %i\t AveCharWidth = %li\n"
1306 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %li\n"
1307 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %li\n"
1308 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1309 " PitchAndFamily = %02x\n"
1310 " --------------------\n"
1311 " InternalLeading = %li\n"
1315 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1316 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1317 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1318 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1319 metrics->tmPitchAndFamily,
1320 metrics->tmInternalLeading,
1323 metrics->tmHeight );
1325 GDI_ReleaseObj( hdc );
1330 /***********************************************************************
1331 * GetOutlineTextMetrics [GDI.308] Gets metrics for TrueType fonts.
1334 * lpOTM should be LPOUTLINETEXTMETRIC
1337 * Success: Non-zero or size of required buffer
1340 UINT16 WINAPI GetOutlineTextMetrics16(
1341 HDC16 hdc, /* [in] Handle of device context */
1342 UINT16 cbData, /* [in] Size of metric data array */
1343 LPOUTLINETEXTMETRIC16 lpOTM) /* [out] Address of metric data array */
1345 FIXME("(%04x,%04x,%p): stub\n", hdc,cbData,lpOTM);
1350 /***********************************************************************
1351 * GetOutlineTextMetricsA (GDI32.@)
1352 * Gets metrics for TrueType fonts.
1355 * If the supplied buffer isn't big enough Windows partially fills it up to
1356 * its given length and returns that length.
1359 * Success: Non-zero or size of required buffer
1362 UINT WINAPI GetOutlineTextMetricsA(
1363 HDC hdc, /* [in] Handle of device context */
1364 UINT cbData, /* [in] Size of metric data array */
1365 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1367 char buf[512], *ptr;
1369 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1370 OUTLINETEXTMETRICA *output = lpOTM;
1373 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1375 if(ret > sizeof(buf))
1376 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1377 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1379 needed = sizeof(OUTLINETEXTMETRICA);
1380 if(lpOTMW->otmpFamilyName)
1381 needed += WideCharToMultiByte(CP_ACP, 0,
1382 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1383 NULL, 0, NULL, NULL);
1384 if(lpOTMW->otmpFaceName)
1385 needed += WideCharToMultiByte(CP_ACP, 0,
1386 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1387 NULL, 0, NULL, NULL);
1388 if(lpOTMW->otmpStyleName)
1389 needed += WideCharToMultiByte(CP_ACP, 0,
1390 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1391 NULL, 0, NULL, NULL);
1392 if(lpOTMW->otmpFullName)
1393 needed += WideCharToMultiByte(CP_ACP, 0,
1394 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1395 NULL, 0, NULL, NULL);
1402 TRACE("needed = %d\n", needed);
1404 /* Since the supplied buffer isn't big enough, we'll alloc one
1405 that is and memcpy the first cbData bytes into the lpOTM at
1407 output = HeapAlloc(GetProcessHeap(), 0, needed);
1409 ret = output->otmSize = min(needed, cbData);
1410 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1411 output->otmFiller = 0;
1412 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1413 output->otmfsSelection = lpOTMW->otmfsSelection;
1414 output->otmfsType = lpOTMW->otmfsType;
1415 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1416 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1417 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1418 output->otmEMSquare = lpOTMW->otmEMSquare;
1419 output->otmAscent = lpOTMW->otmAscent;
1420 output->otmDescent = lpOTMW->otmDescent;
1421 output->otmLineGap = lpOTMW->otmLineGap;
1422 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1423 output->otmsXHeight = lpOTMW->otmsXHeight;
1424 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1425 output->otmMacAscent = lpOTMW->otmMacAscent;
1426 output->otmMacDescent = lpOTMW->otmMacDescent;
1427 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1428 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1429 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1430 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1431 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1432 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1433 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1434 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1435 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1436 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1439 ptr = (char*)(output + 1);
1440 left = needed - sizeof(*output);
1442 if(lpOTMW->otmpFamilyName) {
1443 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1444 len = WideCharToMultiByte(CP_ACP, 0,
1445 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1446 ptr, left, NULL, NULL);
1450 output->otmpFamilyName = 0;
1452 if(lpOTMW->otmpFaceName) {
1453 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1454 len = WideCharToMultiByte(CP_ACP, 0,
1455 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1456 ptr, left, NULL, NULL);
1460 output->otmpFaceName = 0;
1462 if(lpOTMW->otmpStyleName) {
1463 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1464 len = WideCharToMultiByte(CP_ACP, 0,
1465 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1466 ptr, left, NULL, NULL);
1470 output->otmpStyleName = 0;
1472 if(lpOTMW->otmpFullName) {
1473 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1474 len = WideCharToMultiByte(CP_ACP, 0,
1475 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1476 ptr, left, NULL, NULL);
1479 output->otmpFullName = 0;
1483 if(output != lpOTM) {
1484 memcpy(lpOTM, output, cbData);
1485 HeapFree(GetProcessHeap(), 0, output);
1487 /* check if the string offsets really fit into the provided size */
1488 /* FIXME: should we check string length as well? */
1489 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1490 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1492 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1493 lpOTM->otmpFaceName = 0; /* doesn't fit */
1495 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1496 lpOTM->otmpStyleName = 0; /* doesn't fit */
1498 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1499 lpOTM->otmpFullName = 0; /* doesn't fit */
1503 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1504 HeapFree(GetProcessHeap(), 0, lpOTMW);
1510 /***********************************************************************
1511 * GetOutlineTextMetricsW [GDI32.@]
1513 UINT WINAPI GetOutlineTextMetricsW(
1514 HDC hdc, /* [in] Handle of device context */
1515 UINT cbData, /* [in] Size of metric data array */
1516 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1518 DC *dc = DC_GetDCPtr( hdc );
1519 OUTLINETEXTMETRICW *output = lpOTM;
1522 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1526 ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, output);
1529 output = HeapAlloc(GetProcessHeap(), 0, ret);
1530 WineEngGetOutlineTextMetrics(dc->gdiFont, ret, output);
1533 #define WDPTOLP(x) ((x<0)? \
1534 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1535 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1536 #define HDPTOLP(y) ((y<0)? \
1537 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1538 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1540 output->otmTextMetrics.tmHeight = HDPTOLP(output->otmTextMetrics.tmHeight);
1541 output->otmTextMetrics.tmAscent = HDPTOLP(output->otmTextMetrics.tmAscent);
1542 output->otmTextMetrics.tmDescent = HDPTOLP(output->otmTextMetrics.tmDescent);
1543 output->otmTextMetrics.tmInternalLeading = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1544 output->otmTextMetrics.tmExternalLeading = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1545 output->otmTextMetrics.tmAveCharWidth = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1546 output->otmTextMetrics.tmMaxCharWidth = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1547 output->otmTextMetrics.tmOverhang = WDPTOLP(output->otmTextMetrics.tmOverhang);
1548 output->otmAscent = HDPTOLP(output->otmAscent);
1549 output->otmDescent = HDPTOLP(output->otmDescent);
1550 output->otmLineGap = HDPTOLP(output->otmLineGap);
1551 output->otmsCapEmHeight = HDPTOLP(output->otmsCapEmHeight);
1552 output->otmsXHeight = HDPTOLP(output->otmsXHeight);
1553 output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1554 output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1555 output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1556 output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1557 output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1558 output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1559 output->otmMacLineGap = HDPTOLP(output->otmMacLineGap);
1560 output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1561 output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1562 output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1563 output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1564 output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1565 output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1566 output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1567 output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1568 output->otmsStrikeoutSize = HDPTOLP(output->otmsStrikeoutSize);
1569 output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1570 output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1571 output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1574 if(output != lpOTM) {
1575 memcpy(lpOTM, output, cbData);
1576 HeapFree(GetProcessHeap(), 0, output);
1582 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1583 but really this should just be a return 0. */
1585 ret = sizeof(*lpOTM);
1590 memset(lpOTM, 0, ret);
1591 lpOTM->otmSize = sizeof(*lpOTM);
1592 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1594 Further fill of the structure not implemented,
1595 Needs real values for the structure members
1600 GDI_ReleaseObj(hdc);
1605 /***********************************************************************
1606 * GetCharWidthW (GDI32.@)
1607 * GetCharWidth32W (GDI32.@)
1609 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1614 DC * dc = DC_GetDCPtr( hdc );
1615 if (!dc) return FALSE;
1618 ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1619 else if (dc->funcs->pGetCharWidth)
1620 ret = dc->funcs->pGetCharWidth( dc->physDev, firstChar, lastChar, buffer);
1624 /* convert device units to logical */
1625 for( i = firstChar; i <= lastChar; i++, buffer++ )
1626 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1629 GDI_ReleaseObj( hdc );
1634 /***********************************************************************
1635 * GetCharWidthA (GDI32.@)
1636 * GetCharWidth32A (GDI32.@)
1638 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1641 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1646 if(count <= 0) return FALSE;
1648 str = HeapAlloc(GetProcessHeap(), 0, count);
1649 for(i = 0; i < count; i++)
1650 str[i] = (BYTE)(firstChar + i);
1652 wstr = FONT_mbtowc(str, count, &wlen);
1654 for(i = 0; i < wlen; i++)
1656 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1664 HeapFree(GetProcessHeap(), 0, str);
1665 HeapFree(GetProcessHeap(), 0, wstr);
1671 /***********************************************************************
1672 * ExtTextOutA (GDI32.@)
1676 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1677 const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1684 if (flags & ETO_GLYPH_INDEX)
1685 return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
1687 p = FONT_mbtowc(str, count, &wlen);
1690 unsigned int i = 0, j = 0;
1692 lpDxW = HeapAlloc( GetProcessHeap(), 0, wlen*sizeof(INT));
1694 if(IsDBCSLeadByte(str[i])) {
1695 lpDxW[j++] = lpDx[i] + lpDx[i+1];
1698 lpDxW[j++] = lpDx[i];
1704 ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1706 HeapFree( GetProcessHeap(), 0, p );
1707 HeapFree( GetProcessHeap(), 0, lpDxW );
1712 /***********************************************************************
1713 * ExtTextOutW (GDI32.@)
1715 * Draws text using the currently selected font, background color, and text color.
1719 * x,y [I] coordinates of string
1721 * ETO_GRAYED - undocumented on MSDN
1722 * ETO_OPAQUE - use background color for fill the rectangle
1723 * ETO_CLIPPED - clipping text to the rectangle
1724 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1725 * than encoded characters. Implies ETO_IGNORELANGUAGE
1726 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1727 * Affects BiDi ordering
1728 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1729 * ETO_PDY - unimplemented
1730 * ETO_NUMERICSLATIN - unimplemented always assumed -
1731 * do not translate numbers into locale representations
1732 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1733 * lprect [I] dimensions for clipping or/and opaquing
1734 * str [I] text string
1735 * count [I] number of symbols in string
1736 * lpDx [I] optional parameter with distance between drawing characters
1742 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1743 const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1746 LPWSTR reordered_str = (LPWSTR)str;
1747 WORD *glyphs = NULL;
1748 UINT align = GetTextAlign( hdc );
1752 double cosEsc, sinEsc;
1753 INT *deltas = NULL, char_extra;
1756 BOOL done_extents = FALSE;
1757 INT width, xwidth = 0, ywidth = 0;
1759 DC * dc = DC_GetDCUpdate( hdc );
1761 if (!dc) return FALSE;
1763 if (flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY))
1764 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY unimplemented\n");
1766 if (!dc->funcs->pExtTextOut && !PATH_IsPathOpen(dc->path))
1768 GDI_ReleaseObj( hdc );
1772 type = GetObjectType(hdc);
1773 if(type == OBJ_METADC || type == OBJ_ENHMETADC)
1775 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, flags, lprect, str, count, lpDx);
1776 GDI_ReleaseObj( hdc );
1781 flags &= ~ETO_CLIPPED;
1783 if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && BidiAvail && count > 0 )
1785 reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1787 BIDI_Reorder( str, count, GCP_REORDER,
1788 ((flags&ETO_RTLREADING)!=0 || (GetTextAlign(hdc)&TA_RTLREADING)!=0)?
1789 WINE_GCPW_FORCE_RTL:WINE_GCPW_FORCE_LTR,
1790 reordered_str, count, NULL );
1792 flags |= ETO_IGNORELANGUAGE;
1795 TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc, x, y, flags,
1796 lprect, debugstr_wn(str, count), count, lpDx);
1798 if(flags & ETO_GLYPH_INDEX)
1799 glyphs = reordered_str;
1802 TRACE("rect: %ld,%ld - %ld,%ld\n", lprect->left, lprect->top, lprect->right,
1804 TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
1806 if(align & TA_UPDATECP)
1808 GetCurrentPositionEx( hdc, &pt );
1813 GetTextMetricsW(hdc, &tm);
1814 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1816 if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
1817 lf.lfEscapement = 0;
1819 if(lf.lfEscapement != 0)
1821 cosEsc = cos(lf.lfEscapement * M_PI / 1800);
1822 sinEsc = sin(lf.lfEscapement * M_PI / 1800);
1830 if(flags & (ETO_CLIPPED | ETO_OPAQUE))
1834 if(flags & ETO_GLYPH_INDEX)
1835 GetTextExtentPointI(hdc, glyphs, count, &sz);
1837 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1839 done_extents = TRUE;
1842 rc.right = x + sz.cx;
1843 rc.bottom = y + sz.cy;
1850 LPtoDP(hdc, (POINT*)&rc, 2);
1852 if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
1853 if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
1856 if ((flags & ETO_OPAQUE) && !PATH_IsPathOpen(dc->path))
1857 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1867 LPtoDP(hdc, &pt, 1);
1871 char_extra = GetTextCharacterExtra(hdc);
1873 if(char_extra || dc->breakExtra || lpDx)
1877 deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT));
1878 for(i = 0; i < count; i++)
1880 if(lpDx && (flags & ETO_PDY))
1881 deltas[i] = lpDx[i*2] + char_extra;
1883 deltas[i] = lpDx[i] + char_extra;
1886 if(flags & ETO_GLYPH_INDEX)
1887 GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
1889 GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
1891 deltas[i] = tmpsz.cx;
1894 if (!(flags & ETO_GLYPH_INDEX) && dc->breakExtra && reordered_str[i] == tm.tmBreakChar)
1896 deltas[i] = deltas[i] + dc->breakExtra;
1898 deltas[i] = INTERNAL_XWSTODS(dc, deltas[i]);
1906 if(flags & ETO_GLYPH_INDEX)
1907 GetTextExtentPointI(hdc, glyphs, count, &sz);
1909 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1910 done_extents = TRUE;
1912 width = INTERNAL_XWSTODS(dc, sz.cx);
1914 xwidth = width * cosEsc;
1915 ywidth = width * sinEsc;
1917 tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
1918 tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
1919 switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
1922 if (align & TA_UPDATECP)
1926 DPtoLP(hdc, &pt, 1);
1927 MoveToEx(hdc, pt.x, pt.y, NULL);
1939 if (align & TA_UPDATECP)
1943 DPtoLP(hdc, &pt, 1);
1944 MoveToEx(hdc, pt.x, pt.y, NULL);
1949 switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
1952 y += tm.tmAscent * cosEsc;
1953 x += tm.tmAscent * sinEsc;
1957 y -= tm.tmDescent * cosEsc;
1958 x -= tm.tmDescent * sinEsc;
1965 if (GetBkMode(hdc) != TRANSPARENT && !PATH_IsPathOpen(dc->path))
1967 if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
1969 if(!(flags & ETO_OPAQUE) || x < rc.left || x + width >= rc.right ||
1970 y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
1974 rc.right = x + width;
1975 rc.top = y - tm.tmAscent;
1976 rc.bottom = y + tm.tmDescent;
1977 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1982 if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
1984 HFONT orig_font = dc->hFont, cur_font;
1986 INT span = 0, *offsets = NULL, i;
1988 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
1989 for(i = 0; i < count; i++)
1991 WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
1992 if(cur_font != dc->hFont)
1997 offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
2002 for(j = 1; j < count; j++)
2004 GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
2005 offsets[j] = offsets[j-1] + INTERNAL_XWSTODS(dc, tmpsz.cx);
2010 for(j = 1; j < count; j++)
2011 offsets[j] = offsets[j-1] + deltas[j];
2016 if (PATH_IsPathOpen(dc->path))
2017 ret = PATH_ExtTextOut(dc, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
2018 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2019 glyphs, span, deltas ? deltas + i - span : NULL);
2021 dc->funcs->pExtTextOut(dc->physDev, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
2022 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2023 glyphs, span, deltas ? deltas + i - span : NULL);
2026 SelectObject(hdc, cur_font);
2028 glyphs[span++] = glyph;
2032 if (PATH_IsPathOpen(dc->path))
2033 ret = PATH_ExtTextOut(dc, x + (offsets ? offsets[count - span] * cosEsc : 0),
2034 y - (offsets ? offsets[count - span] * sinEsc : 0),
2035 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2036 glyphs, span, deltas ? deltas + count - span : NULL);
2038 ret = dc->funcs->pExtTextOut(dc->physDev, x + (offsets ? offsets[count - span] * cosEsc : 0),
2039 y - (offsets ? offsets[count - span] * sinEsc : 0),
2040 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2041 glyphs, span, deltas ? deltas + count - span : NULL);
2042 SelectObject(hdc, orig_font);
2043 HeapFree(GetProcessHeap(), 0, offsets);
2049 if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
2051 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2052 GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
2053 flags |= ETO_GLYPH_INDEX;
2056 if (PATH_IsPathOpen(dc->path))
2057 ret = PATH_ExtTextOut(dc, x, y, (flags & ~ETO_OPAQUE), &rc,
2058 glyphs ? glyphs : reordered_str, count, deltas);
2060 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, (flags & ~ETO_OPAQUE), &rc,
2061 glyphs ? glyphs : reordered_str, count, deltas);
2065 HeapFree(GetProcessHeap(), 0, deltas);
2066 if(glyphs != reordered_str)
2067 HeapFree(GetProcessHeap(), 0, glyphs);
2068 if(reordered_str != str)
2069 HeapFree(GetProcessHeap(), 0, reordered_str);
2071 GDI_ReleaseObj( hdc );
2073 if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2075 int underlinePos, strikeoutPos;
2076 int underlineWidth, strikeoutWidth;
2077 UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2078 OUTLINETEXTMETRICW* otm = NULL;
2083 underlineWidth = tm.tmAscent / 20 + 1;
2084 strikeoutPos = tm.tmAscent / 2;
2085 strikeoutWidth = underlineWidth;
2089 otm = HeapAlloc(GetProcessHeap(), 0, size);
2090 GetOutlineTextMetricsW(hdc, size, otm);
2091 underlinePos = otm->otmsUnderscorePosition;
2092 underlineWidth = otm->otmsUnderscoreSize;
2093 strikeoutPos = otm->otmsStrikeoutPosition;
2094 strikeoutWidth = otm->otmsStrikeoutSize;
2095 HeapFree(GetProcessHeap(), 0, otm);
2098 if (PATH_IsPathOpen(dc->path))
2102 HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2104 hbrush = SelectObject(hdc, hbrush);
2105 hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2109 pts[0].x = x - underlinePos * sinEsc;
2110 pts[0].y = y - underlinePos * cosEsc;
2111 pts[1].x = x + xwidth - underlinePos * sinEsc;
2112 pts[1].y = y - ywidth - underlinePos * cosEsc;
2113 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2114 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2115 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2116 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2117 pts[4].x = pts[0].x;
2118 pts[4].y = pts[0].y;
2119 DPtoLP(hdc, pts, 5);
2120 Polygon(hdc, pts, 5);
2125 pts[0].x = x - strikeoutPos * sinEsc;
2126 pts[0].y = y - strikeoutPos * cosEsc;
2127 pts[1].x = x + xwidth - strikeoutPos * sinEsc;
2128 pts[1].y = y - ywidth - strikeoutPos * cosEsc;
2129 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2130 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2131 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2132 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2133 pts[4].x = pts[0].x;
2134 pts[4].y = pts[0].y;
2135 DPtoLP(hdc, pts, 5);
2136 Polygon(hdc, pts, 5);
2139 SelectObject(hdc, hpen);
2140 hbrush = SelectObject(hdc, hbrush);
2141 DeleteObject(hbrush);
2145 POINT pts[2], oldpt;
2150 hpen = CreatePen(PS_SOLID, underlineWidth, GetTextColor(hdc));
2151 hpen = SelectObject(hdc, hpen);
2154 pts[1].x = x + xwidth;
2155 pts[1].y = y - ywidth;
2156 DPtoLP(hdc, pts, 2);
2157 MoveToEx(hdc, pts[0].x - underlinePos * sinEsc, pts[0].y - underlinePos * cosEsc, &oldpt);
2158 LineTo(hdc, pts[1].x - underlinePos * sinEsc, pts[1].y - underlinePos * cosEsc);
2159 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2160 DeleteObject(SelectObject(hdc, hpen));
2165 hpen = CreatePen(PS_SOLID, strikeoutWidth, GetTextColor(hdc));
2166 hpen = SelectObject(hdc, hpen);
2169 pts[1].x = x + xwidth;
2170 pts[1].y = y - ywidth;
2171 DPtoLP(hdc, pts, 2);
2172 MoveToEx(hdc, pts[0].x - strikeoutPos * sinEsc, pts[0].y - strikeoutPos * cosEsc, &oldpt);
2173 LineTo(hdc, pts[1].x - strikeoutPos * sinEsc, pts[1].y - strikeoutPos * cosEsc);
2174 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2175 DeleteObject(SelectObject(hdc, hpen));
2184 /***********************************************************************
2185 * TextOutA (GDI32.@)
2187 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2189 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2193 /***********************************************************************
2194 * TextOutW (GDI32.@)
2196 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2198 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2202 /***********************************************************************
2203 * PolyTextOutA (GDI32.@)
2207 BOOL WINAPI PolyTextOutA ( HDC hdc, /* [in] Handle to device context */
2208 PPOLYTEXTA pptxt, /* [in] Array of strings */
2209 INT cStrings ) /* [in] Number of strings in array */
2211 for (; cStrings>0; cStrings--, pptxt++)
2212 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2219 /***********************************************************************
2220 * PolyTextOutW (GDI32.@)
2222 * Draw several Strings
2228 BOOL WINAPI PolyTextOutW ( HDC hdc, /* [in] Handle to device context */
2229 PPOLYTEXTW pptxt, /* [in] Array of strings */
2230 INT cStrings ) /* [in] Number of strings in array */
2232 for (; cStrings>0; cStrings--, pptxt++)
2233 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2239 /* FIXME: all following APIs ******************************************/
2242 /***********************************************************************
2243 * SetMapperFlags (GDI32.@)
2245 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
2247 DC *dc = DC_GetDCPtr( hDC );
2250 if(dc->funcs->pSetMapperFlags)
2252 ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
2253 /* FIXME: ret is just a success flag, we should return a proper value */
2256 FIXME("(%p, 0x%08lx): stub - harmless\n", hDC, dwFlag);
2257 GDI_ReleaseObj( hDC );
2261 /***********************************************************************
2262 * GetAspectRatioFilterEx (GDI.486)
2264 BOOL16 WINAPI GetAspectRatioFilterEx16( HDC16 hdc, LPSIZE16 pAspectRatio )
2266 FIXME("(%04x, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2270 /***********************************************************************
2271 * GetAspectRatioFilterEx (GDI32.@)
2273 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2275 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2280 /***********************************************************************
2281 * GetCharABCWidthsA (GDI32.@)
2283 * See GetCharABCWidthsW.
2285 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2288 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
2293 if(count <= 0) return FALSE;
2295 str = HeapAlloc(GetProcessHeap(), 0, count);
2296 for(i = 0; i < count; i++)
2297 str[i] = (BYTE)(firstChar + i);
2299 wstr = FONT_mbtowc(str, count, &wlen);
2301 for(i = 0; i < wlen; i++)
2303 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2311 HeapFree(GetProcessHeap(), 0, str);
2312 HeapFree(GetProcessHeap(), 0, wstr);
2318 /******************************************************************************
2319 * GetCharABCWidthsW [GDI32.@]
2321 * Retrieves widths of characters in range.
2324 * hdc [I] Handle of device context
2325 * firstChar [I] First character in range to query
2326 * lastChar [I] Last character in range to query
2327 * abc [O] Address of character-width structure
2330 * Only works with TrueType fonts
2336 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2339 DC *dc = DC_GetDCPtr(hdc);
2343 if (!dc) return FALSE;
2346 ret = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
2352 /* convert device units to logical */
2353 for( i = firstChar; i <= lastChar; i++, abc++ ) {
2354 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2355 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2356 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2361 GDI_ReleaseObj(hdc);
2366 /******************************************************************************
2367 * GetCharABCWidthsI [GDI32.@]
2369 * Retrieves widths of characters in range.
2372 * hdc [I] Handle of device context
2373 * firstChar [I] First glyphs in range to query
2374 * count [I] Last glyphs in range to query
2375 * pgi [i] Array of glyphs to query
2376 * abc [O] Address of character-width structure
2379 * Only works with TrueType fonts
2385 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2386 LPWORD pgi, LPABC abc)
2388 DC *dc = DC_GetDCPtr(hdc);
2392 if (!dc) return FALSE;
2395 ret = WineEngGetCharABCWidthsI( dc->gdiFont, firstChar, count, pgi, abc );
2401 /* convert device units to logical */
2402 for( i = 0; i < count; i++, abc++ ) {
2403 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2404 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2405 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2410 GDI_ReleaseObj(hdc);
2415 /***********************************************************************
2416 * GetGlyphOutlineA (GDI32.@)
2418 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2419 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2420 LPVOID lpBuffer, const MAT2 *lpmat2 )
2426 if(!(fuFormat & GGO_GLYPH_INDEX)) {
2429 if(uChar > 0xff) { /* but, 2 bytes character only */
2431 mbchs[0] = (uChar & 0xff00) >> 8;
2432 mbchs[1] = (uChar & 0xff);
2435 mbchs[0] = (uChar & 0xff);
2437 p = FONT_mbtowc(mbchs, len, NULL);
2441 ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
2443 HeapFree(GetProcessHeap(), 0, p);
2447 /***********************************************************************
2448 * GetGlyphOutlineW (GDI32.@)
2450 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2451 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2452 LPVOID lpBuffer, const MAT2 *lpmat2 )
2454 DC *dc = DC_GetDCPtr(hdc);
2457 TRACE("(%p, %04x, %04x, %p, %ld, %p, %p)\n",
2458 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2460 if(!dc) return GDI_ERROR;
2463 ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
2464 cbBuffer, lpBuffer, lpmat2);
2468 GDI_ReleaseObj(hdc);
2473 /***********************************************************************
2474 * CreateScalableFontResourceA (GDI32.@)
2476 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2477 LPCSTR lpszResourceFile,
2478 LPCSTR lpszFontFile,
2479 LPCSTR lpszCurrentPath )
2483 /* fHidden=1 - only visible for the calling app, read-only, not
2484 * enumbered with EnumFonts/EnumFontFamilies
2485 * lpszCurrentPath can be NULL
2487 FIXME("(%ld,%s,%s,%s): stub\n",
2488 fHidden, debugstr_a(lpszResourceFile), debugstr_a(lpszFontFile),
2489 debugstr_a(lpszCurrentPath) );
2491 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2492 if ((f = CreateFileA(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2494 SetLastError(ERROR_FILE_EXISTS);
2497 return FALSE; /* create failed */
2500 /***********************************************************************
2501 * CreateScalableFontResourceW (GDI32.@)
2503 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2504 LPCWSTR lpszResourceFile,
2505 LPCWSTR lpszFontFile,
2506 LPCWSTR lpszCurrentPath )
2508 FIXME("(%ld,%p,%p,%p): stub\n",
2509 fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
2510 return FALSE; /* create failed */
2513 /*************************************************************************
2514 * GetKerningPairsA (GDI32.@)
2516 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2517 LPKERNINGPAIR kern_pairA )
2522 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2523 KERNINGPAIR *kern_pairW;
2525 if (!cPairs && kern_pairA)
2527 SetLastError(ERROR_INVALID_PARAMETER);
2531 charset = GetTextCharset(hDC);
2532 if (!TranslateCharsetInfo((DWORD *)charset, &csi, TCI_SRCCHARSET))
2534 FIXME("Can't find codepage for charset %d\n", charset);
2537 if (!GetCPInfo(csi.ciACP, &cpi))
2539 FIXME("Can't find codepage %u info\n", csi.ciACP);
2542 TRACE("charset %d => codepage %u\n", charset, csi.ciACP);
2544 total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2545 if (!total_kern_pairs) return 0;
2547 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2548 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2550 for (i = 0; i < total_kern_pairs; i++)
2554 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2557 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2560 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2565 if (kern_pairs_copied >= cPairs) break;
2567 kern_pairA->wFirst = (BYTE)first;
2568 kern_pairA->wSecond = (BYTE)second;
2569 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2572 kern_pairs_copied++;
2575 HeapFree(GetProcessHeap(), 0, kern_pairW);
2577 return kern_pairs_copied;
2580 /*************************************************************************
2581 * GetKerningPairsW (GDI32.@)
2583 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2584 LPKERNINGPAIR lpKerningPairs )
2589 TRACE("(%p,%ld,%p)\n", hDC, cPairs, lpKerningPairs);
2591 if (!cPairs && lpKerningPairs)
2593 SetLastError(ERROR_INVALID_PARAMETER);
2597 dc = DC_GetDCPtr(hDC);
2601 ret = WineEngGetKerningPairs(dc->gdiFont, cPairs, lpKerningPairs);
2603 GDI_ReleaseObj(hDC);
2607 /*************************************************************************
2608 * TranslateCharsetInfo [GDI32.@]
2610 * Fills a CHARSETINFO structure for a character set, code page, or
2611 * font. This allows making the correspondance between different labelings
2612 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2613 * of the same encoding.
2615 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2616 * only one codepage should be set in *lpSrc.
2619 * TRUE on success, FALSE on failure.
2622 BOOL WINAPI TranslateCharsetInfo(
2623 LPDWORD lpSrc, /* [in]
2624 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2625 if flags == TCI_SRCCHARSET: a character set value
2626 if flags == TCI_SRCCODEPAGE: a code page value
2628 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2629 DWORD flags /* [in] determines interpretation of lpSrc */)
2633 case TCI_SRCFONTSIG:
2634 while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
2636 case TCI_SRCCODEPAGE:
2637 while ((UINT) (lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
2639 case TCI_SRCCHARSET:
2640 while ((UINT) (lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
2645 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2646 memcpy(lpCs, &FONT_tci[index], sizeof(CHARSETINFO));
2650 /*************************************************************************
2651 * GetFontLanguageInfo (GDI32.@)
2653 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2655 FONTSIGNATURE fontsig;
2656 static const DWORD GCP_DBCS_MASK=0x003F0000,
2657 GCP_DIACRITIC_MASK=0x00000000,
2658 FLI_GLYPHS_MASK=0x00000000,
2659 GCP_GLYPHSHAPE_MASK=0x00000040,
2660 GCP_KASHIDA_MASK=0x00000000,
2661 GCP_LIGATE_MASK=0x00000000,
2662 GCP_USEKERNING_MASK=0x00000000,
2663 GCP_REORDER_MASK=0x00000060;
2667 GetTextCharsetInfo( hdc, &fontsig, 0 );
2668 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2670 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2673 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2674 result|=GCP_DIACRITIC;
2676 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2679 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2680 result|=GCP_GLYPHSHAPE;
2682 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2683 result|=GCP_KASHIDA;
2685 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2688 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2689 result|=GCP_USEKERNING;
2691 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2692 if( GetTextAlign( hdc) & TA_RTLREADING )
2693 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2694 result|=GCP_REORDER;
2700 /*************************************************************************
2701 * GetFontData [GDI32.@]
2703 * Retrieve data for TrueType font.
2707 * success: Number of bytes returned
2708 * failure: GDI_ERROR
2712 * Calls SetLastError()
2715 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2716 LPVOID buffer, DWORD length)
2718 DC *dc = DC_GetDCPtr(hdc);
2719 DWORD ret = GDI_ERROR;
2721 if(!dc) return GDI_ERROR;
2724 ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2726 GDI_ReleaseObj(hdc);
2730 /*************************************************************************
2731 * GetGlyphIndicesA [GDI32.@]
2733 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2734 LPWORD pgi, DWORD flags)
2740 TRACE("(%p, %s, %d, %p, 0x%lx)\n",
2741 hdc, debugstr_an(lpstr, count), count, pgi, flags);
2743 lpstrW = FONT_mbtowc(lpstr, count, &countW);
2744 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2745 HeapFree(GetProcessHeap(), 0, lpstrW);
2750 /*************************************************************************
2751 * GetGlyphIndicesW [GDI32.@]
2753 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2754 LPWORD pgi, DWORD flags)
2756 DC *dc = DC_GetDCPtr(hdc);
2757 DWORD ret = GDI_ERROR;
2759 TRACE("(%p, %s, %d, %p, 0x%lx)\n",
2760 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2762 if(!dc) return GDI_ERROR;
2765 ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2767 GDI_ReleaseObj(hdc);
2771 /*************************************************************************
2772 * GetCharacterPlacementA [GDI32.@]
2774 * See GetCharacterPlacementW.
2777 * the web browser control of ie4 calls this with dwFlags=0
2780 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2781 INT nMaxExtent, GCP_RESULTSA *lpResults,
2786 GCP_RESULTSW resultsW;
2789 TRACE("%s, %d, %d, 0x%08lx\n",
2790 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2792 /* both structs are equal in size */
2793 memcpy(&resultsW, lpResults, sizeof(resultsW));
2795 lpStringW = FONT_mbtowc(lpString, uCount, &uCountW);
2796 if(lpResults->lpOutString)
2797 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2799 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2801 lpResults->nGlyphs = resultsW.nGlyphs;
2802 lpResults->nMaxFit = resultsW.nMaxFit;
2804 if(lpResults->lpOutString) {
2805 WideCharToMultiByte(CP_ACP, 0, resultsW.lpOutString, uCountW,
2806 lpResults->lpOutString, uCount, NULL, NULL );
2809 HeapFree(GetProcessHeap(), 0, lpStringW);
2810 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2815 /*************************************************************************
2816 * GetCharacterPlacementW [GDI32.@]
2818 * Retrieve information about a string. This includes the width, reordering,
2819 * Glyphing and so on.
2823 * The width and height of the string if successful, 0 if failed.
2827 * All flags except GCP_REORDER are not yet implemented.
2828 * Reordering is not 100% complient to the Windows BiDi method.
2829 * Caret positioning is not yet implemented for BiDi.
2830 * Classes are not yet implemented.
2834 GetCharacterPlacementW(
2835 HDC hdc, /* [in] Device context for which the rendering is to be done */
2836 LPCWSTR lpString, /* [in] The string for which information is to be returned */
2837 INT uCount, /* [in] Number of WORDS in string. */
2838 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
2839 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2840 DWORD dwFlags /* [in] Flags specifying how to process the string */
2847 TRACE("%s, %d, %d, 0x%08lx\n",
2848 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2850 TRACE("lStructSize=%ld, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2851 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2852 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2853 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2854 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2856 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08lx ignored\n", dwFlags);
2857 if(lpResults->lpClass) FIXME("classes not implemented\n");
2858 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2859 FIXME("Caret positions for complex scripts not implemented\n");
2861 nSet = (UINT)uCount;
2862 if(nSet > lpResults->nGlyphs)
2863 nSet = lpResults->nGlyphs;
2865 /* return number of initialized fields */
2866 lpResults->nGlyphs = nSet;
2868 if((dwFlags&GCP_REORDER)==0 || !BidiAvail)
2870 /* Treat the case where no special handling was requested in a fastpath way */
2871 /* copy will do if the GCP_REORDER flag is not set */
2872 if(lpResults->lpOutString)
2873 memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
2875 if(lpResults->lpOrder)
2877 for(i = 0; i < nSet; i++)
2878 lpResults->lpOrder[i] = i;
2882 BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
2883 nSet, lpResults->lpOrder );
2886 /* FIXME: Will use the placement chars */
2887 if (lpResults->lpDx)
2890 for (i = 0; i < nSet; i++)
2892 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
2893 lpResults->lpDx[i]= c;
2897 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
2901 lpResults->lpCaretPos[0] = 0;
2902 for (i = 1; i < nSet; i++)
2903 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
2904 lpResults->lpCaretPos[i] = (pos += size.cx);
2907 if(lpResults->lpGlyphs)
2908 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
2910 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
2911 ret = MAKELONG(size.cx, size.cy);
2916 /*************************************************************************
2917 * GetCharABCWidthsFloatA [GDI32.@]
2919 * See GetCharABCWidthsFloatW.
2921 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
2923 INT i, wlen, count = (INT)(last - first + 1);
2928 if (count <= 0) return FALSE;
2930 str = HeapAlloc(GetProcessHeap(), 0, count);
2932 for(i = 0; i < count; i++)
2933 str[i] = (BYTE)(first + i);
2935 wstr = FONT_mbtowc(str, count, &wlen);
2937 for (i = 0; i < wlen; i++)
2939 if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
2947 HeapFree( GetProcessHeap(), 0, str );
2948 HeapFree( GetProcessHeap(), 0, wstr );
2953 /*************************************************************************
2954 * GetCharABCWidthsFloatW [GDI32.@]
2956 * Retrieves widths of a range of characters.
2959 * hdc [I] Handle to device context.
2960 * first [I] First character in range to query.
2961 * last [I] Last character in range to query.
2962 * abcf [O] Array of LPABCFLOAT structures.
2969 * Only works with TrueType fonts. It also doesn't return real
2970 * floats but converted integers because it's implemented on
2971 * top of GetCharABCWidthsW.
2973 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
2976 unsigned int i, size = sizeof(ABC) * (last - first + 1);
2979 TRACE("%p, %d, %d, %p - partial stub\n", hdc, first, last, abcf);
2981 abc = HeapAlloc( GetProcessHeap(), 0, size );
2982 if (!abc) return FALSE;
2984 ret = GetCharABCWidthsW( hdc, first, last, abc );
2987 for (i = first; i <= last; i++, abc++, abcf++)
2989 abcf->abcfA = abc->abcA;
2990 abcf->abcfB = abc->abcB;
2991 abcf->abcfC = abc->abcC;
2994 HeapFree( GetProcessHeap(), 0, abc );
2998 /*************************************************************************
2999 * GetCharWidthFloatA [GDI32.@]
3001 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
3002 UINT iLastChar, PFLOAT pxBuffer)
3004 FIXME_(gdi)("GetCharWidthFloatA, stub\n");
3008 /*************************************************************************
3009 * GetCharWidthFloatW [GDI32.@]
3011 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
3012 UINT iLastChar, PFLOAT pxBuffer)
3014 FIXME_(gdi)("GetCharWidthFloatW, stub\n");
3019 /***********************************************************************
3021 * Font Resource API *
3023 ***********************************************************************/
3025 /***********************************************************************
3026 * AddFontResourceA (GDI32.@)
3028 INT WINAPI AddFontResourceA( LPCSTR str )
3030 return AddFontResourceExA( str, 0, NULL);
3033 /***********************************************************************
3034 * AddFontResourceW (GDI32.@)
3036 INT WINAPI AddFontResourceW( LPCWSTR str )
3038 return AddFontResourceExW(str, 0, NULL);
3042 /***********************************************************************
3043 * AddFontResourceExA (GDI32.@)
3045 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3047 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3048 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3051 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3052 ret = AddFontResourceExW(strW, fl, pdv);
3053 HeapFree(GetProcessHeap(), 0, strW);
3057 /***********************************************************************
3058 * AddFontResourceExW (GDI32.@)
3060 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3062 return WineEngAddFontResourceEx(str, fl, pdv);
3065 /***********************************************************************
3066 * RemoveFontResourceA (GDI32.@)
3068 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3070 return RemoveFontResourceExA(str, 0, 0);
3073 /***********************************************************************
3074 * RemoveFontResourceW (GDI32.@)
3076 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3078 return RemoveFontResourceExW(str, 0, 0);
3081 /***********************************************************************
3082 * AddFontMemResourceEx (GDI32.@)
3084 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3086 FIXME("(%p,%08lx,%p,%p): stub\n", pbFont, cbFont, pdv, pcFonts);
3090 /***********************************************************************
3091 * RemoveFontResourceExA (GDI32.@)
3093 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3095 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3096 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3099 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3100 ret = RemoveFontResourceExW(strW, fl, pdv);
3101 HeapFree(GetProcessHeap(), 0, strW);
3105 /***********************************************************************
3106 * RemoveFontResourceExW (GDI32.@)
3108 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3110 return WineEngRemoveFontResourceEx(str, fl, pdv);
3113 /***********************************************************************
3114 * GetTextCharset (GDI32.@)
3116 UINT WINAPI GetTextCharset(HDC hdc)
3118 /* MSDN docs say this is equivalent */
3119 return GetTextCharsetInfo(hdc, NULL, 0);
3122 /***********************************************************************
3123 * GetTextCharsetInfo (GDI32.@)
3125 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3127 UINT ret = DEFAULT_CHARSET;
3128 DC *dc = DC_GetDCPtr(hdc);
3133 ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
3135 GDI_ReleaseObj(hdc);
3138 if (ret == DEFAULT_CHARSET && fs)
3139 memset(fs, 0, sizeof(FONTSIGNATURE));
3143 /***********************************************************************
3144 * GdiGetCharDimensions (GDI32.@)
3146 * Gets the average width of the characters in the English alphabet.
3149 * hdc [I] Handle to the device context to measure on.
3150 * lptm [O] Pointer to memory to store the text metrics into.
3151 * height [O] On exit, the maximum height of characters in the English alphabet.
3154 * The average width of characters in the English alphabet.
3157 * This function is used by the dialog manager to get the size of a dialog
3158 * unit. It should also be used by other pieces of code that need to know
3159 * the size of a dialog unit in logical units without having access to the
3160 * window handle of the dialog.
3161 * Windows caches the font metrics from this function, but we don't and
3162 * there doesn't appear to be an immediate advantage to do so.
3165 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3167 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3170 static const WCHAR alphabet[] = {
3171 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3172 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3173 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3175 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3177 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3179 if (height) *height = sz.cy;
3180 return (sz.cx / 26 + 1) / 2;
3183 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3185 FIXME("(%d): stub\n", fEnableEUDC);
3189 /***********************************************************************
3190 * GetCharWidthI (GDI32.@)
3192 BOOL WINAPI GetCharWidthI(HDC hdc, UINT giFirst, UINT cgi, LPWORD pgi, LPINT lpBuffer)
3194 FIXME("(%p, %d, %d, %p, %p): stub\n", hdc, giFirst, cgi, pgi, lpBuffer);
3198 /***********************************************************************
3199 * GetFontUnicodeRanges (GDI32.@)
3201 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3203 FIXME("(%p, %p): stub\n", hdc, lpgs);