systray: Add support for NIS_HIDDEN flag.
[wine.git] / dlls / gdi32 / font.c
blob28853fbabebba7bf1a67dad21f4589c98d34fe13
1 /*
2 * GDI font objects
4 * Copyright 1993 Alexandre Julliard
5 * 1997 Alex Korobka
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
23 #include "config.h"
24 #include "wine/port.h"
26 #include <stdarg.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <assert.h>
30 #include "winerror.h"
31 #include "windef.h"
32 #include "winbase.h"
33 #include "winnls.h"
34 #include "wownt32.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)
48 FLOAT floatWidth;
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)
61 FLOAT floatHeight;
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)
71 POINT pt[2];
72 pt[0].x = pt[0].y = 0;
73 pt[1].x = width;
74 pt[1].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)
81 POINT pt[2];
82 pt[0].x = pt[0].y = 0;
83 pt[1].x = 0;
84 pt[1].y = height;
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_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
91 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
92 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
93 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj );
95 static const struct gdi_obj_funcs font_funcs =
97 FONT_SelectObject, /* pSelectObject */
98 FONT_GetObject16, /* pGetObject16 */
99 FONT_GetObjectA, /* pGetObjectA */
100 FONT_GetObjectW, /* pGetObjectW */
101 NULL, /* pUnrealizeObject */
102 FONT_DeleteObject /* pDeleteObject */
105 #define ENUM_UNICODE 0x00000001
106 #define ENUM_CALLED 0x00000002
108 typedef struct
110 GDIOBJHDR header;
111 LOGFONTW logfont;
112 } FONTOBJ;
114 typedef struct
116 LPLOGFONT16 lpLogFontParam;
117 FONTENUMPROC16 lpEnumFunc;
118 LPARAM lpData;
120 LPNEWTEXTMETRICEX16 lpTextMetric;
121 LPENUMLOGFONTEX16 lpLogFont;
122 SEGPTR segTextMetric;
123 SEGPTR segLogFont;
124 DWORD dwFlags;
125 HDC hdc;
126 } fontEnum16;
128 typedef struct
130 LPLOGFONTW lpLogFontParam;
131 FONTENUMPROCW lpEnumFunc;
132 LPARAM lpData;
133 DWORD dwFlags;
134 HDC hdc;
135 } fontEnum32;
138 * For TranslateCharsetInfo
140 #define MAXTCIINDEX 32
141 static const CHARSETINFO FONT_tci[MAXTCIINDEX] = {
142 /* ANSI */
143 { ANSI_CHARSET, 1252, {{0,0,0,0},{FS_LATIN1,0}} },
144 { EASTEUROPE_CHARSET, 1250, {{0,0,0,0},{FS_LATIN2,0}} },
145 { RUSSIAN_CHARSET, 1251, {{0,0,0,0},{FS_CYRILLIC,0}} },
146 { GREEK_CHARSET, 1253, {{0,0,0,0},{FS_GREEK,0}} },
147 { TURKISH_CHARSET, 1254, {{0,0,0,0},{FS_TURKISH,0}} },
148 { HEBREW_CHARSET, 1255, {{0,0,0,0},{FS_HEBREW,0}} },
149 { ARABIC_CHARSET, 1256, {{0,0,0,0},{FS_ARABIC,0}} },
150 { BALTIC_CHARSET, 1257, {{0,0,0,0},{FS_BALTIC,0}} },
151 { VIETNAMESE_CHARSET, 1258, {{0,0,0,0},{FS_VIETNAMESE,0}} },
152 /* reserved by ANSI */
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}} },
158 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
159 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
160 /* ANSI and OEM */
161 { THAI_CHARSET, 874, {{0,0,0,0},{FS_THAI,0}} },
162 { SHIFTJIS_CHARSET, 932, {{0,0,0,0},{FS_JISJAPAN,0}} },
163 { GB2312_CHARSET, 936, {{0,0,0,0},{FS_CHINESESIMP,0}} },
164 { HANGEUL_CHARSET, 949, {{0,0,0,0},{FS_WANSUNG,0}} },
165 { CHINESEBIG5_CHARSET, 950, {{0,0,0,0},{FS_CHINESETRAD,0}} },
166 { JOHAB_CHARSET, 1361, {{0,0,0,0},{FS_JOHAB,0}} },
167 /* reserved for alternate ANSI and OEM */
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 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
175 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
176 /* reserved for system */
177 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
178 { SYMBOL_CHARSET, CP_SYMBOL, {{0,0,0,0},{FS_SYMBOL,0}} }
181 /***********************************************************************
182 * LOGFONT conversion functions.
184 static void FONT_LogFontWTo16( const LOGFONTW* font32, LPLOGFONT16 font16 )
186 font16->lfHeight = font32->lfHeight;
187 font16->lfWidth = font32->lfWidth;
188 font16->lfEscapement = font32->lfEscapement;
189 font16->lfOrientation = font32->lfOrientation;
190 font16->lfWeight = font32->lfWeight;
191 font16->lfItalic = font32->lfItalic;
192 font16->lfUnderline = font32->lfUnderline;
193 font16->lfStrikeOut = font32->lfStrikeOut;
194 font16->lfCharSet = font32->lfCharSet;
195 font16->lfOutPrecision = font32->lfOutPrecision;
196 font16->lfClipPrecision = font32->lfClipPrecision;
197 font16->lfQuality = font32->lfQuality;
198 font16->lfPitchAndFamily = font32->lfPitchAndFamily;
199 WideCharToMultiByte( CP_ACP, 0, font32->lfFaceName, -1,
200 font16->lfFaceName, LF_FACESIZE, NULL, NULL );
201 font16->lfFaceName[LF_FACESIZE-1] = 0;
204 static void FONT_LogFont16ToW( const LOGFONT16 *font16, LPLOGFONTW font32 )
206 font32->lfHeight = font16->lfHeight;
207 font32->lfWidth = font16->lfWidth;
208 font32->lfEscapement = font16->lfEscapement;
209 font32->lfOrientation = font16->lfOrientation;
210 font32->lfWeight = font16->lfWeight;
211 font32->lfItalic = font16->lfItalic;
212 font32->lfUnderline = font16->lfUnderline;
213 font32->lfStrikeOut = font16->lfStrikeOut;
214 font32->lfCharSet = font16->lfCharSet;
215 font32->lfOutPrecision = font16->lfOutPrecision;
216 font32->lfClipPrecision = font16->lfClipPrecision;
217 font32->lfQuality = font16->lfQuality;
218 font32->lfPitchAndFamily = font16->lfPitchAndFamily;
219 MultiByteToWideChar( CP_ACP, 0, font16->lfFaceName, -1, font32->lfFaceName, LF_FACESIZE );
220 font32->lfFaceName[LF_FACESIZE-1] = 0;
223 static void FONT_LogFontAToW( const LOGFONTA *fontA, LPLOGFONTW fontW )
225 memcpy(fontW, fontA, sizeof(LOGFONTA) - LF_FACESIZE);
226 MultiByteToWideChar(CP_ACP, 0, fontA->lfFaceName, -1, fontW->lfFaceName,
227 LF_FACESIZE);
228 fontW->lfFaceName[LF_FACESIZE-1] = 0;
231 static void FONT_LogFontWToA( const LOGFONTW *fontW, LPLOGFONTA fontA )
233 memcpy(fontA, fontW, sizeof(LOGFONTA) - LF_FACESIZE);
234 WideCharToMultiByte(CP_ACP, 0, fontW->lfFaceName, -1, fontA->lfFaceName,
235 LF_FACESIZE, NULL, NULL);
236 fontA->lfFaceName[LF_FACESIZE-1] = 0;
239 static void FONT_EnumLogFontExWTo16( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEX16 font16 )
241 FONT_LogFontWTo16( (const LOGFONTW *)fontW, (LPLOGFONT16)font16);
243 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
244 (LPSTR) font16->elfFullName, LF_FULLFACESIZE, NULL, NULL );
245 font16->elfFullName[LF_FULLFACESIZE-1] = '\0';
246 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
247 (LPSTR) font16->elfStyle, LF_FACESIZE, NULL, NULL );
248 font16->elfStyle[LF_FACESIZE-1] = '\0';
249 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
250 (LPSTR) font16->elfScript, LF_FACESIZE, NULL, NULL );
251 font16->elfScript[LF_FACESIZE-1] = '\0';
254 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEXA fontA )
256 FONT_LogFontWToA( (const LOGFONTW *)fontW, (LPLOGFONTA)fontA);
258 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
259 (LPSTR) fontA->elfFullName, LF_FULLFACESIZE, NULL, NULL );
260 fontA->elfFullName[LF_FULLFACESIZE-1] = '\0';
261 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
262 (LPSTR) fontA->elfStyle, LF_FACESIZE, NULL, NULL );
263 fontA->elfStyle[LF_FACESIZE-1] = '\0';
264 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
265 (LPSTR) fontA->elfScript, LF_FACESIZE, NULL, NULL );
266 fontA->elfScript[LF_FACESIZE-1] = '\0';
269 /***********************************************************************
270 * TEXTMETRIC conversion functions.
272 static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
274 ptmA->tmHeight = ptmW->tmHeight;
275 ptmA->tmAscent = ptmW->tmAscent;
276 ptmA->tmDescent = ptmW->tmDescent;
277 ptmA->tmInternalLeading = ptmW->tmInternalLeading;
278 ptmA->tmExternalLeading = ptmW->tmExternalLeading;
279 ptmA->tmAveCharWidth = ptmW->tmAveCharWidth;
280 ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth;
281 ptmA->tmWeight = ptmW->tmWeight;
282 ptmA->tmOverhang = ptmW->tmOverhang;
283 ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX;
284 ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
285 ptmA->tmFirstChar = min(ptmW->tmFirstChar, 255);
286 if (ptmW->tmCharSet == SYMBOL_CHARSET)
288 UINT last_char = ptmW->tmLastChar;
289 if (last_char > 0xf000) last_char -= 0xf000;
290 ptmA->tmLastChar = min(last_char, 255);
292 else
293 ptmA->tmLastChar = min(ptmW->tmLastChar, 255);
294 ptmA->tmDefaultChar = min(ptmW->tmDefaultChar, 255);
295 ptmA->tmBreakChar = min(ptmW->tmBreakChar, 255);
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 /***********************************************************************
345 * GdiGetCodePage (GDI32.@)
347 DWORD WINAPI GdiGetCodePage( HDC hdc )
349 UINT cp = CP_ACP;
350 CHARSETINFO csi;
351 int charset = GetTextCharset(hdc);
353 /* Hmm, nicely designed api this one! */
354 if(TranslateCharsetInfo(ULongToPtr(charset), &csi, TCI_SRCCHARSET))
355 cp = csi.ciACP;
356 else {
357 switch(charset) {
358 case OEM_CHARSET:
359 cp = GetOEMCP();
360 break;
361 case DEFAULT_CHARSET:
362 cp = GetACP();
363 break;
365 case VISCII_CHARSET:
366 case TCVN_CHARSET:
367 case KOI8_CHARSET:
368 case ISO3_CHARSET:
369 case ISO4_CHARSET:
370 case ISO10_CHARSET:
371 case CELTIC_CHARSET:
372 /* FIXME: These have no place here, but because x11drv
373 enumerates fonts with these (made up) charsets some apps
374 might use them and then the FIXME below would become
375 annoying. Now we could pick the intended codepage for
376 each of these, but since it's broken anyway we'll just
377 use CP_ACP and hope it'll go away...
379 cp = CP_ACP;
380 break;
382 default:
383 FIXME("Can't find codepage for charset %d\n", charset);
384 break;
388 TRACE("charset %d => cp %d\n", charset, cp);
389 return cp;
392 /***********************************************************************
393 * FONT_mbtowc
395 * Returns a Unicode translation of str using the charset of the
396 * currently selected font in hdc. If count is -1 then str is assumed
397 * to be '\0' terminated, otherwise it contains the number of bytes to
398 * convert. If plenW is non-NULL, on return it will point to the
399 * number of WCHARs that have been written. If pCP is non-NULL, on
400 * return it will point to the codepage used in the conversion. The
401 * caller should free the returned LPWSTR from the process heap
402 * itself.
404 static LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
406 UINT cp;
407 INT lenW;
408 LPWSTR strW;
410 cp = GdiGetCodePage( hdc );
412 if(count == -1) count = strlen(str);
413 lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
414 strW = HeapAlloc(GetProcessHeap(), 0, lenW*sizeof(WCHAR));
415 MultiByteToWideChar(cp, 0, str, count, strW, lenW);
416 TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW));
417 if(plenW) *plenW = lenW;
418 if(pCP) *pCP = cp;
419 return strW;
423 /***********************************************************************
424 * CreateFontIndirectA (GDI32.@)
426 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *plfA )
428 LOGFONTW lfW;
430 if (!plfA) return 0;
432 FONT_LogFontAToW( plfA, &lfW );
433 return CreateFontIndirectW( &lfW );
436 /***********************************************************************
437 * CreateFontIndirectW (GDI32.@)
439 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
441 static const WCHAR ItalicW[] = {' ','I','t','a','l','i','c','\0'};
442 static const WCHAR BoldW[] = {' ','B','o','l','d','\0'};
443 WCHAR *pFaceNameItalicSuffix, *pFaceNameBoldSuffix;
444 WCHAR *pFaceNameSuffix = NULL;
445 HFONT hFont;
446 FONTOBJ *fontPtr;
448 if (!plf) return 0;
450 if (!(fontPtr = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC, (HGDIOBJ *)&hFont,
451 &font_funcs ))) return 0;
453 memcpy( &fontPtr->logfont, plf, sizeof(LOGFONTW) );
455 TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
456 plf->lfHeight, plf->lfWidth,
457 plf->lfEscapement, plf->lfOrientation,
458 plf->lfPitchAndFamily,
459 plf->lfOutPrecision, plf->lfClipPrecision,
460 plf->lfQuality, plf->lfCharSet,
461 debugstr_w(plf->lfFaceName),
462 plf->lfWeight > 400 ? "Bold" : "",
463 plf->lfItalic ? "Italic" : "",
464 plf->lfUnderline ? "Underline" : "", hFont);
466 if (plf->lfEscapement != plf->lfOrientation)
468 /* this should really depend on whether GM_ADVANCED is set */
469 fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
470 WARN("orientation angle %f set to "
471 "escapement angle %f for new font %p\n",
472 plf->lfOrientation/10., plf->lfEscapement/10., hFont);
475 pFaceNameItalicSuffix = strstrW(fontPtr->logfont.lfFaceName, ItalicW);
476 if (pFaceNameItalicSuffix)
478 fontPtr->logfont.lfItalic = TRUE;
479 pFaceNameSuffix = pFaceNameItalicSuffix;
482 pFaceNameBoldSuffix = strstrW(fontPtr->logfont.lfFaceName, BoldW);
483 if (pFaceNameBoldSuffix)
485 if (fontPtr->logfont.lfWeight < FW_BOLD)
486 fontPtr->logfont.lfWeight = FW_BOLD;
487 if (!pFaceNameSuffix || (pFaceNameBoldSuffix < pFaceNameSuffix))
488 pFaceNameSuffix = pFaceNameBoldSuffix;
491 if (pFaceNameSuffix) *pFaceNameSuffix = 0;
493 GDI_ReleaseObj( hFont );
494 return hFont;
497 /*************************************************************************
498 * CreateFontA (GDI32.@)
500 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
501 INT orient, INT weight, DWORD italic,
502 DWORD underline, DWORD strikeout, DWORD charset,
503 DWORD outpres, DWORD clippres, DWORD quality,
504 DWORD pitch, LPCSTR name )
506 LOGFONTA logfont;
508 logfont.lfHeight = height;
509 logfont.lfWidth = width;
510 logfont.lfEscapement = esc;
511 logfont.lfOrientation = orient;
512 logfont.lfWeight = weight;
513 logfont.lfItalic = italic;
514 logfont.lfUnderline = underline;
515 logfont.lfStrikeOut = strikeout;
516 logfont.lfCharSet = charset;
517 logfont.lfOutPrecision = outpres;
518 logfont.lfClipPrecision = clippres;
519 logfont.lfQuality = quality;
520 logfont.lfPitchAndFamily = pitch;
522 if (name)
523 lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
524 else
525 logfont.lfFaceName[0] = '\0';
527 return CreateFontIndirectA( &logfont );
530 /*************************************************************************
531 * CreateFontW (GDI32.@)
533 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
534 INT orient, INT weight, DWORD italic,
535 DWORD underline, DWORD strikeout, DWORD charset,
536 DWORD outpres, DWORD clippres, DWORD quality,
537 DWORD pitch, LPCWSTR name )
539 LOGFONTW logfont;
541 logfont.lfHeight = height;
542 logfont.lfWidth = width;
543 logfont.lfEscapement = esc;
544 logfont.lfOrientation = orient;
545 logfont.lfWeight = weight;
546 logfont.lfItalic = italic;
547 logfont.lfUnderline = underline;
548 logfont.lfStrikeOut = strikeout;
549 logfont.lfCharSet = charset;
550 logfont.lfOutPrecision = outpres;
551 logfont.lfClipPrecision = clippres;
552 logfont.lfQuality = quality;
553 logfont.lfPitchAndFamily = pitch;
555 if (name)
556 lstrcpynW(logfont.lfFaceName, name,
557 sizeof(logfont.lfFaceName) / sizeof(WCHAR));
558 else
559 logfont.lfFaceName[0] = '\0';
561 return CreateFontIndirectW( &logfont );
565 /***********************************************************************
566 * FONT_SelectObject
568 * If the driver supports vector fonts we create a gdi font first and
569 * then call the driver to give it a chance to supply its own device
570 * font. If the driver wants to do this it returns TRUE and we can
571 * delete the gdi font, if the driver wants to use the gdi font it
572 * should return FALSE, to signal an error return GDI_ERROR. For
573 * drivers that don't support vector fonts they must supply their own
574 * font.
576 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc )
578 HGDIOBJ ret = 0;
579 DC *dc = get_dc_ptr( hdc );
581 if (!dc) return 0;
583 if (!GDI_inc_ref_count( handle ))
585 release_dc_ptr( dc );
586 return 0;
589 if (dc->hFont != handle || dc->gdiFont == NULL)
591 if(GetDeviceCaps(dc->hSelf, TEXTCAPS) & TC_VA_ABLE)
593 FONTOBJ *font = GDI_GetObjPtr( handle, FONT_MAGIC ); /* to grab the GDI lock (FIXME) */
594 dc->gdiFont = WineEngCreateFontInstance(dc, handle);
595 if (font) GDI_ReleaseObj( handle );
599 if (dc->funcs->pSelectFont) ret = dc->funcs->pSelectFont( dc->physDev, handle, dc->gdiFont );
601 if (ret && dc->gdiFont) dc->gdiFont = 0;
603 if (ret == HGDI_ERROR)
605 GDI_dec_ref_count( handle );
606 ret = 0; /* SelectObject returns 0 on error */
608 else
610 ret = dc->hFont;
611 dc->hFont = handle;
612 GDI_dec_ref_count( ret );
614 release_dc_ptr( dc );
615 return ret;
619 /***********************************************************************
620 * FONT_GetObject16
622 static INT FONT_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
624 FONTOBJ *font = obj;
625 LOGFONT16 lf16;
627 FONT_LogFontWTo16( &font->logfont, &lf16 );
629 if (count > sizeof(LOGFONT16)) count = sizeof(LOGFONT16);
630 memcpy( buffer, &lf16, count );
631 return count;
634 /***********************************************************************
635 * FONT_GetObjectA
637 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
639 FONTOBJ *font = obj;
640 LOGFONTA lfA;
642 if(!buffer)
643 return sizeof(lfA);
644 FONT_LogFontWToA( &font->logfont, &lfA );
646 if (count > sizeof(lfA)) count = sizeof(lfA);
647 memcpy( buffer, &lfA, count );
648 return count;
651 /***********************************************************************
652 * FONT_GetObjectW
654 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
656 FONTOBJ *font = obj;
657 if(!buffer)
658 return sizeof(LOGFONTW);
659 if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
660 memcpy( buffer, &font->logfont, count );
661 return count;
665 /***********************************************************************
666 * FONT_DeleteObject
668 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj )
670 WineEngDestroyFontInstance( handle );
671 return GDI_FreeObject( handle, obj );
675 /***********************************************************************
676 * FONT_EnumInstance16
678 * Called by the device driver layer to pass font info
679 * down to the application.
681 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
682 * We have to use other types because of the FONTENUMPROCW definition.
684 static INT CALLBACK FONT_EnumInstance16( const LOGFONTW *plf, const TEXTMETRICW *ptm,
685 DWORD fType, LPARAM lp )
687 fontEnum16 *pfe = (fontEnum16*)lp;
688 INT ret = 1;
690 if (!pfe->lpLogFontParam ||
691 pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
692 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet )
694 WORD args[7];
695 DWORD result;
697 FONT_EnumLogFontExWTo16((const ENUMLOGFONTEXW *)plf, pfe->lpLogFont);
698 FONT_NewTextMetricExWTo16((const NEWTEXTMETRICEXW *)ptm, pfe->lpTextMetric);
699 pfe->dwFlags |= ENUM_CALLED;
701 args[6] = SELECTOROF(pfe->segLogFont);
702 args[5] = OFFSETOF(pfe->segLogFont);
703 args[4] = SELECTOROF(pfe->segTextMetric);
704 args[3] = OFFSETOF(pfe->segTextMetric);
705 args[2] = fType;
706 args[1] = HIWORD(pfe->lpData);
707 args[0] = LOWORD(pfe->lpData);
708 WOWCallback16Ex( (DWORD)pfe->lpEnumFunc, WCB16_PASCAL, sizeof(args), args, &result );
709 ret = LOWORD(result);
711 return ret;
714 /***********************************************************************
715 * FONT_EnumInstance
717 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
718 * We have to use other types because of the FONTENUMPROCW definition.
720 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
721 DWORD fType, LPARAM lp )
723 fontEnum32 *pfe = (fontEnum32*)lp;
724 INT ret = 1;
726 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
727 if ((!pfe->lpLogFontParam ||
728 pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
729 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
730 (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
732 /* convert font metrics */
733 ENUMLOGFONTEXA logfont;
734 NEWTEXTMETRICEXA tmA;
736 pfe->dwFlags |= ENUM_CALLED;
737 if (!(pfe->dwFlags & ENUM_UNICODE))
739 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
740 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
741 plf = (LOGFONTW *)&logfont.elfLogFont;
742 ptm = (TEXTMETRICW *)&tmA;
745 ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
747 return ret;
750 /***********************************************************************
751 * EnumFontFamiliesEx (GDI.613)
753 INT16 WINAPI EnumFontFamiliesEx16( HDC16 hDC, LPLOGFONT16 plf,
754 FONTENUMPROC16 efproc, LPARAM lParam,
755 DWORD dwFlags)
757 fontEnum16 fe16;
758 INT16 ret = 1, ret2;
759 DC* dc = get_dc_ptr( HDC_32(hDC) );
760 NEWTEXTMETRICEX16 tm16;
761 ENUMLOGFONTEX16 lf16;
762 LOGFONTW lfW, *plfW;
763 BOOL enum_gdi_fonts;
765 if (!dc) return 0;
767 if (plf)
769 FONT_LogFont16ToW(plf, &lfW);
770 plfW = &lfW;
772 else plfW = NULL;
774 fe16.hdc = HDC_32(hDC);
775 fe16.lpLogFontParam = plf;
776 fe16.lpEnumFunc = efproc;
777 fe16.lpData = lParam;
778 fe16.lpTextMetric = &tm16;
779 fe16.lpLogFont = &lf16;
780 fe16.segTextMetric = MapLS( &tm16 );
781 fe16.segLogFont = MapLS( &lf16 );
782 fe16.dwFlags = 0;
784 enum_gdi_fonts = GetDeviceCaps(fe16.hdc, TEXTCAPS) & TC_VA_ABLE;
786 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
788 ret = 0;
789 goto done;
792 if (enum_gdi_fonts)
793 ret = WineEngEnumFonts( plfW, FONT_EnumInstance16, (LPARAM)&fe16 );
794 fe16.dwFlags &= ~ENUM_CALLED;
795 if (ret && dc->funcs->pEnumDeviceFonts) {
796 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, plfW, FONT_EnumInstance16, (LPARAM)&fe16 );
797 if(fe16.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
798 ret = ret2;
800 done:
801 UnMapLS( fe16.segTextMetric );
802 UnMapLS( fe16.segLogFont );
803 release_dc_ptr( dc );
804 return ret;
807 /***********************************************************************
808 * FONT_EnumFontFamiliesEx
810 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf,
811 FONTENUMPROCW efproc,
812 LPARAM lParam, DWORD dwUnicode)
814 INT ret = 1, ret2;
815 DC *dc = get_dc_ptr( hDC );
816 fontEnum32 fe32;
817 BOOL enum_gdi_fonts;
819 if (!dc) return 0;
821 if (plf)
822 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName),
823 plf->lfCharSet);
824 fe32.lpLogFontParam = plf;
825 fe32.lpEnumFunc = efproc;
826 fe32.lpData = lParam;
827 fe32.dwFlags = dwUnicode;
828 fe32.hdc = hDC;
830 enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE;
832 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
834 ret = 0;
835 goto done;
838 if (enum_gdi_fonts)
839 ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
840 fe32.dwFlags &= ~ENUM_CALLED;
841 if (ret && dc->funcs->pEnumDeviceFonts) {
842 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, plf, FONT_EnumInstance, (LPARAM)&fe32 );
843 if(fe32.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
844 ret = ret2;
846 done:
847 release_dc_ptr( dc );
848 return ret;
851 /***********************************************************************
852 * EnumFontFamiliesExW (GDI32.@)
854 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
855 FONTENUMPROCW efproc,
856 LPARAM lParam, DWORD dwFlags )
858 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, ENUM_UNICODE );
861 /***********************************************************************
862 * EnumFontFamiliesExA (GDI32.@)
864 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
865 FONTENUMPROCA efproc,
866 LPARAM lParam, DWORD dwFlags)
868 LOGFONTW lfW, *plfW;
870 if (plf)
872 FONT_LogFontAToW( plf, &lfW );
873 plfW = &lfW;
875 else plfW = NULL;
877 return FONT_EnumFontFamiliesEx( hDC, plfW, (FONTENUMPROCW)efproc, lParam, 0);
880 /***********************************************************************
881 * EnumFontFamilies (GDI.330)
883 INT16 WINAPI EnumFontFamilies16( HDC16 hDC, LPCSTR lpFamily,
884 FONTENUMPROC16 efproc, LPARAM lpData )
886 LOGFONT16 lf, *plf;
888 if (lpFamily)
890 if (!*lpFamily) return 1;
891 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
892 lf.lfCharSet = DEFAULT_CHARSET;
893 lf.lfPitchAndFamily = 0;
894 plf = &lf;
896 else plf = NULL;
898 return EnumFontFamiliesEx16( hDC, plf, efproc, lpData, 0 );
901 /***********************************************************************
902 * EnumFontFamiliesA (GDI32.@)
904 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
905 FONTENUMPROCA efproc, LPARAM lpData )
907 LOGFONTA lf, *plf;
909 if (lpFamily)
911 if (!*lpFamily) return 1;
912 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
913 lf.lfCharSet = DEFAULT_CHARSET;
914 lf.lfPitchAndFamily = 0;
915 plf = &lf;
917 else plf = NULL;
919 return EnumFontFamiliesExA( hDC, plf, efproc, lpData, 0 );
922 /***********************************************************************
923 * EnumFontFamiliesW (GDI32.@)
925 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
926 FONTENUMPROCW efproc, LPARAM lpData )
928 LOGFONTW lf, *plf;
930 if (lpFamily)
932 if (!*lpFamily) return 1;
933 lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
934 lf.lfCharSet = DEFAULT_CHARSET;
935 lf.lfPitchAndFamily = 0;
936 plf = &lf;
938 else plf = NULL;
940 return EnumFontFamiliesExW( hDC, plf, efproc, lpData, 0 );
943 /***********************************************************************
944 * EnumFonts (GDI.70)
946 INT16 WINAPI EnumFonts16( HDC16 hDC, LPCSTR lpName, FONTENUMPROC16 efproc,
947 LPARAM lpData )
949 return EnumFontFamilies16( hDC, lpName, efproc, lpData );
952 /***********************************************************************
953 * EnumFontsA (GDI32.@)
955 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
956 LPARAM lpData )
958 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
961 /***********************************************************************
962 * EnumFontsW (GDI32.@)
964 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
965 LPARAM lpData )
967 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
971 /***********************************************************************
972 * GetTextCharacterExtra (GDI32.@)
974 INT WINAPI GetTextCharacterExtra( HDC hdc )
976 INT ret;
977 DC *dc = get_dc_ptr( hdc );
978 if (!dc) return 0x80000000;
979 ret = dc->charExtra;
980 release_dc_ptr( dc );
981 return ret;
985 /***********************************************************************
986 * SetTextCharacterExtra (GDI32.@)
988 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
990 INT prev;
991 DC * dc = get_dc_ptr( hdc );
992 if (!dc) return 0x80000000;
993 if (dc->funcs->pSetTextCharacterExtra)
994 prev = dc->funcs->pSetTextCharacterExtra( dc->physDev, extra );
995 else
997 prev = dc->charExtra;
998 dc->charExtra = extra;
1000 release_dc_ptr( dc );
1001 return prev;
1005 /***********************************************************************
1006 * SetTextJustification (GDI32.@)
1008 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
1010 BOOL ret = TRUE;
1011 DC * dc = get_dc_ptr( hdc );
1012 if (!dc) return FALSE;
1013 if (dc->funcs->pSetTextJustification)
1014 ret = dc->funcs->pSetTextJustification( dc->physDev, extra, breaks );
1015 else
1017 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
1018 if (!extra) breaks = 0;
1019 if (breaks)
1021 dc->breakExtra = extra / breaks;
1022 dc->breakRem = extra - (breaks * dc->breakExtra);
1024 else
1026 dc->breakExtra = 0;
1027 dc->breakRem = 0;
1030 release_dc_ptr( dc );
1031 return ret;
1035 /***********************************************************************
1036 * GetTextFaceA (GDI32.@)
1038 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
1040 INT res = GetTextFaceW(hdc, 0, NULL);
1041 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
1042 GetTextFaceW( hdc, res, nameW );
1044 if (name)
1046 if (count && !WideCharToMultiByte( CP_ACP, 0, nameW, -1, name, count, NULL, NULL))
1047 name[count-1] = 0;
1048 res = strlen(name);
1050 else
1051 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
1052 HeapFree( GetProcessHeap(), 0, nameW );
1053 return res;
1056 /***********************************************************************
1057 * GetTextFaceW (GDI32.@)
1059 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
1061 FONTOBJ *font;
1062 INT ret = 0;
1064 DC * dc = get_dc_ptr( hdc );
1065 if (!dc) return 0;
1067 if(dc->gdiFont)
1068 ret = WineEngGetTextFace(dc->gdiFont, count, name);
1069 else if ((font = (FONTOBJ *) GDI_GetObjPtr( dc->hFont, FONT_MAGIC )))
1071 if (name)
1073 lstrcpynW( name, font->logfont.lfFaceName, count );
1074 ret = strlenW(name);
1076 else ret = strlenW(font->logfont.lfFaceName) + 1;
1077 GDI_ReleaseObj( dc->hFont );
1079 release_dc_ptr( dc );
1080 return ret;
1084 /***********************************************************************
1085 * GetTextExtentPoint32A (GDI32.@)
1087 * See GetTextExtentPoint32W.
1089 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
1090 LPSIZE size )
1092 BOOL ret = FALSE;
1093 INT wlen;
1094 LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1096 if (p) {
1097 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
1098 HeapFree( GetProcessHeap(), 0, p );
1101 TRACE("(%p %s %d %p): returning %d x %d\n",
1102 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
1103 return ret;
1107 /***********************************************************************
1108 * GetTextExtentPoint32W [GDI32.@]
1110 * Computes width/height for a string.
1112 * Computes width and height of the specified string.
1114 * RETURNS
1115 * Success: TRUE
1116 * Failure: FALSE
1118 BOOL WINAPI GetTextExtentPoint32W(
1119 HDC hdc, /* [in] Handle of device context */
1120 LPCWSTR str, /* [in] Address of text string */
1121 INT count, /* [in] Number of characters in string */
1122 LPSIZE size) /* [out] Address of structure for string size */
1124 return GetTextExtentExPointW(hdc, str, count, 0, NULL, NULL, size);
1127 /***********************************************************************
1128 * GetTextExtentExPointI [GDI32.@]
1130 * Computes width and height of the array of glyph indices.
1132 * PARAMS
1133 * hdc [I] Handle of device context.
1134 * indices [I] Glyph index array.
1135 * count [I] Number of glyphs in array.
1136 * max_ext [I] Maximum width in glyphs.
1137 * nfit [O] Maximum number of characters.
1138 * dxs [O] Partial string widths.
1139 * size [O] Returned string size.
1141 * RETURNS
1142 * Success: TRUE
1143 * Failure: FALSE
1145 BOOL WINAPI GetTextExtentExPointI( HDC hdc, const WORD *indices, INT count, INT max_ext,
1146 LPINT nfit, LPINT dxs, LPSIZE size )
1148 BOOL ret = FALSE;
1149 DC * dc = get_dc_ptr( hdc );
1150 if (!dc) return FALSE;
1152 if(dc->gdiFont) {
1153 ret = WineEngGetTextExtentExPointI(dc->gdiFont, indices, count, max_ext, nfit, dxs, size);
1154 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1155 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1156 size->cx += count * dc->charExtra;
1158 else if(dc->funcs->pGetTextExtentExPoint) {
1159 FIXME("calling GetTextExtentExPoint\n");
1160 ret = dc->funcs->pGetTextExtentExPoint( dc->physDev, (LPCWSTR)indices,
1161 count, max_ext, nfit, dxs, size );
1164 release_dc_ptr( dc );
1166 TRACE("(%p %p %d %p): returning %d x %d\n",
1167 hdc, indices, count, size, size->cx, size->cy );
1168 return ret;
1171 /***********************************************************************
1172 * GetTextExtentPointI [GDI32.@]
1174 * Computes width and height of the array of glyph indices.
1176 * PARAMS
1177 * hdc [I] Handle of device context.
1178 * indices [I] Glyph index array.
1179 * count [I] Number of glyphs in array.
1180 * size [O] Returned string size.
1182 * RETURNS
1183 * Success: TRUE
1184 * Failure: FALSE
1186 BOOL WINAPI GetTextExtentPointI( HDC hdc, const WORD *indices, INT count, LPSIZE size )
1188 return GetTextExtentExPointI( hdc, indices, count, 0, NULL, NULL, size );
1192 /***********************************************************************
1193 * GetTextExtentPointA (GDI32.@)
1195 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
1196 LPSIZE size )
1198 TRACE("not bug compatible.\n");
1199 return GetTextExtentPoint32A( hdc, str, count, size );
1202 /***********************************************************************
1203 * GetTextExtentPointW (GDI32.@)
1205 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1206 LPSIZE size )
1208 TRACE("not bug compatible.\n");
1209 return GetTextExtentPoint32W( hdc, str, count, size );
1213 /***********************************************************************
1214 * GetTextExtentExPointA (GDI32.@)
1216 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1217 INT maxExt, LPINT lpnFit,
1218 LPINT alpDx, LPSIZE size )
1220 BOOL ret;
1221 INT wlen;
1222 INT *walpDx = NULL;
1223 LPWSTR p = NULL;
1225 if (alpDx &&
1226 NULL == (walpDx = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT))))
1227 return FALSE;
1229 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1230 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
1231 if (walpDx)
1233 INT n = lpnFit ? *lpnFit : wlen;
1234 INT i, j;
1235 for(i = 0, j = 0; i < n; i++, j++)
1237 alpDx[j] = walpDx[i];
1238 if (IsDBCSLeadByte(str[j])) alpDx[++j] = walpDx[i];
1241 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1242 HeapFree( GetProcessHeap(), 0, p );
1243 HeapFree( GetProcessHeap(), 0, walpDx );
1244 return ret;
1248 /***********************************************************************
1249 * GetTextExtentExPointW (GDI32.@)
1251 * Return the size of the string as it would be if it was output properly by
1252 * e.g. TextOut.
1254 * This should include
1255 * - Intercharacter spacing
1256 * - justification spacing (not yet done)
1257 * - kerning? see below
1259 * Kerning. Since kerning would be carried out by the rendering code it should
1260 * be done by the driver. However they don't support it yet. Also I am not
1261 * yet persuaded that (certainly under Win95) any kerning is actually done.
1263 * str: According to MSDN this should be null-terminated. That is not true; a
1264 * null will not terminate it early.
1265 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1266 * than count. I have seen it be either the size of the full string or
1267 * 1 less than the size of the full string. I have not seen it bear any
1268 * resemblance to the portion that would fit.
1269 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1270 * trailing intercharacter spacing and any trailing justification.
1272 * FIXME
1273 * Currently we do this by measuring each character etc. We should do it by
1274 * passing the request to the driver, perhaps by extending the
1275 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1276 * thinking about kerning issues and rounding issues in the justification.
1279 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1280 INT maxExt, LPINT lpnFit,
1281 LPINT alpDx, LPSIZE size )
1283 INT nFit = 0;
1284 LPINT dxs = NULL;
1285 DC *dc;
1286 BOOL ret = FALSE;
1287 TEXTMETRICW tm;
1289 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1291 dc = get_dc_ptr(hdc);
1292 if (! dc)
1293 return FALSE;
1295 GetTextMetricsW(hdc, &tm);
1297 /* If we need to calculate nFit, then we need the partial extents even if
1298 the user hasn't provided us with an array. */
1299 if (lpnFit)
1301 dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]);
1302 if (! dxs)
1304 release_dc_ptr(dc);
1305 SetLastError(ERROR_OUTOFMEMORY);
1306 return FALSE;
1309 else
1310 dxs = alpDx;
1312 if (dc->gdiFont)
1313 ret = WineEngGetTextExtentExPoint(dc->gdiFont, str, count,
1314 0, NULL, dxs, size);
1315 else if (dc->funcs->pGetTextExtentExPoint)
1316 ret = dc->funcs->pGetTextExtentExPoint(dc->physDev, str, count,
1317 0, NULL, dxs, size);
1319 /* Perform device size to world size transformations. */
1320 if (ret)
1322 INT extra = dc->charExtra,
1323 breakExtra = dc->breakExtra,
1324 breakRem = dc->breakRem,
1327 if (dxs)
1329 for (i = 0; i < count; ++i)
1331 dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
1332 dxs[i] += (i+1) * extra;
1333 if (count > 1 && (breakExtra || breakRem) && str[i] == tm.tmBreakChar)
1335 dxs[i] += breakExtra;
1336 if (breakRem > 0)
1338 breakRem--;
1339 dxs[i]++;
1342 if (dxs[i] <= maxExt)
1343 ++nFit;
1345 breakRem = dc->breakRem;
1347 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1348 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1350 if (!dxs && count > 1 && (breakExtra || breakRem))
1352 for (i = 0; i < count; i++)
1354 if (str[i] == tm.tmBreakChar)
1356 size->cx += breakExtra;
1357 if (breakRem > 0)
1359 breakRem--;
1360 (size->cx)++;
1367 if (lpnFit)
1368 *lpnFit = nFit;
1370 if (! alpDx)
1371 HeapFree(GetProcessHeap(), 0, dxs);
1373 release_dc_ptr( dc );
1375 TRACE("returning %d %d x %d\n",nFit,size->cx,size->cy);
1376 return ret;
1379 /***********************************************************************
1380 * GetTextMetricsA (GDI32.@)
1382 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1384 TEXTMETRICW tm32;
1386 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1387 FONT_TextMetricWToA( &tm32, metrics );
1388 return TRUE;
1391 /***********************************************************************
1392 * GetTextMetricsW (GDI32.@)
1394 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1396 BOOL ret = FALSE;
1397 DC * dc = get_dc_ptr( hdc );
1398 if (!dc) return FALSE;
1400 if (dc->gdiFont)
1401 ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1402 else if (dc->funcs->pGetTextMetrics)
1403 ret = dc->funcs->pGetTextMetrics( dc->physDev, metrics );
1405 if (ret)
1407 /* device layer returns values in device units
1408 * therefore we have to convert them to logical */
1410 metrics->tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1411 metrics->tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1413 #define WDPTOLP(x) ((x<0)? \
1414 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1415 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1416 #define HDPTOLP(y) ((y<0)? \
1417 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1418 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1420 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1421 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1422 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1423 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1424 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1425 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1426 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1427 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1428 ret = TRUE;
1429 #undef WDPTOLP
1430 #undef HDPTOLP
1431 TRACE("text metrics:\n"
1432 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1433 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1434 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1435 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1436 " PitchAndFamily = %02x\n"
1437 " --------------------\n"
1438 " InternalLeading = %i\n"
1439 " Ascent = %i\n"
1440 " Descent = %i\n"
1441 " Height = %i\n",
1442 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1443 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1444 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1445 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1446 metrics->tmPitchAndFamily,
1447 metrics->tmInternalLeading,
1448 metrics->tmAscent,
1449 metrics->tmDescent,
1450 metrics->tmHeight );
1452 release_dc_ptr( dc );
1453 return ret;
1457 /***********************************************************************
1458 * GetOutlineTextMetrics [GDI.308] Gets metrics for TrueType fonts.
1460 * NOTES
1461 * lpOTM should be LPOUTLINETEXTMETRIC
1463 * RETURNS
1464 * Success: Non-zero or size of required buffer
1465 * Failure: 0
1467 UINT16 WINAPI GetOutlineTextMetrics16(
1468 HDC16 hdc, /* [in] Handle of device context */
1469 UINT16 cbData, /* [in] Size of metric data array */
1470 LPOUTLINETEXTMETRIC16 lpOTM) /* [out] Address of metric data array */
1472 FIXME("(%04x,%04x,%p): stub\n", hdc,cbData,lpOTM);
1473 return 0;
1477 /***********************************************************************
1478 * GetOutlineTextMetricsA (GDI32.@)
1479 * Gets metrics for TrueType fonts.
1481 * NOTES
1482 * If the supplied buffer isn't big enough Windows partially fills it up to
1483 * its given length and returns that length.
1485 * RETURNS
1486 * Success: Non-zero or size of required buffer
1487 * Failure: 0
1489 UINT WINAPI GetOutlineTextMetricsA(
1490 HDC hdc, /* [in] Handle of device context */
1491 UINT cbData, /* [in] Size of metric data array */
1492 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1494 char buf[512], *ptr;
1495 UINT ret, needed;
1496 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1497 OUTLINETEXTMETRICA *output = lpOTM;
1498 INT left, len;
1500 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1501 return 0;
1502 if(ret > sizeof(buf))
1503 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1504 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1506 needed = sizeof(OUTLINETEXTMETRICA);
1507 if(lpOTMW->otmpFamilyName)
1508 needed += WideCharToMultiByte(CP_ACP, 0,
1509 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1510 NULL, 0, NULL, NULL);
1511 if(lpOTMW->otmpFaceName)
1512 needed += WideCharToMultiByte(CP_ACP, 0,
1513 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1514 NULL, 0, NULL, NULL);
1515 if(lpOTMW->otmpStyleName)
1516 needed += WideCharToMultiByte(CP_ACP, 0,
1517 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1518 NULL, 0, NULL, NULL);
1519 if(lpOTMW->otmpFullName)
1520 needed += WideCharToMultiByte(CP_ACP, 0,
1521 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1522 NULL, 0, NULL, NULL);
1524 if(!lpOTM) {
1525 ret = needed;
1526 goto end;
1529 TRACE("needed = %d\n", needed);
1530 if(needed > cbData)
1531 /* Since the supplied buffer isn't big enough, we'll alloc one
1532 that is and memcpy the first cbData bytes into the lpOTM at
1533 the end. */
1534 output = HeapAlloc(GetProcessHeap(), 0, needed);
1536 ret = output->otmSize = min(needed, cbData);
1537 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1538 output->otmFiller = 0;
1539 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1540 output->otmfsSelection = lpOTMW->otmfsSelection;
1541 output->otmfsType = lpOTMW->otmfsType;
1542 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1543 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1544 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1545 output->otmEMSquare = lpOTMW->otmEMSquare;
1546 output->otmAscent = lpOTMW->otmAscent;
1547 output->otmDescent = lpOTMW->otmDescent;
1548 output->otmLineGap = lpOTMW->otmLineGap;
1549 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1550 output->otmsXHeight = lpOTMW->otmsXHeight;
1551 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1552 output->otmMacAscent = lpOTMW->otmMacAscent;
1553 output->otmMacDescent = lpOTMW->otmMacDescent;
1554 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1555 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1556 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1557 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1558 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1559 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1560 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1561 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1562 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1563 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1566 ptr = (char*)(output + 1);
1567 left = needed - sizeof(*output);
1569 if(lpOTMW->otmpFamilyName) {
1570 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1571 len = WideCharToMultiByte(CP_ACP, 0,
1572 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1573 ptr, left, NULL, NULL);
1574 left -= len;
1575 ptr += len;
1576 } else
1577 output->otmpFamilyName = 0;
1579 if(lpOTMW->otmpFaceName) {
1580 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1581 len = WideCharToMultiByte(CP_ACP, 0,
1582 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1583 ptr, left, NULL, NULL);
1584 left -= len;
1585 ptr += len;
1586 } else
1587 output->otmpFaceName = 0;
1589 if(lpOTMW->otmpStyleName) {
1590 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1591 len = WideCharToMultiByte(CP_ACP, 0,
1592 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1593 ptr, left, NULL, NULL);
1594 left -= len;
1595 ptr += len;
1596 } else
1597 output->otmpStyleName = 0;
1599 if(lpOTMW->otmpFullName) {
1600 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1601 len = WideCharToMultiByte(CP_ACP, 0,
1602 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1603 ptr, left, NULL, NULL);
1604 left -= len;
1605 } else
1606 output->otmpFullName = 0;
1608 assert(left == 0);
1610 if(output != lpOTM) {
1611 memcpy(lpOTM, output, cbData);
1612 HeapFree(GetProcessHeap(), 0, output);
1614 /* check if the string offsets really fit into the provided size */
1615 /* FIXME: should we check string length as well? */
1616 /* make sure that we don't read/write beyond the provided buffer */
1617 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(LPSTR))
1619 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1620 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1623 /* make sure that we don't read/write beyond the provided buffer */
1624 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(LPSTR))
1626 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1627 lpOTM->otmpFaceName = 0; /* doesn't fit */
1630 /* make sure that we don't read/write beyond the provided buffer */
1631 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(LPSTR))
1633 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1634 lpOTM->otmpStyleName = 0; /* doesn't fit */
1637 /* make sure that we don't read/write beyond the provided buffer */
1638 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(LPSTR))
1640 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1641 lpOTM->otmpFullName = 0; /* doesn't fit */
1645 end:
1646 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1647 HeapFree(GetProcessHeap(), 0, lpOTMW);
1649 return ret;
1653 /***********************************************************************
1654 * GetOutlineTextMetricsW [GDI32.@]
1656 UINT WINAPI GetOutlineTextMetricsW(
1657 HDC hdc, /* [in] Handle of device context */
1658 UINT cbData, /* [in] Size of metric data array */
1659 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1661 DC *dc = get_dc_ptr( hdc );
1662 OUTLINETEXTMETRICW *output = lpOTM;
1663 UINT ret;
1665 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1666 if(!dc) return 0;
1668 if(dc->gdiFont) {
1669 ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, output);
1670 if(lpOTM && ret) {
1671 if(ret > cbData) {
1672 output = HeapAlloc(GetProcessHeap(), 0, ret);
1673 WineEngGetOutlineTextMetrics(dc->gdiFont, ret, output);
1676 #define WDPTOLP(x) ((x<0)? \
1677 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1678 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1679 #define HDPTOLP(y) ((y<0)? \
1680 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1681 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1683 output->otmTextMetrics.tmHeight = HDPTOLP(output->otmTextMetrics.tmHeight);
1684 output->otmTextMetrics.tmAscent = HDPTOLP(output->otmTextMetrics.tmAscent);
1685 output->otmTextMetrics.tmDescent = HDPTOLP(output->otmTextMetrics.tmDescent);
1686 output->otmTextMetrics.tmInternalLeading = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1687 output->otmTextMetrics.tmExternalLeading = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1688 output->otmTextMetrics.tmAveCharWidth = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1689 output->otmTextMetrics.tmMaxCharWidth = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1690 output->otmTextMetrics.tmOverhang = WDPTOLP(output->otmTextMetrics.tmOverhang);
1691 output->otmAscent = HDPTOLP(output->otmAscent);
1692 output->otmDescent = HDPTOLP(output->otmDescent);
1693 output->otmLineGap = HDPTOLP(output->otmLineGap);
1694 output->otmsCapEmHeight = HDPTOLP(output->otmsCapEmHeight);
1695 output->otmsXHeight = HDPTOLP(output->otmsXHeight);
1696 output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1697 output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1698 output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1699 output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1700 output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1701 output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1702 output->otmMacLineGap = HDPTOLP(output->otmMacLineGap);
1703 output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1704 output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1705 output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1706 output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1707 output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1708 output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1709 output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1710 output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1711 output->otmsStrikeoutSize = HDPTOLP(output->otmsStrikeoutSize);
1712 output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1713 output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1714 output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1715 #undef WDPTOLP
1716 #undef HDPTOLP
1717 if(output != lpOTM) {
1718 memcpy(lpOTM, output, cbData);
1719 HeapFree(GetProcessHeap(), 0, output);
1720 ret = cbData;
1725 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1726 but really this should just be a return 0. */
1728 ret = sizeof(*lpOTM);
1729 if (lpOTM) {
1730 if(cbData < ret)
1731 ret = 0;
1732 else {
1733 memset(lpOTM, 0, ret);
1734 lpOTM->otmSize = sizeof(*lpOTM);
1735 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1737 Further fill of the structure not implemented,
1738 Needs real values for the structure members
1743 release_dc_ptr(dc);
1744 return ret;
1748 /***********************************************************************
1749 * GetCharWidthW (GDI32.@)
1750 * GetCharWidth32W (GDI32.@)
1752 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1753 LPINT buffer )
1755 UINT i;
1756 BOOL ret = FALSE;
1757 DC * dc = get_dc_ptr( hdc );
1758 if (!dc) return FALSE;
1760 if (dc->gdiFont)
1761 ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1762 else if (dc->funcs->pGetCharWidth)
1763 ret = dc->funcs->pGetCharWidth( dc->physDev, firstChar, lastChar, buffer);
1765 if (ret)
1767 /* convert device units to logical */
1768 for( i = firstChar; i <= lastChar; i++, buffer++ )
1769 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1770 ret = TRUE;
1772 release_dc_ptr( dc );
1773 return ret;
1777 /***********************************************************************
1778 * GetCharWidthA (GDI32.@)
1779 * GetCharWidth32A (GDI32.@)
1781 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1782 LPINT buffer )
1784 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1785 LPSTR str;
1786 LPWSTR wstr;
1787 BOOL ret = TRUE;
1789 if(count <= 0) return FALSE;
1791 str = HeapAlloc(GetProcessHeap(), 0, count);
1792 for(i = 0; i < count; i++)
1793 str[i] = (BYTE)(firstChar + i);
1795 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1797 for(i = 0; i < wlen; i++)
1799 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1801 ret = FALSE;
1802 break;
1804 buffer++;
1807 HeapFree(GetProcessHeap(), 0, str);
1808 HeapFree(GetProcessHeap(), 0, wstr);
1810 return ret;
1814 /***********************************************************************
1815 * ExtTextOutA (GDI32.@)
1817 * See ExtTextOutW.
1819 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1820 const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1822 INT wlen;
1823 UINT codepage;
1824 LPWSTR p;
1825 BOOL ret;
1826 LPINT lpDxW = NULL;
1828 if (flags & ETO_GLYPH_INDEX)
1829 return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
1831 p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
1833 if (lpDx) {
1834 unsigned int i = 0, j = 0;
1836 lpDxW = HeapAlloc( GetProcessHeap(), 0, wlen*sizeof(INT));
1837 while(i < count) {
1838 if(IsDBCSLeadByteEx(codepage, str[i])) {
1839 lpDxW[j++] = lpDx[i] + lpDx[i+1];
1840 i = i + 2;
1841 } else {
1842 lpDxW[j++] = lpDx[i];
1843 i = i + 1;
1848 ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1850 HeapFree( GetProcessHeap(), 0, p );
1851 HeapFree( GetProcessHeap(), 0, lpDxW );
1852 return ret;
1856 /***********************************************************************
1857 * ExtTextOutW (GDI32.@)
1859 * Draws text using the currently selected font, background color, and text color.
1862 * PARAMS
1863 * x,y [I] coordinates of string
1864 * flags [I]
1865 * ETO_GRAYED - undocumented on MSDN
1866 * ETO_OPAQUE - use background color for fill the rectangle
1867 * ETO_CLIPPED - clipping text to the rectangle
1868 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1869 * than encoded characters. Implies ETO_IGNORELANGUAGE
1870 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1871 * Affects BiDi ordering
1872 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1873 * ETO_PDY - unimplemented
1874 * ETO_NUMERICSLATIN - unimplemented always assumed -
1875 * do not translate numbers into locale representations
1876 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1877 * lprect [I] dimensions for clipping or/and opaquing
1878 * str [I] text string
1879 * count [I] number of symbols in string
1880 * lpDx [I] optional parameter with distance between drawing characters
1882 * RETURNS
1883 * Success: TRUE
1884 * Failure: FALSE
1886 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1887 const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1889 BOOL ret = FALSE;
1890 LPWSTR reordered_str = (LPWSTR)str;
1891 WORD *glyphs = NULL;
1892 UINT align = GetTextAlign( hdc );
1893 POINT pt;
1894 TEXTMETRICW tm;
1895 LOGFONTW lf;
1896 double cosEsc, sinEsc;
1897 INT *deltas = NULL, char_extra;
1898 SIZE sz;
1899 RECT rc;
1900 BOOL done_extents = FALSE;
1901 INT width = 0, xwidth = 0, ywidth = 0;
1902 DWORD type;
1903 DC * dc = get_dc_ptr( hdc );
1904 INT breakRem;
1906 if (!dc) return FALSE;
1908 breakRem = dc->breakRem;
1910 if (flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY))
1911 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY unimplemented\n");
1913 if (!dc->funcs->pExtTextOut && !PATH_IsPathOpen(dc->path))
1915 release_dc_ptr( dc );
1916 return ret;
1919 update_dc( dc );
1920 type = GetObjectType(hdc);
1921 if(type == OBJ_METADC || type == OBJ_ENHMETADC)
1923 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, flags, lprect, str, count, lpDx);
1924 release_dc_ptr( dc );
1925 return ret;
1928 if (!lprect)
1929 flags &= ~ETO_CLIPPED;
1931 if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && count > 0 )
1933 reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1935 BIDI_Reorder( str, count, GCP_REORDER,
1936 ((flags&ETO_RTLREADING)!=0 || (GetTextAlign(hdc)&TA_RTLREADING)!=0)?
1937 WINE_GCPW_FORCE_RTL:WINE_GCPW_FORCE_LTR,
1938 reordered_str, count, NULL );
1940 flags |= ETO_IGNORELANGUAGE;
1943 TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc, x, y, flags,
1944 lprect, debugstr_wn(str, count), count, lpDx);
1946 if(flags & ETO_GLYPH_INDEX)
1947 glyphs = reordered_str;
1949 if(lprect)
1950 TRACE("rect: %d,%d - %d,%d\n", lprect->left, lprect->top, lprect->right,
1951 lprect->bottom);
1952 TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
1954 if(align & TA_UPDATECP)
1956 GetCurrentPositionEx( hdc, &pt );
1957 x = pt.x;
1958 y = pt.y;
1961 GetTextMetricsW(hdc, &tm);
1962 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1964 if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
1965 lf.lfEscapement = 0;
1967 if(lf.lfEscapement != 0)
1969 cosEsc = cos(lf.lfEscapement * M_PI / 1800);
1970 sinEsc = sin(lf.lfEscapement * M_PI / 1800);
1972 else
1974 cosEsc = 1;
1975 sinEsc = 0;
1978 if(flags & (ETO_CLIPPED | ETO_OPAQUE))
1980 if(!lprect)
1982 if(flags & ETO_GLYPH_INDEX)
1983 GetTextExtentPointI(hdc, glyphs, count, &sz);
1984 else
1985 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1987 done_extents = TRUE;
1988 rc.left = x;
1989 rc.top = y;
1990 rc.right = x + sz.cx;
1991 rc.bottom = y + sz.cy;
1993 else
1995 rc = *lprect;
1998 LPtoDP(hdc, (POINT*)&rc, 2);
2000 if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
2001 if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
2004 if ((flags & ETO_OPAQUE) && !PATH_IsPathOpen(dc->path))
2005 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
2007 if(count == 0)
2009 ret = TRUE;
2010 goto done;
2013 pt.x = x;
2014 pt.y = y;
2015 LPtoDP(hdc, &pt, 1);
2016 x = pt.x;
2017 y = pt.y;
2019 char_extra = GetTextCharacterExtra(hdc);
2020 if(char_extra || dc->breakExtra || breakRem || lpDx || lf.lfEscapement != 0)
2022 UINT i;
2023 SIZE tmpsz;
2024 deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT));
2025 for(i = 0; i < count; i++)
2027 if(lpDx && (flags & ETO_PDY))
2028 deltas[i] = lpDx[i*2] + char_extra;
2029 else if(lpDx)
2030 deltas[i] = lpDx[i] + char_extra;
2031 else
2033 if(flags & ETO_GLYPH_INDEX)
2034 GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
2035 else
2036 GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
2038 deltas[i] = tmpsz.cx;
2041 if (!(flags & ETO_GLYPH_INDEX) && (dc->breakExtra || breakRem) && reordered_str[i] == tm.tmBreakChar)
2043 deltas[i] = deltas[i] + dc->breakExtra;
2044 if (breakRem > 0)
2046 breakRem--;
2047 deltas[i]++;
2050 deltas[i] = INTERNAL_XWSTODS(dc, deltas[i]);
2051 width += deltas[i];
2054 else
2056 if(!done_extents)
2058 if(flags & ETO_GLYPH_INDEX)
2059 GetTextExtentPointI(hdc, glyphs, count, &sz);
2060 else
2061 GetTextExtentPointW(hdc, reordered_str, count, &sz);
2062 done_extents = TRUE;
2064 width = INTERNAL_XWSTODS(dc, sz.cx);
2066 xwidth = width * cosEsc;
2067 ywidth = width * sinEsc;
2069 tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
2070 tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
2071 switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
2073 case TA_LEFT:
2074 if (align & TA_UPDATECP)
2076 pt.x = x + xwidth;
2077 pt.y = y - ywidth;
2078 DPtoLP(hdc, &pt, 1);
2079 MoveToEx(hdc, pt.x, pt.y, NULL);
2081 break;
2083 case TA_CENTER:
2084 x -= xwidth / 2;
2085 y += ywidth / 2;
2086 break;
2088 case TA_RIGHT:
2089 x -= xwidth;
2090 y += ywidth;
2091 if (align & TA_UPDATECP)
2093 pt.x = x;
2094 pt.y = y;
2095 DPtoLP(hdc, &pt, 1);
2096 MoveToEx(hdc, pt.x, pt.y, NULL);
2098 break;
2101 switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
2103 case TA_TOP:
2104 y += tm.tmAscent * cosEsc;
2105 x += tm.tmAscent * sinEsc;
2106 break;
2108 case TA_BOTTOM:
2109 y -= tm.tmDescent * cosEsc;
2110 x -= tm.tmDescent * sinEsc;
2111 break;
2113 case TA_BASELINE:
2114 break;
2117 if (GetBkMode(hdc) != TRANSPARENT && !PATH_IsPathOpen(dc->path))
2119 if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
2121 if(!(flags & ETO_OPAQUE) || x < rc.left || x + width >= rc.right ||
2122 y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
2124 RECT rc;
2125 rc.left = x;
2126 rc.right = x + width;
2127 rc.top = y - tm.tmAscent;
2128 rc.bottom = y + tm.tmDescent;
2129 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
2134 if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
2136 HFONT orig_font = dc->hFont, cur_font;
2137 UINT glyph;
2138 INT span = 0, *offsets = NULL;
2139 unsigned int i;
2141 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2142 for(i = 0; i < count; i++)
2144 WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
2145 if(cur_font != dc->hFont)
2147 if(!offsets)
2149 unsigned int j;
2150 offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
2151 offsets[0] = 0;
2152 if(!deltas)
2154 SIZE tmpsz;
2155 for(j = 1; j < count; j++)
2157 GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
2158 offsets[j] = offsets[j-1] + INTERNAL_XWSTODS(dc, tmpsz.cx);
2161 else
2163 for(j = 1; j < count; j++)
2164 offsets[j] = offsets[j-1] + deltas[j];
2167 if(span)
2169 if (PATH_IsPathOpen(dc->path))
2170 ret = PATH_ExtTextOut(dc, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
2171 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2172 glyphs, span, deltas ? deltas + i - span : NULL);
2173 else
2174 dc->funcs->pExtTextOut(dc->physDev, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
2175 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2176 glyphs, span, deltas ? deltas + i - span : NULL);
2177 span = 0;
2179 SelectObject(hdc, cur_font);
2181 glyphs[span++] = glyph;
2183 if(i == count - 1)
2185 if (PATH_IsPathOpen(dc->path))
2186 ret = PATH_ExtTextOut(dc, x + (offsets ? offsets[count - span] * cosEsc : 0),
2187 y - (offsets ? offsets[count - span] * sinEsc : 0),
2188 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2189 glyphs, span, deltas ? deltas + count - span : NULL);
2190 else
2191 ret = dc->funcs->pExtTextOut(dc->physDev, x + (offsets ? offsets[count - span] * cosEsc : 0),
2192 y - (offsets ? offsets[count - span] * sinEsc : 0),
2193 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2194 glyphs, span, deltas ? deltas + count - span : NULL);
2195 SelectObject(hdc, orig_font);
2196 HeapFree(GetProcessHeap(), 0, offsets);
2200 else
2202 if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
2204 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2205 GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
2206 flags |= ETO_GLYPH_INDEX;
2209 if (PATH_IsPathOpen(dc->path))
2210 ret = PATH_ExtTextOut(dc, x, y, (flags & ~ETO_OPAQUE), &rc,
2211 glyphs ? glyphs : reordered_str, count, deltas);
2212 else
2213 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, (flags & ~ETO_OPAQUE), &rc,
2214 glyphs ? glyphs : reordered_str, count, deltas);
2217 done:
2218 HeapFree(GetProcessHeap(), 0, deltas);
2219 if(glyphs != reordered_str)
2220 HeapFree(GetProcessHeap(), 0, glyphs);
2221 if(reordered_str != str)
2222 HeapFree(GetProcessHeap(), 0, reordered_str);
2224 release_dc_ptr( dc );
2226 if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2228 int underlinePos, strikeoutPos;
2229 int underlineWidth, strikeoutWidth;
2230 UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2231 OUTLINETEXTMETRICW* otm = NULL;
2233 if(!size)
2235 underlinePos = 0;
2236 underlineWidth = tm.tmAscent / 20 + 1;
2237 strikeoutPos = tm.tmAscent / 2;
2238 strikeoutWidth = underlineWidth;
2240 else
2242 otm = HeapAlloc(GetProcessHeap(), 0, size);
2243 GetOutlineTextMetricsW(hdc, size, otm);
2244 underlinePos = otm->otmsUnderscorePosition;
2245 underlineWidth = otm->otmsUnderscoreSize;
2246 strikeoutPos = otm->otmsStrikeoutPosition;
2247 strikeoutWidth = otm->otmsStrikeoutSize;
2248 HeapFree(GetProcessHeap(), 0, otm);
2251 if (PATH_IsPathOpen(dc->path))
2253 POINT pts[5];
2254 HPEN hpen;
2255 HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2257 hbrush = SelectObject(hdc, hbrush);
2258 hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2260 if (lf.lfUnderline)
2262 pts[0].x = x - underlinePos * sinEsc;
2263 pts[0].y = y - underlinePos * cosEsc;
2264 pts[1].x = x + xwidth - underlinePos * sinEsc;
2265 pts[1].y = y - ywidth - underlinePos * cosEsc;
2266 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2267 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2268 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2269 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2270 pts[4].x = pts[0].x;
2271 pts[4].y = pts[0].y;
2272 DPtoLP(hdc, pts, 5);
2273 Polygon(hdc, pts, 5);
2276 if (lf.lfStrikeOut)
2278 pts[0].x = x - strikeoutPos * sinEsc;
2279 pts[0].y = y - strikeoutPos * cosEsc;
2280 pts[1].x = x + xwidth - strikeoutPos * sinEsc;
2281 pts[1].y = y - ywidth - strikeoutPos * cosEsc;
2282 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2283 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2284 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2285 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2286 pts[4].x = pts[0].x;
2287 pts[4].y = pts[0].y;
2288 DPtoLP(hdc, pts, 5);
2289 Polygon(hdc, pts, 5);
2292 SelectObject(hdc, hpen);
2293 hbrush = SelectObject(hdc, hbrush);
2294 DeleteObject(hbrush);
2296 else
2298 POINT pts[2], oldpt;
2299 HPEN hpen;
2301 if (lf.lfUnderline)
2303 hpen = CreatePen(PS_SOLID, underlineWidth, GetTextColor(hdc));
2304 hpen = SelectObject(hdc, hpen);
2305 pts[0].x = x;
2306 pts[0].y = y;
2307 pts[1].x = x + xwidth;
2308 pts[1].y = y - ywidth;
2309 DPtoLP(hdc, pts, 2);
2310 MoveToEx(hdc, pts[0].x - underlinePos * sinEsc, pts[0].y - underlinePos * cosEsc, &oldpt);
2311 LineTo(hdc, pts[1].x - underlinePos * sinEsc, pts[1].y - underlinePos * cosEsc);
2312 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2313 DeleteObject(SelectObject(hdc, hpen));
2316 if (lf.lfStrikeOut)
2318 hpen = CreatePen(PS_SOLID, strikeoutWidth, GetTextColor(hdc));
2319 hpen = SelectObject(hdc, hpen);
2320 pts[0].x = x;
2321 pts[0].y = y;
2322 pts[1].x = x + xwidth;
2323 pts[1].y = y - ywidth;
2324 DPtoLP(hdc, pts, 2);
2325 MoveToEx(hdc, pts[0].x - strikeoutPos * sinEsc, pts[0].y - strikeoutPos * cosEsc, &oldpt);
2326 LineTo(hdc, pts[1].x - strikeoutPos * sinEsc, pts[1].y - strikeoutPos * cosEsc);
2327 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2328 DeleteObject(SelectObject(hdc, hpen));
2333 return ret;
2337 /***********************************************************************
2338 * TextOutA (GDI32.@)
2340 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2342 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2346 /***********************************************************************
2347 * TextOutW (GDI32.@)
2349 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2351 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2355 /***********************************************************************
2356 * PolyTextOutA (GDI32.@)
2358 * See PolyTextOutW.
2360 BOOL WINAPI PolyTextOutA( HDC hdc, const POLYTEXTA *pptxt, INT cStrings )
2362 for (; cStrings>0; cStrings--, pptxt++)
2363 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2364 return FALSE;
2365 return TRUE;
2370 /***********************************************************************
2371 * PolyTextOutW (GDI32.@)
2373 * Draw several Strings
2375 * RETURNS
2376 * TRUE: Success.
2377 * FALSE: Failure.
2379 BOOL WINAPI PolyTextOutW( HDC hdc, const POLYTEXTW *pptxt, INT cStrings )
2381 for (; cStrings>0; cStrings--, pptxt++)
2382 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2383 return FALSE;
2384 return TRUE;
2388 /* FIXME: all following APIs ******************************************/
2391 /***********************************************************************
2392 * SetMapperFlags (GDI32.@)
2394 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
2396 DC *dc = get_dc_ptr( hDC );
2397 DWORD ret = 0;
2398 if(!dc) return 0;
2399 if(dc->funcs->pSetMapperFlags)
2401 ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
2402 /* FIXME: ret is just a success flag, we should return a proper value */
2404 else
2405 FIXME("(%p, 0x%08x): stub - harmless\n", hDC, dwFlag);
2406 release_dc_ptr( dc );
2407 return ret;
2410 /***********************************************************************
2411 * GetAspectRatioFilterEx (GDI.486)
2413 BOOL16 WINAPI GetAspectRatioFilterEx16( HDC16 hdc, LPSIZE16 pAspectRatio )
2415 FIXME("(%04x, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2416 return FALSE;
2419 /***********************************************************************
2420 * GetAspectRatioFilterEx (GDI32.@)
2422 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2424 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2425 return FALSE;
2429 /***********************************************************************
2430 * GetCharABCWidthsA (GDI32.@)
2432 * See GetCharABCWidthsW.
2434 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2435 LPABC abc )
2437 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
2438 LPSTR str;
2439 LPWSTR wstr;
2440 BOOL ret = TRUE;
2442 if(count <= 0) return FALSE;
2444 str = HeapAlloc(GetProcessHeap(), 0, count);
2445 for(i = 0; i < count; i++)
2446 str[i] = (BYTE)(firstChar + i);
2448 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
2450 for(i = 0; i < wlen; i++)
2452 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2454 ret = FALSE;
2455 break;
2457 abc++;
2460 HeapFree(GetProcessHeap(), 0, str);
2461 HeapFree(GetProcessHeap(), 0, wstr);
2463 return ret;
2467 /******************************************************************************
2468 * GetCharABCWidthsW [GDI32.@]
2470 * Retrieves widths of characters in range.
2472 * PARAMS
2473 * hdc [I] Handle of device context
2474 * firstChar [I] First character in range to query
2475 * lastChar [I] Last character in range to query
2476 * abc [O] Address of character-width structure
2478 * NOTES
2479 * Only works with TrueType fonts
2481 * RETURNS
2482 * Success: TRUE
2483 * Failure: FALSE
2485 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2486 LPABC abc )
2488 DC *dc = get_dc_ptr(hdc);
2489 unsigned int i;
2490 BOOL ret = FALSE;
2492 if (!dc) return FALSE;
2494 if (!abc)
2496 release_dc_ptr( dc );
2497 return FALSE;
2500 if(dc->gdiFont)
2501 ret = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
2502 else
2503 FIXME(": stub\n");
2505 if (ret)
2507 /* convert device units to logical */
2508 for( i = firstChar; i <= lastChar; i++, abc++ ) {
2509 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2510 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2511 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2513 ret = TRUE;
2516 release_dc_ptr( dc );
2517 return ret;
2521 /******************************************************************************
2522 * GetCharABCWidthsI [GDI32.@]
2524 * Retrieves widths of characters in range.
2526 * PARAMS
2527 * hdc [I] Handle of device context
2528 * firstChar [I] First glyphs in range to query
2529 * count [I] Last glyphs in range to query
2530 * pgi [i] Array of glyphs to query
2531 * abc [O] Address of character-width structure
2533 * NOTES
2534 * Only works with TrueType fonts
2536 * RETURNS
2537 * Success: TRUE
2538 * Failure: FALSE
2540 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2541 LPWORD pgi, LPABC abc)
2543 DC *dc = get_dc_ptr(hdc);
2544 unsigned int i;
2545 BOOL ret = FALSE;
2547 if (!dc) return FALSE;
2549 if (!abc)
2551 release_dc_ptr( dc );
2552 return FALSE;
2555 if(dc->gdiFont)
2556 ret = WineEngGetCharABCWidthsI( dc->gdiFont, firstChar, count, pgi, abc );
2557 else
2558 FIXME(": stub\n");
2560 if (ret)
2562 /* convert device units to logical */
2563 for( i = 0; i < count; i++, abc++ ) {
2564 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2565 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2566 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2568 ret = TRUE;
2571 release_dc_ptr( dc );
2572 return ret;
2576 /***********************************************************************
2577 * GetGlyphOutlineA (GDI32.@)
2579 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2580 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2581 LPVOID lpBuffer, const MAT2 *lpmat2 )
2583 LPWSTR p = NULL;
2584 DWORD ret;
2585 UINT c;
2587 if(!(fuFormat & GGO_GLYPH_INDEX)) {
2588 int len;
2589 char mbchs[2];
2590 if(uChar > 0xff) { /* but, 2 bytes character only */
2591 len = 2;
2592 mbchs[0] = (uChar & 0xff00) >> 8;
2593 mbchs[1] = (uChar & 0xff);
2594 } else {
2595 len = 1;
2596 mbchs[0] = (uChar & 0xff);
2598 p = FONT_mbtowc(hdc, mbchs, len, NULL, NULL);
2599 c = p[0];
2600 } else
2601 c = uChar;
2602 ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
2603 lpmat2);
2604 HeapFree(GetProcessHeap(), 0, p);
2605 return ret;
2608 /***********************************************************************
2609 * GetGlyphOutlineW (GDI32.@)
2611 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2612 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2613 LPVOID lpBuffer, const MAT2 *lpmat2 )
2615 DC *dc = get_dc_ptr(hdc);
2616 DWORD ret;
2618 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2619 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2621 if(!dc) return GDI_ERROR;
2623 if(dc->gdiFont)
2624 ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
2625 cbBuffer, lpBuffer, lpmat2);
2626 else
2627 ret = GDI_ERROR;
2629 release_dc_ptr( dc );
2630 return ret;
2634 /***********************************************************************
2635 * CreateScalableFontResourceA (GDI32.@)
2637 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2638 LPCSTR lpszResourceFile,
2639 LPCSTR lpszFontFile,
2640 LPCSTR lpszCurrentPath )
2642 HANDLE f;
2644 /* fHidden=1 - only visible for the calling app, read-only, not
2645 * enumbered with EnumFonts/EnumFontFamilies
2646 * lpszCurrentPath can be NULL
2648 FIXME("(%d,%s,%s,%s): stub\n",
2649 fHidden, debugstr_a(lpszResourceFile), debugstr_a(lpszFontFile),
2650 debugstr_a(lpszCurrentPath) );
2652 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2653 if ((f = CreateFileA(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2654 CloseHandle(f);
2655 SetLastError(ERROR_FILE_EXISTS);
2656 return FALSE;
2658 return FALSE; /* create failed */
2661 /***********************************************************************
2662 * CreateScalableFontResourceW (GDI32.@)
2664 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2665 LPCWSTR lpszResourceFile,
2666 LPCWSTR lpszFontFile,
2667 LPCWSTR lpszCurrentPath )
2669 FIXME("(%d,%p,%p,%p): stub\n",
2670 fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
2671 return FALSE; /* create failed */
2674 /*************************************************************************
2675 * GetKerningPairsA (GDI32.@)
2677 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2678 LPKERNINGPAIR kern_pairA )
2680 INT charset;
2681 CHARSETINFO csi;
2682 CPINFO cpi;
2683 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2684 KERNINGPAIR *kern_pairW;
2686 if (!cPairs && kern_pairA)
2688 SetLastError(ERROR_INVALID_PARAMETER);
2689 return 0;
2692 charset = GetTextCharset(hDC);
2693 if (!TranslateCharsetInfo(ULongToPtr(charset), &csi, TCI_SRCCHARSET))
2695 FIXME("Can't find codepage for charset %d\n", charset);
2696 return 0;
2698 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2699 * to fail on an invalid character for CP_SYMBOL.
2701 cpi.DefaultChar[0] = 0;
2702 if (csi.ciACP != CP_SYMBOL && !GetCPInfo(csi.ciACP, &cpi))
2704 FIXME("Can't find codepage %u info\n", csi.ciACP);
2705 return 0;
2707 TRACE("charset %d => codepage %u\n", charset, csi.ciACP);
2709 total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2710 if (!total_kern_pairs) return 0;
2712 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2713 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2715 for (i = 0; i < total_kern_pairs; i++)
2717 char first, second;
2719 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2720 continue;
2722 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2723 continue;
2725 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2726 continue;
2728 if (kern_pairA)
2730 if (kern_pairs_copied >= cPairs) break;
2732 kern_pairA->wFirst = (BYTE)first;
2733 kern_pairA->wSecond = (BYTE)second;
2734 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2735 kern_pairA++;
2737 kern_pairs_copied++;
2740 HeapFree(GetProcessHeap(), 0, kern_pairW);
2742 return kern_pairs_copied;
2745 /*************************************************************************
2746 * GetKerningPairsW (GDI32.@)
2748 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2749 LPKERNINGPAIR lpKerningPairs )
2751 DC *dc;
2752 DWORD ret = 0;
2754 TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2756 if (!cPairs && lpKerningPairs)
2758 SetLastError(ERROR_INVALID_PARAMETER);
2759 return 0;
2762 dc = get_dc_ptr(hDC);
2763 if (!dc) return 0;
2765 if (dc->gdiFont)
2766 ret = WineEngGetKerningPairs(dc->gdiFont, cPairs, lpKerningPairs);
2768 release_dc_ptr( dc );
2769 return ret;
2772 /*************************************************************************
2773 * TranslateCharsetInfo [GDI32.@]
2775 * Fills a CHARSETINFO structure for a character set, code page, or
2776 * font. This allows making the correspondence between different labels
2777 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2778 * of the same encoding.
2780 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2781 * only one codepage should be set in *lpSrc.
2783 * RETURNS
2784 * TRUE on success, FALSE on failure.
2787 BOOL WINAPI TranslateCharsetInfo(
2788 LPDWORD lpSrc, /* [in]
2789 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2790 if flags == TCI_SRCCHARSET: a character set value
2791 if flags == TCI_SRCCODEPAGE: a code page value
2793 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2794 DWORD flags /* [in] determines interpretation of lpSrc */)
2796 int index = 0;
2797 switch (flags) {
2798 case TCI_SRCFONTSIG:
2799 while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
2800 break;
2801 case TCI_SRCCODEPAGE:
2802 while (PtrToUlong(lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
2803 break;
2804 case TCI_SRCCHARSET:
2805 while (PtrToUlong(lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
2806 break;
2807 default:
2808 return FALSE;
2810 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2811 memcpy(lpCs, &FONT_tci[index], sizeof(CHARSETINFO));
2812 return TRUE;
2815 /*************************************************************************
2816 * GetFontLanguageInfo (GDI32.@)
2818 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2820 FONTSIGNATURE fontsig;
2821 static const DWORD GCP_DBCS_MASK=0x003F0000,
2822 GCP_DIACRITIC_MASK=0x00000000,
2823 FLI_GLYPHS_MASK=0x00000000,
2824 GCP_GLYPHSHAPE_MASK=0x00000040,
2825 GCP_KASHIDA_MASK=0x00000000,
2826 GCP_LIGATE_MASK=0x00000000,
2827 GCP_USEKERNING_MASK=0x00000000,
2828 GCP_REORDER_MASK=0x00000060;
2830 DWORD result=0;
2832 GetTextCharsetInfo( hdc, &fontsig, 0 );
2833 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2835 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2836 result|=GCP_DBCS;
2838 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2839 result|=GCP_DIACRITIC;
2841 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2842 result|=FLI_GLYPHS;
2844 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2845 result|=GCP_GLYPHSHAPE;
2847 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2848 result|=GCP_KASHIDA;
2850 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2851 result|=GCP_LIGATE;
2853 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2854 result|=GCP_USEKERNING;
2856 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2857 if( GetTextAlign( hdc) & TA_RTLREADING )
2858 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2859 result|=GCP_REORDER;
2861 return result;
2865 /*************************************************************************
2866 * GetFontData [GDI32.@]
2868 * Retrieve data for TrueType font.
2870 * RETURNS
2872 * success: Number of bytes returned
2873 * failure: GDI_ERROR
2875 * NOTES
2877 * Calls SetLastError()
2880 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2881 LPVOID buffer, DWORD length)
2883 DC *dc = get_dc_ptr(hdc);
2884 DWORD ret = GDI_ERROR;
2886 if(!dc) return GDI_ERROR;
2888 if(dc->gdiFont)
2889 ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2891 release_dc_ptr( dc );
2892 return ret;
2895 /*************************************************************************
2896 * GetGlyphIndicesA [GDI32.@]
2898 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2899 LPWORD pgi, DWORD flags)
2901 DWORD ret;
2902 WCHAR *lpstrW;
2903 INT countW;
2905 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2906 hdc, debugstr_an(lpstr, count), count, pgi, flags);
2908 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2909 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2910 HeapFree(GetProcessHeap(), 0, lpstrW);
2912 return ret;
2915 /*************************************************************************
2916 * GetGlyphIndicesW [GDI32.@]
2918 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2919 LPWORD pgi, DWORD flags)
2921 DC *dc = get_dc_ptr(hdc);
2922 DWORD ret = GDI_ERROR;
2924 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2925 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2927 if(!dc) return GDI_ERROR;
2929 if(dc->gdiFont)
2930 ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2932 release_dc_ptr( dc );
2933 return ret;
2936 /*************************************************************************
2937 * GetCharacterPlacementA [GDI32.@]
2939 * See GetCharacterPlacementW.
2941 * NOTES:
2942 * the web browser control of ie4 calls this with dwFlags=0
2944 DWORD WINAPI
2945 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2946 INT nMaxExtent, GCP_RESULTSA *lpResults,
2947 DWORD dwFlags)
2949 WCHAR *lpStringW;
2950 INT uCountW;
2951 GCP_RESULTSW resultsW;
2952 DWORD ret;
2953 UINT font_cp;
2955 TRACE("%s, %d, %d, 0x%08x\n",
2956 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2958 /* both structs are equal in size */
2959 memcpy(&resultsW, lpResults, sizeof(resultsW));
2961 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2962 if(lpResults->lpOutString)
2963 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2965 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2967 lpResults->nGlyphs = resultsW.nGlyphs;
2968 lpResults->nMaxFit = resultsW.nMaxFit;
2970 if(lpResults->lpOutString) {
2971 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2972 lpResults->lpOutString, uCount, NULL, NULL );
2975 HeapFree(GetProcessHeap(), 0, lpStringW);
2976 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2978 return ret;
2981 /*************************************************************************
2982 * GetCharacterPlacementW [GDI32.@]
2984 * Retrieve information about a string. This includes the width, reordering,
2985 * Glyphing and so on.
2987 * RETURNS
2989 * The width and height of the string if successful, 0 if failed.
2991 * BUGS
2993 * All flags except GCP_REORDER are not yet implemented.
2994 * Reordering is not 100% complient to the Windows BiDi method.
2995 * Caret positioning is not yet implemented for BiDi.
2996 * Classes are not yet implemented.
2999 DWORD WINAPI
3000 GetCharacterPlacementW(
3001 HDC hdc, /* [in] Device context for which the rendering is to be done */
3002 LPCWSTR lpString, /* [in] The string for which information is to be returned */
3003 INT uCount, /* [in] Number of WORDS in string. */
3004 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
3005 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
3006 DWORD dwFlags /* [in] Flags specifying how to process the string */
3009 DWORD ret=0;
3010 SIZE size;
3011 UINT i, nSet;
3013 TRACE("%s, %d, %d, 0x%08x\n",
3014 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
3016 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
3017 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
3018 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
3019 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
3020 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
3022 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08x ignored\n", dwFlags);
3023 if(lpResults->lpClass) FIXME("classes not implemented\n");
3024 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
3025 FIXME("Caret positions for complex scripts not implemented\n");
3027 nSet = (UINT)uCount;
3028 if(nSet > lpResults->nGlyphs)
3029 nSet = lpResults->nGlyphs;
3031 /* return number of initialized fields */
3032 lpResults->nGlyphs = nSet;
3034 if((dwFlags&GCP_REORDER)==0 )
3036 /* Treat the case where no special handling was requested in a fastpath way */
3037 /* copy will do if the GCP_REORDER flag is not set */
3038 if(lpResults->lpOutString)
3039 memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
3041 if(lpResults->lpOrder)
3043 for(i = 0; i < nSet; i++)
3044 lpResults->lpOrder[i] = i;
3046 } else
3048 BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
3049 nSet, lpResults->lpOrder );
3052 /* FIXME: Will use the placement chars */
3053 if (lpResults->lpDx)
3055 int c;
3056 for (i = 0; i < nSet; i++)
3058 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
3059 lpResults->lpDx[i]= c;
3063 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
3065 int pos = 0;
3067 lpResults->lpCaretPos[0] = 0;
3068 for (i = 1; i < nSet; i++)
3069 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
3070 lpResults->lpCaretPos[i] = (pos += size.cx);
3073 if(lpResults->lpGlyphs)
3074 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
3076 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
3077 ret = MAKELONG(size.cx, size.cy);
3079 return ret;
3082 /*************************************************************************
3083 * GetCharABCWidthsFloatA [GDI32.@]
3085 * See GetCharABCWidthsFloatW.
3087 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3089 INT i, wlen, count = (INT)(last - first + 1);
3090 LPSTR str;
3091 LPWSTR wstr;
3092 BOOL ret = TRUE;
3094 if (count <= 0) return FALSE;
3096 str = HeapAlloc(GetProcessHeap(), 0, count);
3098 for(i = 0; i < count; i++)
3099 str[i] = (BYTE)(first + i);
3101 wstr = FONT_mbtowc( hdc, str, count, &wlen, NULL );
3103 for (i = 0; i < wlen; i++)
3105 if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
3107 ret = FALSE;
3108 break;
3110 abcf++;
3113 HeapFree( GetProcessHeap(), 0, str );
3114 HeapFree( GetProcessHeap(), 0, wstr );
3116 return ret;
3119 /*************************************************************************
3120 * GetCharABCWidthsFloatW [GDI32.@]
3122 * Retrieves widths of a range of characters.
3124 * PARAMS
3125 * hdc [I] Handle to device context.
3126 * first [I] First character in range to query.
3127 * last [I] Last character in range to query.
3128 * abcf [O] Array of LPABCFLOAT structures.
3130 * RETURNS
3131 * Success: TRUE
3132 * Failure: FALSE
3134 * BUGS
3135 * Only works with TrueType fonts. It also doesn't return real
3136 * floats but converted integers because it's implemented on
3137 * top of GetCharABCWidthsW.
3139 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3141 ABC *abc;
3142 unsigned int i, size = sizeof(ABC) * (last - first + 1);
3143 BOOL ret;
3145 TRACE("%p, %d, %d, %p - partial stub\n", hdc, first, last, abcf);
3147 abc = HeapAlloc( GetProcessHeap(), 0, size );
3148 if (!abc) return FALSE;
3150 ret = GetCharABCWidthsW( hdc, first, last, abc );
3151 if (ret)
3153 for (i = first; i <= last; i++, abc++, abcf++)
3155 abcf->abcfA = abc->abcA;
3156 abcf->abcfB = abc->abcB;
3157 abcf->abcfC = abc->abcC;
3160 HeapFree( GetProcessHeap(), 0, abc );
3161 return ret;
3164 /*************************************************************************
3165 * GetCharWidthFloatA [GDI32.@]
3167 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
3168 UINT iLastChar, PFLOAT pxBuffer)
3170 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3171 return 0;
3174 /*************************************************************************
3175 * GetCharWidthFloatW [GDI32.@]
3177 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
3178 UINT iLastChar, PFLOAT pxBuffer)
3180 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3181 return 0;
3185 /***********************************************************************
3187 * Font Resource API *
3189 ***********************************************************************/
3191 /***********************************************************************
3192 * AddFontResourceA (GDI32.@)
3194 INT WINAPI AddFontResourceA( LPCSTR str )
3196 return AddFontResourceExA( str, 0, NULL);
3199 /***********************************************************************
3200 * AddFontResourceW (GDI32.@)
3202 INT WINAPI AddFontResourceW( LPCWSTR str )
3204 return AddFontResourceExW(str, 0, NULL);
3208 /***********************************************************************
3209 * AddFontResourceExA (GDI32.@)
3211 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3213 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3214 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3215 INT ret;
3217 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3218 ret = AddFontResourceExW(strW, fl, pdv);
3219 HeapFree(GetProcessHeap(), 0, strW);
3220 return ret;
3223 static BOOL CALLBACK load_enumed_resource(HMODULE hModule, LPCWSTR type, LPWSTR name, LONG_PTR lParam)
3225 HRSRC rsrc = FindResourceW(hModule, name, type);
3226 HGLOBAL hMem = LoadResource(hModule, rsrc);
3227 LPVOID *pMem = LockResource(hMem);
3228 int *num_total = (int *)lParam;
3229 DWORD num_in_res;
3231 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type));
3232 if (!AddFontMemResourceEx(pMem, SizeofResource(hModule, rsrc), NULL, &num_in_res))
3234 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule, hMem);
3235 return FALSE;
3238 *num_total += num_in_res;
3239 return TRUE;
3242 /***********************************************************************
3243 * AddFontResourceExW (GDI32.@)
3245 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3247 int ret = WineEngAddFontResourceEx(str, fl, pdv);
3248 if (ret == 0)
3250 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3251 HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
3252 if (hModule != NULL)
3254 int num_resources = 0;
3255 LPWSTR rt_font = (LPWSTR)((ULONG_PTR)8); /* we don't want to include winuser.h */
3257 TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3258 wine_dbgstr_w(str));
3259 if (EnumResourceNamesW(hModule, rt_font, load_enumed_resource, (LONG_PTR)&num_resources))
3260 ret = num_resources;
3261 FreeLibrary(hModule);
3264 return ret;
3267 /***********************************************************************
3268 * RemoveFontResourceA (GDI32.@)
3270 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3272 return RemoveFontResourceExA(str, 0, 0);
3275 /***********************************************************************
3276 * RemoveFontResourceW (GDI32.@)
3278 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3280 return RemoveFontResourceExW(str, 0, 0);
3283 /***********************************************************************
3284 * AddFontMemResourceEx (GDI32.@)
3286 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3288 return WineEngAddFontMemResourceEx(pbFont, cbFont, pdv, pcFonts);
3291 /***********************************************************************
3292 * RemoveFontMemResourceEx (GDI32.@)
3294 BOOL WINAPI RemoveFontMemResourceEx( HANDLE fh )
3296 FIXME("(%p) stub\n", fh);
3297 return TRUE;
3300 /***********************************************************************
3301 * RemoveFontResourceExA (GDI32.@)
3303 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3305 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3306 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3307 INT ret;
3309 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3310 ret = RemoveFontResourceExW(strW, fl, pdv);
3311 HeapFree(GetProcessHeap(), 0, strW);
3312 return ret;
3315 /***********************************************************************
3316 * RemoveFontResourceExW (GDI32.@)
3318 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3320 return WineEngRemoveFontResourceEx(str, fl, pdv);
3323 /***********************************************************************
3324 * GetTextCharset (GDI32.@)
3326 UINT WINAPI GetTextCharset(HDC hdc)
3328 /* MSDN docs say this is equivalent */
3329 return GetTextCharsetInfo(hdc, NULL, 0);
3332 /***********************************************************************
3333 * GetTextCharsetInfo (GDI32.@)
3335 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3337 UINT ret = DEFAULT_CHARSET;
3338 DC *dc = get_dc_ptr(hdc);
3340 if (dc)
3342 if (dc->gdiFont)
3343 ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
3345 release_dc_ptr( dc );
3348 if (ret == DEFAULT_CHARSET && fs)
3349 memset(fs, 0, sizeof(FONTSIGNATURE));
3350 return ret;
3353 /***********************************************************************
3354 * GdiGetCharDimensions (GDI32.@)
3356 * Gets the average width of the characters in the English alphabet.
3358 * PARAMS
3359 * hdc [I] Handle to the device context to measure on.
3360 * lptm [O] Pointer to memory to store the text metrics into.
3361 * height [O] On exit, the maximum height of characters in the English alphabet.
3363 * RETURNS
3364 * The average width of characters in the English alphabet.
3366 * NOTES
3367 * This function is used by the dialog manager to get the size of a dialog
3368 * unit. It should also be used by other pieces of code that need to know
3369 * the size of a dialog unit in logical units without having access to the
3370 * window handle of the dialog.
3371 * Windows caches the font metrics from this function, but we don't and
3372 * there doesn't appear to be an immediate advantage to do so.
3374 * SEE ALSO
3375 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3377 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3379 SIZE sz;
3380 static const WCHAR alphabet[] = {
3381 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3382 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3383 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3385 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3387 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3389 if (height) *height = sz.cy;
3390 return (sz.cx / 26 + 1) / 2;
3393 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3395 FIXME("(%d): stub\n", fEnableEUDC);
3396 return FALSE;
3399 /***********************************************************************
3400 * GetCharWidthI (GDI32.@)
3402 * Retrieve widths of characters.
3404 * PARAMS
3405 * hdc [I] Handle to a device context.
3406 * first [I] First glyph in range to query.
3407 * count [I] Number of glyph indices to query.
3408 * glyphs [I] Array of glyphs to query.
3409 * buffer [O] Buffer to receive character widths.
3411 * NOTES
3412 * Only works with TrueType fonts.
3414 * RETURNS
3415 * Success: TRUE
3416 * Failure: FALSE
3418 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3420 ABC *abc;
3421 unsigned int i;
3423 TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3425 if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3426 return FALSE;
3428 if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3430 HeapFree(GetProcessHeap(), 0, abc);
3431 return FALSE;
3434 for (i = 0; i < count; i++)
3435 buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3437 HeapFree(GetProcessHeap(), 0, abc);
3438 return TRUE;
3441 /***********************************************************************
3442 * GetFontUnicodeRanges (GDI32.@)
3444 * Retrieve a list of supported Unicode characters in a font.
3446 * PARAMS
3447 * hdc [I] Handle to a device context.
3448 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3450 * RETURNS
3451 * Success: Number of bytes written to the buffer pointed to by lpgs.
3452 * Failure: 0
3455 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3457 DWORD ret = 0;
3458 DC *dc = get_dc_ptr(hdc);
3460 TRACE("(%p, %p)\n", hdc, lpgs);
3462 if (!dc) return 0;
3464 if (dc->gdiFont) ret = WineEngGetFontUnicodeRanges(dc->gdiFont, lpgs);
3465 release_dc_ptr(dc);
3466 return ret;
3470 /*************************************************************
3471 * FontIsLinked (GDI32.@)
3473 BOOL WINAPI FontIsLinked(HDC hdc)
3475 DC *dc = get_dc_ptr(hdc);
3476 BOOL ret = FALSE;
3478 if (!dc) return FALSE;
3479 if (dc->gdiFont) ret = WineEngFontIsLinked(dc->gdiFont);
3480 release_dc_ptr(dc);
3481 TRACE("returning %d\n", ret);
3482 return ret;