4 * Copyright 1993 Alexandre Julliard
6 * Copyright 2002,2003 Shachar Shemesh
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "wine/port.h"
35 #include "gdi_private.h"
36 #include "wine/unicode.h"
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(font);
41 /* Device -> World size conversion */
43 /* Performs a device to world transformation on the specified width (which
44 * is in integer format).
46 static inline INT INTERNAL_XDSTOWS(DC *dc, INT width)
50 /* Perform operation with floating point */
51 floatWidth = (FLOAT)width * dc->xformVport2World.eM11;
52 /* Round to integers */
53 return GDI_ROUND(floatWidth);
56 /* Performs a device to world transformation on the specified size (which
57 * is in integer format).
59 static inline INT INTERNAL_YDSTOWS(DC *dc, INT height)
63 /* Perform operation with floating point */
64 floatHeight = (FLOAT)height * dc->xformVport2World.eM22;
65 /* Round to integers */
66 return GDI_ROUND(floatHeight);
69 static inline INT INTERNAL_XWSTODS(DC *dc, INT width)
72 pt[0].x = pt[0].y = 0;
75 LPtoDP(dc->hSelf, pt, 2);
76 return pt[1].x - pt[0].x;
79 static inline INT INTERNAL_YWSTODS(DC *dc, INT height)
82 pt[0].x = pt[0].y = 0;
85 LPtoDP(dc->hSelf, pt, 2);
86 return pt[1].y - pt[0].y;
89 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc );
90 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
91 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
92 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj );
94 static const struct gdi_obj_funcs font_funcs =
96 FONT_SelectObject, /* pSelectObject */
97 FONT_GetObjectA, /* pGetObjectA */
98 FONT_GetObjectW, /* pGetObjectW */
99 NULL, /* pUnrealizeObject */
100 FONT_DeleteObject /* pDeleteObject */
103 #define ENUM_UNICODE 0x00000001
104 #define ENUM_CALLED 0x00000002
114 LPLOGFONT16 lpLogFontParam;
115 FONTENUMPROC16 lpEnumFunc;
118 LPNEWTEXTMETRICEX16 lpTextMetric;
119 LPENUMLOGFONTEX16 lpLogFont;
120 SEGPTR segTextMetric;
128 LPLOGFONTW lpLogFontParam;
129 FONTENUMPROCW lpEnumFunc;
136 * For TranslateCharsetInfo
138 #define MAXTCIINDEX 32
139 static const CHARSETINFO FONT_tci[MAXTCIINDEX] = {
141 { ANSI_CHARSET, 1252, {{0,0,0,0},{FS_LATIN1,0}} },
142 { EASTEUROPE_CHARSET, 1250, {{0,0,0,0},{FS_LATIN2,0}} },
143 { RUSSIAN_CHARSET, 1251, {{0,0,0,0},{FS_CYRILLIC,0}} },
144 { GREEK_CHARSET, 1253, {{0,0,0,0},{FS_GREEK,0}} },
145 { TURKISH_CHARSET, 1254, {{0,0,0,0},{FS_TURKISH,0}} },
146 { HEBREW_CHARSET, 1255, {{0,0,0,0},{FS_HEBREW,0}} },
147 { ARABIC_CHARSET, 1256, {{0,0,0,0},{FS_ARABIC,0}} },
148 { BALTIC_CHARSET, 1257, {{0,0,0,0},{FS_BALTIC,0}} },
149 { VIETNAMESE_CHARSET, 1258, {{0,0,0,0},{FS_VIETNAMESE,0}} },
150 /* reserved by ANSI */
151 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
152 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
153 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
154 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
155 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
156 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
157 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
159 { THAI_CHARSET, 874, {{0,0,0,0},{FS_THAI,0}} },
160 { SHIFTJIS_CHARSET, 932, {{0,0,0,0},{FS_JISJAPAN,0}} },
161 { GB2312_CHARSET, 936, {{0,0,0,0},{FS_CHINESESIMP,0}} },
162 { HANGEUL_CHARSET, 949, {{0,0,0,0},{FS_WANSUNG,0}} },
163 { CHINESEBIG5_CHARSET, 950, {{0,0,0,0},{FS_CHINESETRAD,0}} },
164 { JOHAB_CHARSET, 1361, {{0,0,0,0},{FS_JOHAB,0}} },
165 /* reserved for alternate ANSI and OEM */
166 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
167 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
168 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
169 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
170 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
171 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
172 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
173 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
174 /* reserved for system */
175 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
176 { SYMBOL_CHARSET, CP_SYMBOL, {{0,0,0,0},{FS_SYMBOL,0}} }
179 /***********************************************************************
180 * LOGFONT conversion functions.
182 static void FONT_LogFontWTo16( const LOGFONTW* font32, LPLOGFONT16 font16 )
184 font16->lfHeight = font32->lfHeight;
185 font16->lfWidth = font32->lfWidth;
186 font16->lfEscapement = font32->lfEscapement;
187 font16->lfOrientation = font32->lfOrientation;
188 font16->lfWeight = font32->lfWeight;
189 font16->lfItalic = font32->lfItalic;
190 font16->lfUnderline = font32->lfUnderline;
191 font16->lfStrikeOut = font32->lfStrikeOut;
192 font16->lfCharSet = font32->lfCharSet;
193 font16->lfOutPrecision = font32->lfOutPrecision;
194 font16->lfClipPrecision = font32->lfClipPrecision;
195 font16->lfQuality = font32->lfQuality;
196 font16->lfPitchAndFamily = font32->lfPitchAndFamily;
197 WideCharToMultiByte( CP_ACP, 0, font32->lfFaceName, -1,
198 font16->lfFaceName, LF_FACESIZE, NULL, NULL );
199 font16->lfFaceName[LF_FACESIZE-1] = 0;
202 static void FONT_LogFont16ToW( const LOGFONT16 *font16, LPLOGFONTW font32 )
204 font32->lfHeight = font16->lfHeight;
205 font32->lfWidth = font16->lfWidth;
206 font32->lfEscapement = font16->lfEscapement;
207 font32->lfOrientation = font16->lfOrientation;
208 font32->lfWeight = font16->lfWeight;
209 font32->lfItalic = font16->lfItalic;
210 font32->lfUnderline = font16->lfUnderline;
211 font32->lfStrikeOut = font16->lfStrikeOut;
212 font32->lfCharSet = font16->lfCharSet;
213 font32->lfOutPrecision = font16->lfOutPrecision;
214 font32->lfClipPrecision = font16->lfClipPrecision;
215 font32->lfQuality = font16->lfQuality;
216 font32->lfPitchAndFamily = font16->lfPitchAndFamily;
217 MultiByteToWideChar( CP_ACP, 0, font16->lfFaceName, -1, font32->lfFaceName, LF_FACESIZE );
218 font32->lfFaceName[LF_FACESIZE-1] = 0;
221 static void FONT_LogFontAToW( const LOGFONTA *fontA, LPLOGFONTW fontW )
223 memcpy(fontW, fontA, sizeof(LOGFONTA) - LF_FACESIZE);
224 MultiByteToWideChar(CP_ACP, 0, fontA->lfFaceName, -1, fontW->lfFaceName,
226 fontW->lfFaceName[LF_FACESIZE-1] = 0;
229 static void FONT_LogFontWToA( const LOGFONTW *fontW, LPLOGFONTA fontA )
231 memcpy(fontA, fontW, sizeof(LOGFONTA) - LF_FACESIZE);
232 WideCharToMultiByte(CP_ACP, 0, fontW->lfFaceName, -1, fontA->lfFaceName,
233 LF_FACESIZE, NULL, NULL);
234 fontA->lfFaceName[LF_FACESIZE-1] = 0;
237 static void FONT_EnumLogFontExWTo16( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEX16 font16 )
239 FONT_LogFontWTo16( (const LOGFONTW *)fontW, (LPLOGFONT16)font16);
241 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
242 (LPSTR) font16->elfFullName, LF_FULLFACESIZE, NULL, NULL );
243 font16->elfFullName[LF_FULLFACESIZE-1] = '\0';
244 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
245 (LPSTR) font16->elfStyle, LF_FACESIZE, NULL, NULL );
246 font16->elfStyle[LF_FACESIZE-1] = '\0';
247 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
248 (LPSTR) font16->elfScript, LF_FACESIZE, NULL, NULL );
249 font16->elfScript[LF_FACESIZE-1] = '\0';
252 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEXA fontA )
254 FONT_LogFontWToA( (const LOGFONTW *)fontW, (LPLOGFONTA)fontA);
256 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
257 (LPSTR) fontA->elfFullName, LF_FULLFACESIZE, NULL, NULL );
258 fontA->elfFullName[LF_FULLFACESIZE-1] = '\0';
259 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
260 (LPSTR) fontA->elfStyle, LF_FACESIZE, NULL, NULL );
261 fontA->elfStyle[LF_FACESIZE-1] = '\0';
262 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
263 (LPSTR) fontA->elfScript, LF_FACESIZE, NULL, NULL );
264 fontA->elfScript[LF_FACESIZE-1] = '\0';
267 /***********************************************************************
268 * TEXTMETRIC conversion functions.
270 static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
272 ptmA->tmHeight = ptmW->tmHeight;
273 ptmA->tmAscent = ptmW->tmAscent;
274 ptmA->tmDescent = ptmW->tmDescent;
275 ptmA->tmInternalLeading = ptmW->tmInternalLeading;
276 ptmA->tmExternalLeading = ptmW->tmExternalLeading;
277 ptmA->tmAveCharWidth = ptmW->tmAveCharWidth;
278 ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth;
279 ptmA->tmWeight = ptmW->tmWeight;
280 ptmA->tmOverhang = ptmW->tmOverhang;
281 ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX;
282 ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
283 ptmA->tmFirstChar = min(ptmW->tmFirstChar, 255);
284 if (ptmW->tmCharSet == SYMBOL_CHARSET)
286 UINT last_char = ptmW->tmLastChar;
287 if (last_char > 0xf000) last_char -= 0xf000;
288 ptmA->tmLastChar = min(last_char, 255);
291 ptmA->tmLastChar = min(ptmW->tmLastChar, 255);
292 ptmA->tmDefaultChar = min(ptmW->tmDefaultChar, 255);
293 ptmA->tmBreakChar = min(ptmW->tmBreakChar, 255);
294 ptmA->tmItalic = ptmW->tmItalic;
295 ptmA->tmUnderlined = ptmW->tmUnderlined;
296 ptmA->tmStruckOut = ptmW->tmStruckOut;
297 ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
298 ptmA->tmCharSet = ptmW->tmCharSet;
302 static void FONT_NewTextMetricExWTo16(const NEWTEXTMETRICEXW *ptmW, LPNEWTEXTMETRICEX16 ptm16 )
304 ptm16->ntmTm.tmHeight = ptmW->ntmTm.tmHeight;
305 ptm16->ntmTm.tmAscent = ptmW->ntmTm.tmAscent;
306 ptm16->ntmTm.tmDescent = ptmW->ntmTm.tmDescent;
307 ptm16->ntmTm.tmInternalLeading = ptmW->ntmTm.tmInternalLeading;
308 ptm16->ntmTm.tmExternalLeading = ptmW->ntmTm.tmExternalLeading;
309 ptm16->ntmTm.tmAveCharWidth = ptmW->ntmTm.tmAveCharWidth;
310 ptm16->ntmTm.tmMaxCharWidth = ptmW->ntmTm.tmMaxCharWidth;
311 ptm16->ntmTm.tmWeight = ptmW->ntmTm.tmWeight;
312 ptm16->ntmTm.tmOverhang = ptmW->ntmTm.tmOverhang;
313 ptm16->ntmTm.tmDigitizedAspectX = ptmW->ntmTm.tmDigitizedAspectX;
314 ptm16->ntmTm.tmDigitizedAspectY = ptmW->ntmTm.tmDigitizedAspectY;
315 ptm16->ntmTm.tmFirstChar = ptmW->ntmTm.tmFirstChar > 255 ? 255 : ptmW->ntmTm.tmFirstChar;
316 ptm16->ntmTm.tmLastChar = ptmW->ntmTm.tmLastChar > 255 ? 255 : ptmW->ntmTm.tmLastChar;
317 ptm16->ntmTm.tmDefaultChar = ptmW->ntmTm.tmDefaultChar > 255 ? 255 : ptmW->ntmTm.tmDefaultChar;
318 ptm16->ntmTm.tmBreakChar = ptmW->ntmTm.tmBreakChar > 255 ? 255 : ptmW->ntmTm.tmBreakChar;
319 ptm16->ntmTm.tmItalic = ptmW->ntmTm.tmItalic;
320 ptm16->ntmTm.tmUnderlined = ptmW->ntmTm.tmUnderlined;
321 ptm16->ntmTm.tmStruckOut = ptmW->ntmTm.tmStruckOut;
322 ptm16->ntmTm.tmPitchAndFamily = ptmW->ntmTm.tmPitchAndFamily;
323 ptm16->ntmTm.tmCharSet = ptmW->ntmTm.tmCharSet;
324 ptm16->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
325 ptm16->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
326 ptm16->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
327 ptm16->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
328 memcpy(&ptm16->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
331 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW *ptmW, NEWTEXTMETRICEXA *ptmA )
333 FONT_TextMetricWToA((const TEXTMETRICW *)ptmW, (LPTEXTMETRICA)ptmA);
334 ptmA->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
335 ptmA->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
336 ptmA->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
337 ptmA->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
338 memcpy(&ptmA->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
342 /***********************************************************************
343 * GdiGetCodePage (GDI32.@)
345 DWORD WINAPI GdiGetCodePage( HDC hdc )
349 int charset = GetTextCharset(hdc);
351 /* Hmm, nicely designed api this one! */
352 if(TranslateCharsetInfo(ULongToPtr(charset), &csi, TCI_SRCCHARSET))
359 case DEFAULT_CHARSET:
370 /* FIXME: These have no place here, but because x11drv
371 enumerates fonts with these (made up) charsets some apps
372 might use them and then the FIXME below would become
373 annoying. Now we could pick the intended codepage for
374 each of these, but since it's broken anyway we'll just
375 use CP_ACP and hope it'll go away...
381 FIXME("Can't find codepage for charset %d\n", charset);
386 TRACE("charset %d => cp %d\n", charset, cp);
390 /***********************************************************************
393 * Returns a Unicode translation of str using the charset of the
394 * currently selected font in hdc. If count is -1 then str is assumed
395 * to be '\0' terminated, otherwise it contains the number of bytes to
396 * convert. If plenW is non-NULL, on return it will point to the
397 * number of WCHARs that have been written. If pCP is non-NULL, on
398 * return it will point to the codepage used in the conversion. The
399 * caller should free the returned LPWSTR from the process heap
402 static LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
408 cp = GdiGetCodePage( hdc );
410 if(count == -1) count = strlen(str);
411 lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
412 strW = HeapAlloc(GetProcessHeap(), 0, lenW*sizeof(WCHAR));
413 MultiByteToWideChar(cp, 0, str, count, strW, lenW);
414 TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW));
415 if(plenW) *plenW = lenW;
421 /***********************************************************************
422 * CreateFontIndirectA (GDI32.@)
424 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *plfA )
430 FONT_LogFontAToW( plfA, &lfW );
431 return CreateFontIndirectW( &lfW );
434 /***********************************************************************
435 * CreateFontIndirectW (GDI32.@)
437 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
439 static const WCHAR ItalicW[] = {' ','I','t','a','l','i','c','\0'};
440 static const WCHAR BoldW[] = {' ','B','o','l','d','\0'};
441 WCHAR *pFaceNameItalicSuffix, *pFaceNameBoldSuffix;
442 WCHAR *pFaceNameSuffix = NULL;
448 if (!(fontPtr = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC, (HGDIOBJ *)&hFont,
449 &font_funcs ))) return 0;
451 memcpy( &fontPtr->logfont, plf, sizeof(LOGFONTW) );
453 TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
454 plf->lfHeight, plf->lfWidth,
455 plf->lfEscapement, plf->lfOrientation,
456 plf->lfPitchAndFamily,
457 plf->lfOutPrecision, plf->lfClipPrecision,
458 plf->lfQuality, plf->lfCharSet,
459 debugstr_w(plf->lfFaceName),
460 plf->lfWeight > 400 ? "Bold" : "",
461 plf->lfItalic ? "Italic" : "",
462 plf->lfUnderline ? "Underline" : "", hFont);
464 if (plf->lfEscapement != plf->lfOrientation)
466 /* this should really depend on whether GM_ADVANCED is set */
467 fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
468 WARN("orientation angle %f set to "
469 "escapement angle %f for new font %p\n",
470 plf->lfOrientation/10., plf->lfEscapement/10., hFont);
473 pFaceNameItalicSuffix = strstrW(fontPtr->logfont.lfFaceName, ItalicW);
474 if (pFaceNameItalicSuffix)
476 fontPtr->logfont.lfItalic = TRUE;
477 pFaceNameSuffix = pFaceNameItalicSuffix;
480 pFaceNameBoldSuffix = strstrW(fontPtr->logfont.lfFaceName, BoldW);
481 if (pFaceNameBoldSuffix)
483 if (fontPtr->logfont.lfWeight < FW_BOLD)
484 fontPtr->logfont.lfWeight = FW_BOLD;
485 if (!pFaceNameSuffix || (pFaceNameBoldSuffix < pFaceNameSuffix))
486 pFaceNameSuffix = pFaceNameBoldSuffix;
489 if (pFaceNameSuffix) *pFaceNameSuffix = 0;
491 GDI_ReleaseObj( hFont );
495 /*************************************************************************
496 * CreateFontA (GDI32.@)
498 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
499 INT orient, INT weight, DWORD italic,
500 DWORD underline, DWORD strikeout, DWORD charset,
501 DWORD outpres, DWORD clippres, DWORD quality,
502 DWORD pitch, LPCSTR name )
506 logfont.lfHeight = height;
507 logfont.lfWidth = width;
508 logfont.lfEscapement = esc;
509 logfont.lfOrientation = orient;
510 logfont.lfWeight = weight;
511 logfont.lfItalic = italic;
512 logfont.lfUnderline = underline;
513 logfont.lfStrikeOut = strikeout;
514 logfont.lfCharSet = charset;
515 logfont.lfOutPrecision = outpres;
516 logfont.lfClipPrecision = clippres;
517 logfont.lfQuality = quality;
518 logfont.lfPitchAndFamily = pitch;
521 lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
523 logfont.lfFaceName[0] = '\0';
525 return CreateFontIndirectA( &logfont );
528 /*************************************************************************
529 * CreateFontW (GDI32.@)
531 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
532 INT orient, INT weight, DWORD italic,
533 DWORD underline, DWORD strikeout, DWORD charset,
534 DWORD outpres, DWORD clippres, DWORD quality,
535 DWORD pitch, LPCWSTR name )
539 logfont.lfHeight = height;
540 logfont.lfWidth = width;
541 logfont.lfEscapement = esc;
542 logfont.lfOrientation = orient;
543 logfont.lfWeight = weight;
544 logfont.lfItalic = italic;
545 logfont.lfUnderline = underline;
546 logfont.lfStrikeOut = strikeout;
547 logfont.lfCharSet = charset;
548 logfont.lfOutPrecision = outpres;
549 logfont.lfClipPrecision = clippres;
550 logfont.lfQuality = quality;
551 logfont.lfPitchAndFamily = pitch;
554 lstrcpynW(logfont.lfFaceName, name,
555 sizeof(logfont.lfFaceName) / sizeof(WCHAR));
557 logfont.lfFaceName[0] = '\0';
559 return CreateFontIndirectW( &logfont );
563 /***********************************************************************
566 * If the driver supports vector fonts we create a gdi font first and
567 * then call the driver to give it a chance to supply its own device
568 * font. If the driver wants to do this it returns TRUE and we can
569 * delete the gdi font, if the driver wants to use the gdi font it
570 * should return FALSE, to signal an error return GDI_ERROR. For
571 * drivers that don't support vector fonts they must supply their own
574 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc )
577 DC *dc = get_dc_ptr( hdc );
581 if (!GDI_inc_ref_count( handle ))
583 release_dc_ptr( dc );
587 if (dc->hFont != handle || dc->gdiFont == NULL)
589 if(GetDeviceCaps(dc->hSelf, TEXTCAPS) & TC_VA_ABLE)
591 FONTOBJ *font = GDI_GetObjPtr( handle, FONT_MAGIC ); /* to grab the GDI lock (FIXME) */
592 dc->gdiFont = WineEngCreateFontInstance(dc, handle);
593 if (font) GDI_ReleaseObj( handle );
597 if (dc->funcs->pSelectFont) ret = dc->funcs->pSelectFont( dc->physDev, handle, dc->gdiFont );
599 if (ret && dc->gdiFont) dc->gdiFont = 0;
601 if (ret == HGDI_ERROR)
603 GDI_dec_ref_count( handle );
604 ret = 0; /* SelectObject returns 0 on error */
610 GDI_dec_ref_count( ret );
612 release_dc_ptr( dc );
617 /***********************************************************************
620 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
627 FONT_LogFontWToA( &font->logfont, &lfA );
629 if (count > sizeof(lfA)) count = sizeof(lfA);
630 memcpy( buffer, &lfA, count );
634 /***********************************************************************
637 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
641 return sizeof(LOGFONTW);
642 if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
643 memcpy( buffer, &font->logfont, count );
648 /***********************************************************************
651 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj )
653 WineEngDestroyFontInstance( handle );
654 return GDI_FreeObject( handle, obj );
658 /***********************************************************************
659 * FONT_EnumInstance16
661 * Called by the device driver layer to pass font info
662 * down to the application.
664 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
665 * We have to use other types because of the FONTENUMPROCW definition.
667 static INT CALLBACK FONT_EnumInstance16( const LOGFONTW *plf, const TEXTMETRICW *ptm,
668 DWORD fType, LPARAM lp )
670 fontEnum16 *pfe = (fontEnum16*)lp;
673 if (!pfe->lpLogFontParam ||
674 pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
675 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet )
680 FONT_EnumLogFontExWTo16((const ENUMLOGFONTEXW *)plf, pfe->lpLogFont);
681 FONT_NewTextMetricExWTo16((const NEWTEXTMETRICEXW *)ptm, pfe->lpTextMetric);
682 pfe->dwFlags |= ENUM_CALLED;
684 args[6] = SELECTOROF(pfe->segLogFont);
685 args[5] = OFFSETOF(pfe->segLogFont);
686 args[4] = SELECTOROF(pfe->segTextMetric);
687 args[3] = OFFSETOF(pfe->segTextMetric);
689 args[1] = HIWORD(pfe->lpData);
690 args[0] = LOWORD(pfe->lpData);
691 WOWCallback16Ex( (DWORD)pfe->lpEnumFunc, WCB16_PASCAL, sizeof(args), args, &result );
692 ret = LOWORD(result);
697 /***********************************************************************
700 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
701 * We have to use other types because of the FONTENUMPROCW definition.
703 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
704 DWORD fType, LPARAM lp )
706 fontEnum32 *pfe = (fontEnum32*)lp;
709 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
710 if ((!pfe->lpLogFontParam ||
711 pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
712 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
713 (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
715 /* convert font metrics */
716 ENUMLOGFONTEXA logfont;
717 NEWTEXTMETRICEXA tmA;
719 pfe->dwFlags |= ENUM_CALLED;
720 if (!(pfe->dwFlags & ENUM_UNICODE))
722 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
723 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
724 plf = (LOGFONTW *)&logfont.elfLogFont;
725 ptm = (TEXTMETRICW *)&tmA;
728 ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
733 /***********************************************************************
734 * EnumFontFamiliesEx (GDI.613)
736 INT16 WINAPI EnumFontFamiliesEx16( HDC16 hDC, LPLOGFONT16 plf,
737 FONTENUMPROC16 efproc, LPARAM lParam,
742 DC* dc = get_dc_ptr( HDC_32(hDC) );
743 NEWTEXTMETRICEX16 tm16;
744 ENUMLOGFONTEX16 lf16;
752 FONT_LogFont16ToW(plf, &lfW);
757 fe16.hdc = HDC_32(hDC);
758 fe16.lpLogFontParam = plf;
759 fe16.lpEnumFunc = efproc;
760 fe16.lpData = lParam;
761 fe16.lpTextMetric = &tm16;
762 fe16.lpLogFont = &lf16;
763 fe16.segTextMetric = MapLS( &tm16 );
764 fe16.segLogFont = MapLS( &lf16 );
767 enum_gdi_fonts = GetDeviceCaps(fe16.hdc, TEXTCAPS) & TC_VA_ABLE;
769 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
776 ret = WineEngEnumFonts( plfW, FONT_EnumInstance16, (LPARAM)&fe16 );
777 fe16.dwFlags &= ~ENUM_CALLED;
778 if (ret && dc->funcs->pEnumDeviceFonts) {
779 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, plfW, FONT_EnumInstance16, (LPARAM)&fe16 );
780 if(fe16.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
784 UnMapLS( fe16.segTextMetric );
785 UnMapLS( fe16.segLogFont );
786 release_dc_ptr( dc );
790 /***********************************************************************
791 * FONT_EnumFontFamiliesEx
793 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf,
794 FONTENUMPROCW efproc,
795 LPARAM lParam, DWORD dwUnicode)
798 DC *dc = get_dc_ptr( hDC );
805 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName),
807 fe32.lpLogFontParam = plf;
808 fe32.lpEnumFunc = efproc;
809 fe32.lpData = lParam;
810 fe32.dwFlags = dwUnicode;
813 enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE;
815 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
822 ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
823 fe32.dwFlags &= ~ENUM_CALLED;
824 if (ret && dc->funcs->pEnumDeviceFonts) {
825 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, plf, FONT_EnumInstance, (LPARAM)&fe32 );
826 if(fe32.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
830 release_dc_ptr( dc );
834 /***********************************************************************
835 * EnumFontFamiliesExW (GDI32.@)
837 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
838 FONTENUMPROCW efproc,
839 LPARAM lParam, DWORD dwFlags )
841 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, ENUM_UNICODE );
844 /***********************************************************************
845 * EnumFontFamiliesExA (GDI32.@)
847 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
848 FONTENUMPROCA efproc,
849 LPARAM lParam, DWORD dwFlags)
855 FONT_LogFontAToW( plf, &lfW );
860 return FONT_EnumFontFamiliesEx( hDC, plfW, (FONTENUMPROCW)efproc, lParam, 0);
863 /***********************************************************************
864 * EnumFontFamilies (GDI.330)
866 INT16 WINAPI EnumFontFamilies16( HDC16 hDC, LPCSTR lpFamily,
867 FONTENUMPROC16 efproc, LPARAM lpData )
873 if (!*lpFamily) return 1;
874 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
875 lf.lfCharSet = DEFAULT_CHARSET;
876 lf.lfPitchAndFamily = 0;
881 return EnumFontFamiliesEx16( hDC, plf, efproc, lpData, 0 );
884 /***********************************************************************
885 * EnumFontFamiliesA (GDI32.@)
887 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
888 FONTENUMPROCA efproc, LPARAM lpData )
894 if (!*lpFamily) return 1;
895 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
896 lf.lfCharSet = DEFAULT_CHARSET;
897 lf.lfPitchAndFamily = 0;
902 return EnumFontFamiliesExA( hDC, plf, efproc, lpData, 0 );
905 /***********************************************************************
906 * EnumFontFamiliesW (GDI32.@)
908 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
909 FONTENUMPROCW efproc, LPARAM lpData )
915 if (!*lpFamily) return 1;
916 lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
917 lf.lfCharSet = DEFAULT_CHARSET;
918 lf.lfPitchAndFamily = 0;
923 return EnumFontFamiliesExW( hDC, plf, efproc, lpData, 0 );
926 /***********************************************************************
929 INT16 WINAPI EnumFonts16( HDC16 hDC, LPCSTR lpName, FONTENUMPROC16 efproc,
932 return EnumFontFamilies16( hDC, lpName, efproc, lpData );
935 /***********************************************************************
936 * EnumFontsA (GDI32.@)
938 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
941 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
944 /***********************************************************************
945 * EnumFontsW (GDI32.@)
947 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
950 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
954 /***********************************************************************
955 * GetTextCharacterExtra (GDI32.@)
957 INT WINAPI GetTextCharacterExtra( HDC hdc )
960 DC *dc = get_dc_ptr( hdc );
961 if (!dc) return 0x80000000;
963 release_dc_ptr( dc );
968 /***********************************************************************
969 * SetTextCharacterExtra (GDI32.@)
971 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
974 DC * dc = get_dc_ptr( hdc );
975 if (!dc) return 0x80000000;
976 if (dc->funcs->pSetTextCharacterExtra)
977 prev = dc->funcs->pSetTextCharacterExtra( dc->physDev, extra );
980 prev = dc->charExtra;
981 dc->charExtra = extra;
983 release_dc_ptr( dc );
988 /***********************************************************************
989 * SetTextJustification (GDI32.@)
991 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
994 DC * dc = get_dc_ptr( hdc );
995 if (!dc) return FALSE;
996 if (dc->funcs->pSetTextJustification)
997 ret = dc->funcs->pSetTextJustification( dc->physDev, extra, breaks );
1000 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
1001 if (!extra) breaks = 0;
1004 dc->breakExtra = extra / breaks;
1005 dc->breakRem = extra - (breaks * dc->breakExtra);
1013 release_dc_ptr( dc );
1018 /***********************************************************************
1019 * GetTextFaceA (GDI32.@)
1021 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
1023 INT res = GetTextFaceW(hdc, 0, NULL);
1024 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
1025 GetTextFaceW( hdc, res, nameW );
1029 if (count && !WideCharToMultiByte( CP_ACP, 0, nameW, -1, name, count, NULL, NULL))
1034 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
1035 HeapFree( GetProcessHeap(), 0, nameW );
1039 /***********************************************************************
1040 * GetTextFaceW (GDI32.@)
1042 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
1047 DC * dc = get_dc_ptr( hdc );
1051 ret = WineEngGetTextFace(dc->gdiFont, count, name);
1052 else if ((font = (FONTOBJ *) GDI_GetObjPtr( dc->hFont, FONT_MAGIC )))
1056 lstrcpynW( name, font->logfont.lfFaceName, count );
1057 ret = strlenW(name);
1059 else ret = strlenW(font->logfont.lfFaceName) + 1;
1060 GDI_ReleaseObj( dc->hFont );
1062 release_dc_ptr( dc );
1067 /***********************************************************************
1068 * GetTextExtentPoint32A (GDI32.@)
1070 * See GetTextExtentPoint32W.
1072 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
1077 LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1080 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
1081 HeapFree( GetProcessHeap(), 0, p );
1084 TRACE("(%p %s %d %p): returning %d x %d\n",
1085 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
1090 /***********************************************************************
1091 * GetTextExtentPoint32W [GDI32.@]
1093 * Computes width/height for a string.
1095 * Computes width and height of the specified string.
1101 BOOL WINAPI GetTextExtentPoint32W(
1102 HDC hdc, /* [in] Handle of device context */
1103 LPCWSTR str, /* [in] Address of text string */
1104 INT count, /* [in] Number of characters in string */
1105 LPSIZE size) /* [out] Address of structure for string size */
1107 return GetTextExtentExPointW(hdc, str, count, 0, NULL, NULL, size);
1110 /***********************************************************************
1111 * GetTextExtentExPointI [GDI32.@]
1113 * Computes width and height of the array of glyph indices.
1116 * hdc [I] Handle of device context.
1117 * indices [I] Glyph index array.
1118 * count [I] Number of glyphs in array.
1119 * max_ext [I] Maximum width in glyphs.
1120 * nfit [O] Maximum number of characters.
1121 * dxs [O] Partial string widths.
1122 * size [O] Returned string size.
1128 BOOL WINAPI GetTextExtentExPointI( HDC hdc, const WORD *indices, INT count, INT max_ext,
1129 LPINT nfit, LPINT dxs, LPSIZE size )
1132 DC * dc = get_dc_ptr( hdc );
1133 if (!dc) return FALSE;
1136 ret = WineEngGetTextExtentExPointI(dc->gdiFont, indices, count, max_ext, nfit, dxs, size);
1137 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1138 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1139 size->cx += count * dc->charExtra;
1141 else if(dc->funcs->pGetTextExtentExPoint) {
1142 FIXME("calling GetTextExtentExPoint\n");
1143 ret = dc->funcs->pGetTextExtentExPoint( dc->physDev, (LPCWSTR)indices,
1144 count, max_ext, nfit, dxs, size );
1147 release_dc_ptr( dc );
1149 TRACE("(%p %p %d %p): returning %d x %d\n",
1150 hdc, indices, count, size, size->cx, size->cy );
1154 /***********************************************************************
1155 * GetTextExtentPointI [GDI32.@]
1157 * Computes width and height of the array of glyph indices.
1160 * hdc [I] Handle of device context.
1161 * indices [I] Glyph index array.
1162 * count [I] Number of glyphs in array.
1163 * size [O] Returned string size.
1169 BOOL WINAPI GetTextExtentPointI( HDC hdc, const WORD *indices, INT count, LPSIZE size )
1171 return GetTextExtentExPointI( hdc, indices, count, 0, NULL, NULL, size );
1175 /***********************************************************************
1176 * GetTextExtentPointA (GDI32.@)
1178 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
1181 TRACE("not bug compatible.\n");
1182 return GetTextExtentPoint32A( hdc, str, count, size );
1185 /***********************************************************************
1186 * GetTextExtentPointW (GDI32.@)
1188 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1191 TRACE("not bug compatible.\n");
1192 return GetTextExtentPoint32W( hdc, str, count, size );
1196 /***********************************************************************
1197 * GetTextExtentExPointA (GDI32.@)
1199 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1200 INT maxExt, LPINT lpnFit,
1201 LPINT alpDx, LPSIZE size )
1209 NULL == (walpDx = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT))))
1212 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1213 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
1216 INT n = lpnFit ? *lpnFit : wlen;
1218 for(i = 0, j = 0; i < n; i++, j++)
1220 alpDx[j] = walpDx[i];
1221 if (IsDBCSLeadByte(str[j])) alpDx[++j] = walpDx[i];
1224 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1225 HeapFree( GetProcessHeap(), 0, p );
1226 HeapFree( GetProcessHeap(), 0, walpDx );
1231 /***********************************************************************
1232 * GetTextExtentExPointW (GDI32.@)
1234 * Return the size of the string as it would be if it was output properly by
1237 * This should include
1238 * - Intercharacter spacing
1239 * - justification spacing (not yet done)
1240 * - kerning? see below
1242 * Kerning. Since kerning would be carried out by the rendering code it should
1243 * be done by the driver. However they don't support it yet. Also I am not
1244 * yet persuaded that (certainly under Win95) any kerning is actually done.
1246 * str: According to MSDN this should be null-terminated. That is not true; a
1247 * null will not terminate it early.
1248 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1249 * than count. I have seen it be either the size of the full string or
1250 * 1 less than the size of the full string. I have not seen it bear any
1251 * resemblance to the portion that would fit.
1252 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1253 * trailing intercharacter spacing and any trailing justification.
1256 * Currently we do this by measuring each character etc. We should do it by
1257 * passing the request to the driver, perhaps by extending the
1258 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1259 * thinking about kerning issues and rounding issues in the justification.
1262 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1263 INT maxExt, LPINT lpnFit,
1264 LPINT alpDx, LPSIZE size )
1272 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1274 dc = get_dc_ptr(hdc);
1278 GetTextMetricsW(hdc, &tm);
1280 /* If we need to calculate nFit, then we need the partial extents even if
1281 the user hasn't provided us with an array. */
1284 dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]);
1288 SetLastError(ERROR_OUTOFMEMORY);
1296 ret = WineEngGetTextExtentExPoint(dc->gdiFont, str, count,
1297 0, NULL, dxs, size);
1298 else if (dc->funcs->pGetTextExtentExPoint)
1299 ret = dc->funcs->pGetTextExtentExPoint(dc->physDev, str, count,
1300 0, NULL, dxs, size);
1302 /* Perform device size to world size transformations. */
1305 INT extra = dc->charExtra,
1306 breakExtra = dc->breakExtra,
1307 breakRem = dc->breakRem,
1312 for (i = 0; i < count; ++i)
1314 dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
1315 dxs[i] += (i+1) * extra;
1316 if (count > 1 && (breakExtra || breakRem) && str[i] == tm.tmBreakChar)
1318 dxs[i] += breakExtra;
1325 if (dxs[i] <= maxExt)
1328 breakRem = dc->breakRem;
1330 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1331 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1333 if (!dxs && count > 1 && (breakExtra || breakRem))
1335 for (i = 0; i < count; i++)
1337 if (str[i] == tm.tmBreakChar)
1339 size->cx += breakExtra;
1354 HeapFree(GetProcessHeap(), 0, dxs);
1356 release_dc_ptr( dc );
1358 TRACE("returning %d %d x %d\n",nFit,size->cx,size->cy);
1362 /***********************************************************************
1363 * GetTextMetricsA (GDI32.@)
1365 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1369 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1370 FONT_TextMetricWToA( &tm32, metrics );
1374 /***********************************************************************
1375 * GetTextMetricsW (GDI32.@)
1377 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1380 DC * dc = get_dc_ptr( hdc );
1381 if (!dc) return FALSE;
1384 ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1385 else if (dc->funcs->pGetTextMetrics)
1386 ret = dc->funcs->pGetTextMetrics( dc->physDev, metrics );
1390 /* device layer returns values in device units
1391 * therefore we have to convert them to logical */
1393 metrics->tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1394 metrics->tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1396 #define WDPTOLP(x) ((x<0)? \
1397 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1398 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1399 #define HDPTOLP(y) ((y<0)? \
1400 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1401 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1403 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1404 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1405 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1406 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1407 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1408 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1409 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1410 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1414 TRACE("text metrics:\n"
1415 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1416 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1417 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1418 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1419 " PitchAndFamily = %02x\n"
1420 " --------------------\n"
1421 " InternalLeading = %i\n"
1425 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1426 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1427 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1428 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1429 metrics->tmPitchAndFamily,
1430 metrics->tmInternalLeading,
1433 metrics->tmHeight );
1435 release_dc_ptr( dc );
1440 /***********************************************************************
1441 * GetOutlineTextMetricsA (GDI32.@)
1442 * Gets metrics for TrueType fonts.
1445 * If the supplied buffer isn't big enough Windows partially fills it up to
1446 * its given length and returns that length.
1449 * Success: Non-zero or size of required buffer
1452 UINT WINAPI GetOutlineTextMetricsA(
1453 HDC hdc, /* [in] Handle of device context */
1454 UINT cbData, /* [in] Size of metric data array */
1455 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1457 char buf[512], *ptr;
1459 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1460 OUTLINETEXTMETRICA *output = lpOTM;
1463 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1465 if(ret > sizeof(buf))
1466 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1467 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1469 needed = sizeof(OUTLINETEXTMETRICA);
1470 if(lpOTMW->otmpFamilyName)
1471 needed += WideCharToMultiByte(CP_ACP, 0,
1472 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1473 NULL, 0, NULL, NULL);
1474 if(lpOTMW->otmpFaceName)
1475 needed += WideCharToMultiByte(CP_ACP, 0,
1476 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1477 NULL, 0, NULL, NULL);
1478 if(lpOTMW->otmpStyleName)
1479 needed += WideCharToMultiByte(CP_ACP, 0,
1480 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1481 NULL, 0, NULL, NULL);
1482 if(lpOTMW->otmpFullName)
1483 needed += WideCharToMultiByte(CP_ACP, 0,
1484 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1485 NULL, 0, NULL, NULL);
1492 TRACE("needed = %d\n", needed);
1494 /* Since the supplied buffer isn't big enough, we'll alloc one
1495 that is and memcpy the first cbData bytes into the lpOTM at
1497 output = HeapAlloc(GetProcessHeap(), 0, needed);
1499 ret = output->otmSize = min(needed, cbData);
1500 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1501 output->otmFiller = 0;
1502 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1503 output->otmfsSelection = lpOTMW->otmfsSelection;
1504 output->otmfsType = lpOTMW->otmfsType;
1505 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1506 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1507 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1508 output->otmEMSquare = lpOTMW->otmEMSquare;
1509 output->otmAscent = lpOTMW->otmAscent;
1510 output->otmDescent = lpOTMW->otmDescent;
1511 output->otmLineGap = lpOTMW->otmLineGap;
1512 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1513 output->otmsXHeight = lpOTMW->otmsXHeight;
1514 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1515 output->otmMacAscent = lpOTMW->otmMacAscent;
1516 output->otmMacDescent = lpOTMW->otmMacDescent;
1517 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1518 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1519 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1520 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1521 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1522 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1523 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1524 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1525 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1526 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1529 ptr = (char*)(output + 1);
1530 left = needed - sizeof(*output);
1532 if(lpOTMW->otmpFamilyName) {
1533 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1534 len = WideCharToMultiByte(CP_ACP, 0,
1535 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1536 ptr, left, NULL, NULL);
1540 output->otmpFamilyName = 0;
1542 if(lpOTMW->otmpFaceName) {
1543 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1544 len = WideCharToMultiByte(CP_ACP, 0,
1545 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1546 ptr, left, NULL, NULL);
1550 output->otmpFaceName = 0;
1552 if(lpOTMW->otmpStyleName) {
1553 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1554 len = WideCharToMultiByte(CP_ACP, 0,
1555 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1556 ptr, left, NULL, NULL);
1560 output->otmpStyleName = 0;
1562 if(lpOTMW->otmpFullName) {
1563 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1564 len = WideCharToMultiByte(CP_ACP, 0,
1565 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1566 ptr, left, NULL, NULL);
1569 output->otmpFullName = 0;
1573 if(output != lpOTM) {
1574 memcpy(lpOTM, output, cbData);
1575 HeapFree(GetProcessHeap(), 0, output);
1577 /* check if the string offsets really fit into the provided size */
1578 /* FIXME: should we check string length as well? */
1579 /* make sure that we don't read/write beyond the provided buffer */
1580 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(LPSTR))
1582 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1583 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1586 /* make sure that we don't read/write beyond the provided buffer */
1587 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(LPSTR))
1589 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1590 lpOTM->otmpFaceName = 0; /* doesn't fit */
1593 /* make sure that we don't read/write beyond the provided buffer */
1594 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(LPSTR))
1596 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1597 lpOTM->otmpStyleName = 0; /* doesn't fit */
1600 /* make sure that we don't read/write beyond the provided buffer */
1601 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(LPSTR))
1603 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1604 lpOTM->otmpFullName = 0; /* doesn't fit */
1609 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1610 HeapFree(GetProcessHeap(), 0, lpOTMW);
1616 /***********************************************************************
1617 * GetOutlineTextMetricsW [GDI32.@]
1619 UINT WINAPI GetOutlineTextMetricsW(
1620 HDC hdc, /* [in] Handle of device context */
1621 UINT cbData, /* [in] Size of metric data array */
1622 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1624 DC *dc = get_dc_ptr( hdc );
1625 OUTLINETEXTMETRICW *output = lpOTM;
1628 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1632 ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, output);
1635 output = HeapAlloc(GetProcessHeap(), 0, ret);
1636 WineEngGetOutlineTextMetrics(dc->gdiFont, ret, output);
1639 #define WDPTOLP(x) ((x<0)? \
1640 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1641 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1642 #define HDPTOLP(y) ((y<0)? \
1643 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1644 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1646 output->otmTextMetrics.tmHeight = HDPTOLP(output->otmTextMetrics.tmHeight);
1647 output->otmTextMetrics.tmAscent = HDPTOLP(output->otmTextMetrics.tmAscent);
1648 output->otmTextMetrics.tmDescent = HDPTOLP(output->otmTextMetrics.tmDescent);
1649 output->otmTextMetrics.tmInternalLeading = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1650 output->otmTextMetrics.tmExternalLeading = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1651 output->otmTextMetrics.tmAveCharWidth = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1652 output->otmTextMetrics.tmMaxCharWidth = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1653 output->otmTextMetrics.tmOverhang = WDPTOLP(output->otmTextMetrics.tmOverhang);
1654 output->otmAscent = HDPTOLP(output->otmAscent);
1655 output->otmDescent = HDPTOLP(output->otmDescent);
1656 output->otmLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmLineGap));
1657 output->otmsCapEmHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsCapEmHeight));
1658 output->otmsXHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsXHeight));
1659 output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1660 output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1661 output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1662 output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1663 output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1664 output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1665 output->otmMacLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmMacLineGap));
1666 output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1667 output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1668 output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1669 output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1670 output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1671 output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1672 output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1673 output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1674 output->otmsStrikeoutSize = abs(INTERNAL_YDSTOWS(dc,output->otmsStrikeoutSize));
1675 output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1676 output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1677 output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1680 if(output != lpOTM) {
1681 memcpy(lpOTM, output, cbData);
1682 HeapFree(GetProcessHeap(), 0, output);
1688 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1689 but really this should just be a return 0. */
1691 ret = sizeof(*lpOTM);
1696 memset(lpOTM, 0, ret);
1697 lpOTM->otmSize = sizeof(*lpOTM);
1698 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1700 Further fill of the structure not implemented,
1701 Needs real values for the structure members
1711 /***********************************************************************
1712 * GetCharWidthW (GDI32.@)
1713 * GetCharWidth32W (GDI32.@)
1715 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1720 DC * dc = get_dc_ptr( hdc );
1721 if (!dc) return FALSE;
1724 ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1725 else if (dc->funcs->pGetCharWidth)
1726 ret = dc->funcs->pGetCharWidth( dc->physDev, firstChar, lastChar, buffer);
1730 /* convert device units to logical */
1731 for( i = firstChar; i <= lastChar; i++, buffer++ )
1732 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1735 release_dc_ptr( dc );
1740 /***********************************************************************
1741 * GetCharWidthA (GDI32.@)
1742 * GetCharWidth32A (GDI32.@)
1744 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1747 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1752 if(count <= 0) return FALSE;
1754 str = HeapAlloc(GetProcessHeap(), 0, count);
1755 for(i = 0; i < count; i++)
1756 str[i] = (BYTE)(firstChar + i);
1758 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1760 for(i = 0; i < wlen; i++)
1762 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1770 HeapFree(GetProcessHeap(), 0, str);
1771 HeapFree(GetProcessHeap(), 0, wstr);
1777 /***********************************************************************
1778 * ExtTextOutA (GDI32.@)
1782 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1783 const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1791 if (flags & ETO_GLYPH_INDEX)
1792 return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
1794 p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
1797 unsigned int i = 0, j = 0;
1799 lpDxW = HeapAlloc( GetProcessHeap(), 0, wlen*sizeof(INT));
1801 if(IsDBCSLeadByteEx(codepage, str[i])) {
1802 lpDxW[j++] = lpDx[i] + lpDx[i+1];
1805 lpDxW[j++] = lpDx[i];
1811 ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1813 HeapFree( GetProcessHeap(), 0, p );
1814 HeapFree( GetProcessHeap(), 0, lpDxW );
1819 /***********************************************************************
1820 * ExtTextOutW (GDI32.@)
1822 * Draws text using the currently selected font, background color, and text color.
1826 * x,y [I] coordinates of string
1828 * ETO_GRAYED - undocumented on MSDN
1829 * ETO_OPAQUE - use background color for fill the rectangle
1830 * ETO_CLIPPED - clipping text to the rectangle
1831 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1832 * than encoded characters. Implies ETO_IGNORELANGUAGE
1833 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1834 * Affects BiDi ordering
1835 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1836 * ETO_PDY - unimplemented
1837 * ETO_NUMERICSLATIN - unimplemented always assumed -
1838 * do not translate numbers into locale representations
1839 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1840 * lprect [I] dimensions for clipping or/and opaquing
1841 * str [I] text string
1842 * count [I] number of symbols in string
1843 * lpDx [I] optional parameter with distance between drawing characters
1849 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1850 const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1853 LPWSTR reordered_str = (LPWSTR)str;
1854 WORD *glyphs = NULL;
1855 UINT align = GetTextAlign( hdc );
1859 double cosEsc, sinEsc;
1860 INT *deltas = NULL, char_extra;
1863 BOOL done_extents = FALSE;
1864 INT width = 0, xwidth = 0, ywidth = 0;
1866 DC * dc = get_dc_ptr( hdc );
1869 if (!dc) return FALSE;
1871 breakRem = dc->breakRem;
1873 if (flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY))
1874 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY unimplemented\n");
1876 if (!dc->funcs->pExtTextOut && !PATH_IsPathOpen(dc->path))
1878 release_dc_ptr( dc );
1883 type = GetObjectType(hdc);
1884 if(type == OBJ_METADC || type == OBJ_ENHMETADC)
1886 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, flags, lprect, str, count, lpDx);
1887 release_dc_ptr( dc );
1892 flags &= ~ETO_CLIPPED;
1894 if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && count > 0 )
1896 reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1898 BIDI_Reorder( str, count, GCP_REORDER,
1899 ((flags&ETO_RTLREADING)!=0 || (GetTextAlign(hdc)&TA_RTLREADING)!=0)?
1900 WINE_GCPW_FORCE_RTL:WINE_GCPW_FORCE_LTR,
1901 reordered_str, count, NULL );
1903 flags |= ETO_IGNORELANGUAGE;
1906 TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc, x, y, flags,
1907 lprect, debugstr_wn(str, count), count, lpDx);
1909 if(flags & ETO_GLYPH_INDEX)
1910 glyphs = reordered_str;
1913 TRACE("rect: %d,%d - %d,%d\n", lprect->left, lprect->top, lprect->right,
1915 TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
1917 if(align & TA_UPDATECP)
1919 GetCurrentPositionEx( hdc, &pt );
1924 GetTextMetricsW(hdc, &tm);
1925 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1927 if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
1928 lf.lfEscapement = 0;
1930 if(lf.lfEscapement != 0)
1932 cosEsc = cos(lf.lfEscapement * M_PI / 1800);
1933 sinEsc = sin(lf.lfEscapement * M_PI / 1800);
1941 if(flags & (ETO_CLIPPED | ETO_OPAQUE))
1945 if(flags & ETO_GLYPH_INDEX)
1946 GetTextExtentPointI(hdc, glyphs, count, &sz);
1948 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1950 done_extents = TRUE;
1953 rc.right = x + sz.cx;
1954 rc.bottom = y + sz.cy;
1961 LPtoDP(hdc, (POINT*)&rc, 2);
1963 if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
1964 if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
1967 if ((flags & ETO_OPAQUE) && !PATH_IsPathOpen(dc->path))
1968 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1978 LPtoDP(hdc, &pt, 1);
1982 char_extra = GetTextCharacterExtra(hdc);
1983 if(char_extra || dc->breakExtra || breakRem || lpDx || lf.lfEscapement != 0)
1987 deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT));
1988 for(i = 0; i < count; i++)
1990 if(lpDx && (flags & ETO_PDY))
1991 deltas[i] = lpDx[i*2] + char_extra;
1993 deltas[i] = lpDx[i] + char_extra;
1996 if(flags & ETO_GLYPH_INDEX)
1997 GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
1999 GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
2001 deltas[i] = tmpsz.cx;
2004 if (!(flags & ETO_GLYPH_INDEX) && (dc->breakExtra || breakRem) && reordered_str[i] == tm.tmBreakChar)
2006 deltas[i] = deltas[i] + dc->breakExtra;
2013 deltas[i] = INTERNAL_XWSTODS(dc, deltas[i]);
2021 if(flags & ETO_GLYPH_INDEX)
2022 GetTextExtentPointI(hdc, glyphs, count, &sz);
2024 GetTextExtentPointW(hdc, reordered_str, count, &sz);
2025 done_extents = TRUE;
2027 width = INTERNAL_XWSTODS(dc, sz.cx);
2029 xwidth = width * cosEsc;
2030 ywidth = width * sinEsc;
2032 tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
2033 tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
2034 switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
2037 if (align & TA_UPDATECP)
2041 DPtoLP(hdc, &pt, 1);
2042 MoveToEx(hdc, pt.x, pt.y, NULL);
2054 if (align & TA_UPDATECP)
2058 DPtoLP(hdc, &pt, 1);
2059 MoveToEx(hdc, pt.x, pt.y, NULL);
2064 switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
2067 y += tm.tmAscent * cosEsc;
2068 x += tm.tmAscent * sinEsc;
2072 y -= tm.tmDescent * cosEsc;
2073 x -= tm.tmDescent * sinEsc;
2080 if (GetBkMode(hdc) != TRANSPARENT && !PATH_IsPathOpen(dc->path))
2082 if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
2084 if(!(flags & ETO_OPAQUE) || x < rc.left || x + width >= rc.right ||
2085 y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
2089 rc.right = x + width;
2090 rc.top = y - tm.tmAscent;
2091 rc.bottom = y + tm.tmDescent;
2092 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
2097 if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
2099 HFONT orig_font = dc->hFont, cur_font;
2101 INT span = 0, *offsets = NULL;
2104 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2105 for(i = 0; i < count; i++)
2107 WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
2108 if(cur_font != dc->hFont)
2113 offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
2118 for(j = 1; j < count; j++)
2120 GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
2121 offsets[j] = offsets[j-1] + INTERNAL_XWSTODS(dc, tmpsz.cx);
2126 for(j = 1; j < count; j++)
2127 offsets[j] = offsets[j-1] + deltas[j];
2132 if (PATH_IsPathOpen(dc->path))
2133 ret = PATH_ExtTextOut(dc, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
2134 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2135 glyphs, span, deltas ? deltas + i - span : NULL);
2137 dc->funcs->pExtTextOut(dc->physDev, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
2138 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2139 glyphs, span, deltas ? deltas + i - span : NULL);
2142 SelectObject(hdc, cur_font);
2144 glyphs[span++] = glyph;
2148 if (PATH_IsPathOpen(dc->path))
2149 ret = PATH_ExtTextOut(dc, x + (offsets ? offsets[count - span] * cosEsc : 0),
2150 y - (offsets ? offsets[count - span] * sinEsc : 0),
2151 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2152 glyphs, span, deltas ? deltas + count - span : NULL);
2154 ret = dc->funcs->pExtTextOut(dc->physDev, x + (offsets ? offsets[count - span] * cosEsc : 0),
2155 y - (offsets ? offsets[count - span] * sinEsc : 0),
2156 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2157 glyphs, span, deltas ? deltas + count - span : NULL);
2158 SelectObject(hdc, orig_font);
2159 HeapFree(GetProcessHeap(), 0, offsets);
2165 if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
2167 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2168 GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
2169 flags |= ETO_GLYPH_INDEX;
2172 if (PATH_IsPathOpen(dc->path))
2173 ret = PATH_ExtTextOut(dc, x, y, (flags & ~ETO_OPAQUE), &rc,
2174 glyphs ? glyphs : reordered_str, count, deltas);
2176 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, (flags & ~ETO_OPAQUE), &rc,
2177 glyphs ? glyphs : reordered_str, count, deltas);
2181 HeapFree(GetProcessHeap(), 0, deltas);
2182 if(glyphs != reordered_str)
2183 HeapFree(GetProcessHeap(), 0, glyphs);
2184 if(reordered_str != str)
2185 HeapFree(GetProcessHeap(), 0, reordered_str);
2187 release_dc_ptr( dc );
2189 if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2191 int underlinePos, strikeoutPos;
2192 int underlineWidth, strikeoutWidth;
2193 UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2194 OUTLINETEXTMETRICW* otm = NULL;
2199 underlineWidth = tm.tmAscent / 20 + 1;
2200 strikeoutPos = tm.tmAscent / 2;
2201 strikeoutWidth = underlineWidth;
2205 otm = HeapAlloc(GetProcessHeap(), 0, size);
2206 GetOutlineTextMetricsW(hdc, size, otm);
2207 underlinePos = otm->otmsUnderscorePosition;
2208 underlineWidth = otm->otmsUnderscoreSize;
2209 strikeoutPos = otm->otmsStrikeoutPosition;
2210 strikeoutWidth = otm->otmsStrikeoutSize;
2211 HeapFree(GetProcessHeap(), 0, otm);
2214 if (PATH_IsPathOpen(dc->path))
2218 HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2220 hbrush = SelectObject(hdc, hbrush);
2221 hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2225 pts[0].x = x - underlinePos * sinEsc;
2226 pts[0].y = y - underlinePos * cosEsc;
2227 pts[1].x = x + xwidth - underlinePos * sinEsc;
2228 pts[1].y = y - ywidth - underlinePos * cosEsc;
2229 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2230 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2231 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2232 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2233 pts[4].x = pts[0].x;
2234 pts[4].y = pts[0].y;
2235 DPtoLP(hdc, pts, 5);
2236 Polygon(hdc, pts, 5);
2241 pts[0].x = x - strikeoutPos * sinEsc;
2242 pts[0].y = y - strikeoutPos * cosEsc;
2243 pts[1].x = x + xwidth - strikeoutPos * sinEsc;
2244 pts[1].y = y - ywidth - strikeoutPos * cosEsc;
2245 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2246 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2247 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2248 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2249 pts[4].x = pts[0].x;
2250 pts[4].y = pts[0].y;
2251 DPtoLP(hdc, pts, 5);
2252 Polygon(hdc, pts, 5);
2255 SelectObject(hdc, hpen);
2256 hbrush = SelectObject(hdc, hbrush);
2257 DeleteObject(hbrush);
2261 POINT pts[2], oldpt;
2266 hpen = CreatePen(PS_SOLID, underlineWidth, GetTextColor(hdc));
2267 hpen = SelectObject(hdc, hpen);
2270 pts[1].x = x + xwidth;
2271 pts[1].y = y - ywidth;
2272 DPtoLP(hdc, pts, 2);
2273 MoveToEx(hdc, pts[0].x - underlinePos * sinEsc, pts[0].y - underlinePos * cosEsc, &oldpt);
2274 LineTo(hdc, pts[1].x - underlinePos * sinEsc, pts[1].y - underlinePos * cosEsc);
2275 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2276 DeleteObject(SelectObject(hdc, hpen));
2281 hpen = CreatePen(PS_SOLID, strikeoutWidth, GetTextColor(hdc));
2282 hpen = SelectObject(hdc, hpen);
2285 pts[1].x = x + xwidth;
2286 pts[1].y = y - ywidth;
2287 DPtoLP(hdc, pts, 2);
2288 MoveToEx(hdc, pts[0].x - strikeoutPos * sinEsc, pts[0].y - strikeoutPos * cosEsc, &oldpt);
2289 LineTo(hdc, pts[1].x - strikeoutPos * sinEsc, pts[1].y - strikeoutPos * cosEsc);
2290 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2291 DeleteObject(SelectObject(hdc, hpen));
2300 /***********************************************************************
2301 * TextOutA (GDI32.@)
2303 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2305 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2309 /***********************************************************************
2310 * TextOutW (GDI32.@)
2312 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2314 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2318 /***********************************************************************
2319 * PolyTextOutA (GDI32.@)
2323 BOOL WINAPI PolyTextOutA( HDC hdc, const POLYTEXTA *pptxt, INT cStrings )
2325 for (; cStrings>0; cStrings--, pptxt++)
2326 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2333 /***********************************************************************
2334 * PolyTextOutW (GDI32.@)
2336 * Draw several Strings
2342 BOOL WINAPI PolyTextOutW( HDC hdc, const POLYTEXTW *pptxt, INT cStrings )
2344 for (; cStrings>0; cStrings--, pptxt++)
2345 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2351 /* FIXME: all following APIs ******************************************/
2354 /***********************************************************************
2355 * SetMapperFlags (GDI32.@)
2357 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
2359 DC *dc = get_dc_ptr( hDC );
2362 if(dc->funcs->pSetMapperFlags)
2364 ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
2365 /* FIXME: ret is just a success flag, we should return a proper value */
2368 FIXME("(%p, 0x%08x): stub - harmless\n", hDC, dwFlag);
2369 release_dc_ptr( dc );
2373 /***********************************************************************
2374 * GetAspectRatioFilterEx (GDI32.@)
2376 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2378 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2383 /***********************************************************************
2384 * GetCharABCWidthsA (GDI32.@)
2386 * See GetCharABCWidthsW.
2388 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2391 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
2396 if(count <= 0) return FALSE;
2398 str = HeapAlloc(GetProcessHeap(), 0, count);
2399 for(i = 0; i < count; i++)
2400 str[i] = (BYTE)(firstChar + i);
2402 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
2404 for(i = 0; i < wlen; i++)
2406 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2414 HeapFree(GetProcessHeap(), 0, str);
2415 HeapFree(GetProcessHeap(), 0, wstr);
2421 /******************************************************************************
2422 * GetCharABCWidthsW [GDI32.@]
2424 * Retrieves widths of characters in range.
2427 * hdc [I] Handle of device context
2428 * firstChar [I] First character in range to query
2429 * lastChar [I] Last character in range to query
2430 * abc [O] Address of character-width structure
2433 * Only works with TrueType fonts
2439 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2442 DC *dc = get_dc_ptr(hdc);
2446 if (!dc) return FALSE;
2450 release_dc_ptr( dc );
2455 ret = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
2461 /* convert device units to logical */
2462 for( i = firstChar; i <= lastChar; i++, abc++ ) {
2463 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2464 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2465 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2470 release_dc_ptr( dc );
2475 /******************************************************************************
2476 * GetCharABCWidthsI [GDI32.@]
2478 * Retrieves widths of characters in range.
2481 * hdc [I] Handle of device context
2482 * firstChar [I] First glyphs in range to query
2483 * count [I] Last glyphs in range to query
2484 * pgi [i] Array of glyphs to query
2485 * abc [O] Address of character-width structure
2488 * Only works with TrueType fonts
2494 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2495 LPWORD pgi, LPABC abc)
2497 DC *dc = get_dc_ptr(hdc);
2501 if (!dc) return FALSE;
2505 release_dc_ptr( dc );
2510 ret = WineEngGetCharABCWidthsI( dc->gdiFont, firstChar, count, pgi, abc );
2516 /* convert device units to logical */
2517 for( i = 0; i < count; i++, abc++ ) {
2518 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2519 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2520 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2525 release_dc_ptr( dc );
2530 /***********************************************************************
2531 * GetGlyphOutlineA (GDI32.@)
2533 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2534 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2535 LPVOID lpBuffer, const MAT2 *lpmat2 )
2541 if(!(fuFormat & GGO_GLYPH_INDEX)) {
2544 if(uChar > 0xff) { /* but, 2 bytes character only */
2546 mbchs[0] = (uChar & 0xff00) >> 8;
2547 mbchs[1] = (uChar & 0xff);
2550 mbchs[0] = (uChar & 0xff);
2552 p = FONT_mbtowc(hdc, mbchs, len, NULL, NULL);
2556 ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
2558 HeapFree(GetProcessHeap(), 0, p);
2562 /***********************************************************************
2563 * GetGlyphOutlineW (GDI32.@)
2565 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2566 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2567 LPVOID lpBuffer, const MAT2 *lpmat2 )
2569 DC *dc = get_dc_ptr(hdc);
2572 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2573 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2575 if(!dc) return GDI_ERROR;
2578 ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
2579 cbBuffer, lpBuffer, lpmat2);
2583 release_dc_ptr( dc );
2588 /***********************************************************************
2589 * CreateScalableFontResourceA (GDI32.@)
2591 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2592 LPCSTR lpszResourceFile,
2593 LPCSTR lpszFontFile,
2594 LPCSTR lpszCurrentPath )
2598 /* fHidden=1 - only visible for the calling app, read-only, not
2599 * enumbered with EnumFonts/EnumFontFamilies
2600 * lpszCurrentPath can be NULL
2602 FIXME("(%d,%s,%s,%s): stub\n",
2603 fHidden, debugstr_a(lpszResourceFile), debugstr_a(lpszFontFile),
2604 debugstr_a(lpszCurrentPath) );
2606 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2607 if ((f = CreateFileA(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2609 SetLastError(ERROR_FILE_EXISTS);
2612 return FALSE; /* create failed */
2615 /***********************************************************************
2616 * CreateScalableFontResourceW (GDI32.@)
2618 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2619 LPCWSTR lpszResourceFile,
2620 LPCWSTR lpszFontFile,
2621 LPCWSTR lpszCurrentPath )
2623 FIXME("(%d,%p,%p,%p): stub\n",
2624 fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
2625 return FALSE; /* create failed */
2628 /*************************************************************************
2629 * GetKerningPairsA (GDI32.@)
2631 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2632 LPKERNINGPAIR kern_pairA )
2637 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2638 KERNINGPAIR *kern_pairW;
2640 if (!cPairs && kern_pairA)
2642 SetLastError(ERROR_INVALID_PARAMETER);
2646 charset = GetTextCharset(hDC);
2647 if (!TranslateCharsetInfo(ULongToPtr(charset), &csi, TCI_SRCCHARSET))
2649 FIXME("Can't find codepage for charset %d\n", charset);
2652 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2653 * to fail on an invalid character for CP_SYMBOL.
2655 cpi.DefaultChar[0] = 0;
2656 if (csi.ciACP != CP_SYMBOL && !GetCPInfo(csi.ciACP, &cpi))
2658 FIXME("Can't find codepage %u info\n", csi.ciACP);
2661 TRACE("charset %d => codepage %u\n", charset, csi.ciACP);
2663 total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2664 if (!total_kern_pairs) return 0;
2666 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2667 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2669 for (i = 0; i < total_kern_pairs; i++)
2673 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2676 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2679 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2684 if (kern_pairs_copied >= cPairs) break;
2686 kern_pairA->wFirst = (BYTE)first;
2687 kern_pairA->wSecond = (BYTE)second;
2688 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2691 kern_pairs_copied++;
2694 HeapFree(GetProcessHeap(), 0, kern_pairW);
2696 return kern_pairs_copied;
2699 /*************************************************************************
2700 * GetKerningPairsW (GDI32.@)
2702 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2703 LPKERNINGPAIR lpKerningPairs )
2708 TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2710 if (!cPairs && lpKerningPairs)
2712 SetLastError(ERROR_INVALID_PARAMETER);
2716 dc = get_dc_ptr(hDC);
2720 ret = WineEngGetKerningPairs(dc->gdiFont, cPairs, lpKerningPairs);
2722 release_dc_ptr( dc );
2726 /*************************************************************************
2727 * TranslateCharsetInfo [GDI32.@]
2729 * Fills a CHARSETINFO structure for a character set, code page, or
2730 * font. This allows making the correspondence between different labels
2731 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2732 * of the same encoding.
2734 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2735 * only one codepage should be set in *lpSrc.
2738 * TRUE on success, FALSE on failure.
2741 BOOL WINAPI TranslateCharsetInfo(
2742 LPDWORD lpSrc, /* [in]
2743 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2744 if flags == TCI_SRCCHARSET: a character set value
2745 if flags == TCI_SRCCODEPAGE: a code page value
2747 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2748 DWORD flags /* [in] determines interpretation of lpSrc */)
2752 case TCI_SRCFONTSIG:
2753 while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
2755 case TCI_SRCCODEPAGE:
2756 while (PtrToUlong(lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
2758 case TCI_SRCCHARSET:
2759 while (PtrToUlong(lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
2764 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2765 memcpy(lpCs, &FONT_tci[index], sizeof(CHARSETINFO));
2769 /*************************************************************************
2770 * GetFontLanguageInfo (GDI32.@)
2772 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2774 FONTSIGNATURE fontsig;
2775 static const DWORD GCP_DBCS_MASK=0x003F0000,
2776 GCP_DIACRITIC_MASK=0x00000000,
2777 FLI_GLYPHS_MASK=0x00000000,
2778 GCP_GLYPHSHAPE_MASK=0x00000040,
2779 GCP_KASHIDA_MASK=0x00000000,
2780 GCP_LIGATE_MASK=0x00000000,
2781 GCP_USEKERNING_MASK=0x00000000,
2782 GCP_REORDER_MASK=0x00000060;
2786 GetTextCharsetInfo( hdc, &fontsig, 0 );
2787 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2789 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2792 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2793 result|=GCP_DIACRITIC;
2795 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2798 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2799 result|=GCP_GLYPHSHAPE;
2801 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2802 result|=GCP_KASHIDA;
2804 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2807 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2808 result|=GCP_USEKERNING;
2810 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2811 if( GetTextAlign( hdc) & TA_RTLREADING )
2812 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2813 result|=GCP_REORDER;
2819 /*************************************************************************
2820 * GetFontData [GDI32.@]
2822 * Retrieve data for TrueType font.
2826 * success: Number of bytes returned
2827 * failure: GDI_ERROR
2831 * Calls SetLastError()
2834 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2835 LPVOID buffer, DWORD length)
2837 DC *dc = get_dc_ptr(hdc);
2838 DWORD ret = GDI_ERROR;
2840 if(!dc) return GDI_ERROR;
2843 ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2845 release_dc_ptr( dc );
2849 /*************************************************************************
2850 * GetGlyphIndicesA [GDI32.@]
2852 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2853 LPWORD pgi, DWORD flags)
2859 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2860 hdc, debugstr_an(lpstr, count), count, pgi, flags);
2862 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2863 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2864 HeapFree(GetProcessHeap(), 0, lpstrW);
2869 /*************************************************************************
2870 * GetGlyphIndicesW [GDI32.@]
2872 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2873 LPWORD pgi, DWORD flags)
2875 DC *dc = get_dc_ptr(hdc);
2876 DWORD ret = GDI_ERROR;
2878 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2879 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2881 if(!dc) return GDI_ERROR;
2884 ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2886 release_dc_ptr( dc );
2890 /*************************************************************************
2891 * GetCharacterPlacementA [GDI32.@]
2893 * See GetCharacterPlacementW.
2896 * the web browser control of ie4 calls this with dwFlags=0
2899 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2900 INT nMaxExtent, GCP_RESULTSA *lpResults,
2905 GCP_RESULTSW resultsW;
2909 TRACE("%s, %d, %d, 0x%08x\n",
2910 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2912 /* both structs are equal in size */
2913 memcpy(&resultsW, lpResults, sizeof(resultsW));
2915 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2916 if(lpResults->lpOutString)
2917 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2919 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2921 lpResults->nGlyphs = resultsW.nGlyphs;
2922 lpResults->nMaxFit = resultsW.nMaxFit;
2924 if(lpResults->lpOutString) {
2925 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2926 lpResults->lpOutString, uCount, NULL, NULL );
2929 HeapFree(GetProcessHeap(), 0, lpStringW);
2930 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2935 /*************************************************************************
2936 * GetCharacterPlacementW [GDI32.@]
2938 * Retrieve information about a string. This includes the width, reordering,
2939 * Glyphing and so on.
2943 * The width and height of the string if successful, 0 if failed.
2947 * All flags except GCP_REORDER are not yet implemented.
2948 * Reordering is not 100% complient to the Windows BiDi method.
2949 * Caret positioning is not yet implemented for BiDi.
2950 * Classes are not yet implemented.
2954 GetCharacterPlacementW(
2955 HDC hdc, /* [in] Device context for which the rendering is to be done */
2956 LPCWSTR lpString, /* [in] The string for which information is to be returned */
2957 INT uCount, /* [in] Number of WORDS in string. */
2958 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
2959 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2960 DWORD dwFlags /* [in] Flags specifying how to process the string */
2967 TRACE("%s, %d, %d, 0x%08x\n",
2968 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2970 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2971 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2972 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2973 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2974 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2976 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08x ignored\n", dwFlags);
2977 if(lpResults->lpClass) FIXME("classes not implemented\n");
2978 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2979 FIXME("Caret positions for complex scripts not implemented\n");
2981 nSet = (UINT)uCount;
2982 if(nSet > lpResults->nGlyphs)
2983 nSet = lpResults->nGlyphs;
2985 /* return number of initialized fields */
2986 lpResults->nGlyphs = nSet;
2988 if((dwFlags&GCP_REORDER)==0 )
2990 /* Treat the case where no special handling was requested in a fastpath way */
2991 /* copy will do if the GCP_REORDER flag is not set */
2992 if(lpResults->lpOutString)
2993 memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
2995 if(lpResults->lpOrder)
2997 for(i = 0; i < nSet; i++)
2998 lpResults->lpOrder[i] = i;
3002 BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
3003 nSet, lpResults->lpOrder );
3006 /* FIXME: Will use the placement chars */
3007 if (lpResults->lpDx)
3010 for (i = 0; i < nSet; i++)
3012 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
3013 lpResults->lpDx[i]= c;
3017 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
3021 lpResults->lpCaretPos[0] = 0;
3022 for (i = 1; i < nSet; i++)
3023 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
3024 lpResults->lpCaretPos[i] = (pos += size.cx);
3027 if(lpResults->lpGlyphs)
3028 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
3030 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
3031 ret = MAKELONG(size.cx, size.cy);
3036 /*************************************************************************
3037 * GetCharABCWidthsFloatA [GDI32.@]
3039 * See GetCharABCWidthsFloatW.
3041 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3043 INT i, wlen, count = (INT)(last - first + 1);
3048 if (count <= 0) return FALSE;
3050 str = HeapAlloc(GetProcessHeap(), 0, count);
3052 for(i = 0; i < count; i++)
3053 str[i] = (BYTE)(first + i);
3055 wstr = FONT_mbtowc( hdc, str, count, &wlen, NULL );
3057 for (i = 0; i < wlen; i++)
3059 if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
3067 HeapFree( GetProcessHeap(), 0, str );
3068 HeapFree( GetProcessHeap(), 0, wstr );
3073 /*************************************************************************
3074 * GetCharABCWidthsFloatW [GDI32.@]
3076 * Retrieves widths of a range of characters.
3079 * hdc [I] Handle to device context.
3080 * first [I] First character in range to query.
3081 * last [I] Last character in range to query.
3082 * abcf [O] Array of LPABCFLOAT structures.
3089 * Only works with TrueType fonts. It also doesn't return real
3090 * floats but converted integers because it's implemented on
3091 * top of GetCharABCWidthsW.
3093 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3096 unsigned int i, size = sizeof(ABC) * (last - first + 1);
3099 TRACE("%p, %d, %d, %p - partial stub\n", hdc, first, last, abcf);
3101 abc = HeapAlloc( GetProcessHeap(), 0, size );
3102 if (!abc) return FALSE;
3104 ret = GetCharABCWidthsW( hdc, first, last, abc );
3107 for (i = first; i <= last; i++, abc++, abcf++)
3109 abcf->abcfA = abc->abcA;
3110 abcf->abcfB = abc->abcB;
3111 abcf->abcfC = abc->abcC;
3114 HeapFree( GetProcessHeap(), 0, abc );
3118 /*************************************************************************
3119 * GetCharWidthFloatA [GDI32.@]
3121 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
3122 UINT iLastChar, PFLOAT pxBuffer)
3124 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3128 /*************************************************************************
3129 * GetCharWidthFloatW [GDI32.@]
3131 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
3132 UINT iLastChar, PFLOAT pxBuffer)
3134 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3139 /***********************************************************************
3141 * Font Resource API *
3143 ***********************************************************************/
3145 /***********************************************************************
3146 * AddFontResourceA (GDI32.@)
3148 INT WINAPI AddFontResourceA( LPCSTR str )
3150 return AddFontResourceExA( str, 0, NULL);
3153 /***********************************************************************
3154 * AddFontResourceW (GDI32.@)
3156 INT WINAPI AddFontResourceW( LPCWSTR str )
3158 return AddFontResourceExW(str, 0, NULL);
3162 /***********************************************************************
3163 * AddFontResourceExA (GDI32.@)
3165 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3167 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3168 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3171 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3172 ret = AddFontResourceExW(strW, fl, pdv);
3173 HeapFree(GetProcessHeap(), 0, strW);
3177 static BOOL CALLBACK load_enumed_resource(HMODULE hModule, LPCWSTR type, LPWSTR name, LONG_PTR lParam)
3179 HRSRC rsrc = FindResourceW(hModule, name, type);
3180 HGLOBAL hMem = LoadResource(hModule, rsrc);
3181 LPVOID *pMem = LockResource(hMem);
3182 int *num_total = (int *)lParam;
3185 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type));
3186 if (!AddFontMemResourceEx(pMem, SizeofResource(hModule, rsrc), NULL, &num_in_res))
3188 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule, hMem);
3192 *num_total += num_in_res;
3196 /***********************************************************************
3197 * AddFontResourceExW (GDI32.@)
3199 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3201 int ret = WineEngAddFontResourceEx(str, fl, pdv);
3204 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3205 HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
3206 if (hModule != NULL)
3208 int num_resources = 0;
3209 LPWSTR rt_font = (LPWSTR)((ULONG_PTR)8); /* we don't want to include winuser.h */
3211 TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3212 wine_dbgstr_w(str));
3213 if (EnumResourceNamesW(hModule, rt_font, load_enumed_resource, (LONG_PTR)&num_resources))
3214 ret = num_resources;
3215 FreeLibrary(hModule);
3221 /***********************************************************************
3222 * RemoveFontResourceA (GDI32.@)
3224 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3226 return RemoveFontResourceExA(str, 0, 0);
3229 /***********************************************************************
3230 * RemoveFontResourceW (GDI32.@)
3232 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3234 return RemoveFontResourceExW(str, 0, 0);
3237 /***********************************************************************
3238 * AddFontMemResourceEx (GDI32.@)
3240 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3242 return WineEngAddFontMemResourceEx(pbFont, cbFont, pdv, pcFonts);
3245 /***********************************************************************
3246 * RemoveFontMemResourceEx (GDI32.@)
3248 BOOL WINAPI RemoveFontMemResourceEx( HANDLE fh )
3250 FIXME("(%p) stub\n", fh);
3254 /***********************************************************************
3255 * RemoveFontResourceExA (GDI32.@)
3257 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3259 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3260 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3263 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3264 ret = RemoveFontResourceExW(strW, fl, pdv);
3265 HeapFree(GetProcessHeap(), 0, strW);
3269 /***********************************************************************
3270 * RemoveFontResourceExW (GDI32.@)
3272 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3274 return WineEngRemoveFontResourceEx(str, fl, pdv);
3277 /***********************************************************************
3278 * GetTextCharset (GDI32.@)
3280 UINT WINAPI GetTextCharset(HDC hdc)
3282 /* MSDN docs say this is equivalent */
3283 return GetTextCharsetInfo(hdc, NULL, 0);
3286 /***********************************************************************
3287 * GetTextCharsetInfo (GDI32.@)
3289 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3291 UINT ret = DEFAULT_CHARSET;
3292 DC *dc = get_dc_ptr(hdc);
3297 ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
3299 release_dc_ptr( dc );
3302 if (ret == DEFAULT_CHARSET && fs)
3303 memset(fs, 0, sizeof(FONTSIGNATURE));
3307 /***********************************************************************
3308 * GdiGetCharDimensions (GDI32.@)
3310 * Gets the average width of the characters in the English alphabet.
3313 * hdc [I] Handle to the device context to measure on.
3314 * lptm [O] Pointer to memory to store the text metrics into.
3315 * height [O] On exit, the maximum height of characters in the English alphabet.
3318 * The average width of characters in the English alphabet.
3321 * This function is used by the dialog manager to get the size of a dialog
3322 * unit. It should also be used by other pieces of code that need to know
3323 * the size of a dialog unit in logical units without having access to the
3324 * window handle of the dialog.
3325 * Windows caches the font metrics from this function, but we don't and
3326 * there doesn't appear to be an immediate advantage to do so.
3329 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3331 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3334 static const WCHAR alphabet[] = {
3335 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3336 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3337 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3339 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3341 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3343 if (height) *height = sz.cy;
3344 return (sz.cx / 26 + 1) / 2;
3347 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3349 FIXME("(%d): stub\n", fEnableEUDC);
3353 /***********************************************************************
3354 * GetCharWidthI (GDI32.@)
3356 * Retrieve widths of characters.
3359 * hdc [I] Handle to a device context.
3360 * first [I] First glyph in range to query.
3361 * count [I] Number of glyph indices to query.
3362 * glyphs [I] Array of glyphs to query.
3363 * buffer [O] Buffer to receive character widths.
3366 * Only works with TrueType fonts.
3372 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3377 TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3379 if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3382 if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3384 HeapFree(GetProcessHeap(), 0, abc);
3388 for (i = 0; i < count; i++)
3389 buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3391 HeapFree(GetProcessHeap(), 0, abc);
3395 /***********************************************************************
3396 * GetFontUnicodeRanges (GDI32.@)
3398 * Retrieve a list of supported Unicode characters in a font.
3401 * hdc [I] Handle to a device context.
3402 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3405 * Success: Number of bytes written to the buffer pointed to by lpgs.
3409 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3412 DC *dc = get_dc_ptr(hdc);
3414 TRACE("(%p, %p)\n", hdc, lpgs);
3418 if (dc->gdiFont) ret = WineEngGetFontUnicodeRanges(dc->gdiFont, lpgs);
3424 /*************************************************************
3425 * FontIsLinked (GDI32.@)
3427 BOOL WINAPI FontIsLinked(HDC hdc)
3429 DC *dc = get_dc_ptr(hdc);
3432 if (!dc) return FALSE;
3433 if (dc->gdiFont) ret = WineEngFontIsLinked(dc->gdiFont);
3435 TRACE("returning %d\n", ret);