advapi32/tests: No need to check return value of GetModuleHandle.
[wine/testsucceed.git] / dlls / gdi32 / font.c
blob1b1d8b43bdeb3d76de598d99dce61e0a44d27559
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, void *obj, HDC hdc );
90 static INT FONT_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
91 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
92 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
93 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj );
95 static const struct gdi_obj_funcs font_funcs =
97 FONT_SelectObject, /* pSelectObject */
98 FONT_GetObject16, /* pGetObject16 */
99 FONT_GetObjectA, /* pGetObjectA */
100 FONT_GetObjectW, /* pGetObjectW */
101 NULL, /* pUnrealizeObject */
102 FONT_DeleteObject /* pDeleteObject */
105 #define ENUM_UNICODE 0x00000001
106 #define ENUM_CALLED 0x00000002
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 DC *dc;
127 PHYSDEV physDev;
128 } fontEnum16;
130 typedef struct
132 LPLOGFONTW lpLogFontParam;
133 FONTENUMPROCW lpEnumFunc;
134 LPARAM lpData;
135 DWORD dwFlags;
136 HDC hdc;
137 DC *dc;
138 PHYSDEV physDev;
139 } fontEnum32;
142 * For TranslateCharsetInfo
144 #define FS(x) {{0,0,0,0},{0x1<<(x),0}}
145 #define MAXTCIINDEX 32
146 static const CHARSETINFO FONT_tci[MAXTCIINDEX] = {
147 /* ANSI */
148 { ANSI_CHARSET, 1252, FS(0)},
149 { EASTEUROPE_CHARSET, 1250, FS(1)},
150 { RUSSIAN_CHARSET, 1251, FS(2)},
151 { GREEK_CHARSET, 1253, FS(3)},
152 { TURKISH_CHARSET, 1254, FS(4)},
153 { HEBREW_CHARSET, 1255, FS(5)},
154 { ARABIC_CHARSET, 1256, FS(6)},
155 { BALTIC_CHARSET, 1257, FS(7)},
156 { VIETNAMESE_CHARSET, 1258, FS(8)},
157 /* reserved by ANSI */
158 { DEFAULT_CHARSET, 0, FS(0)},
159 { DEFAULT_CHARSET, 0, FS(0)},
160 { DEFAULT_CHARSET, 0, FS(0)},
161 { DEFAULT_CHARSET, 0, FS(0)},
162 { DEFAULT_CHARSET, 0, FS(0)},
163 { DEFAULT_CHARSET, 0, FS(0)},
164 { DEFAULT_CHARSET, 0, FS(0)},
165 /* ANSI and OEM */
166 { THAI_CHARSET, 874, FS(16)},
167 { SHIFTJIS_CHARSET, 932, FS(17)},
168 { GB2312_CHARSET, 936, FS(18)},
169 { HANGEUL_CHARSET, 949, FS(19)},
170 { CHINESEBIG5_CHARSET, 950, FS(20)},
171 { JOHAB_CHARSET, 1361, FS(21)},
172 /* reserved for alternate ANSI and OEM */
173 { DEFAULT_CHARSET, 0, FS(0)},
174 { DEFAULT_CHARSET, 0, FS(0)},
175 { DEFAULT_CHARSET, 0, FS(0)},
176 { DEFAULT_CHARSET, 0, FS(0)},
177 { DEFAULT_CHARSET, 0, FS(0)},
178 { DEFAULT_CHARSET, 0, FS(0)},
179 { DEFAULT_CHARSET, 0, FS(0)},
180 { DEFAULT_CHARSET, 0, FS(0)},
181 /* reserved for system */
182 { DEFAULT_CHARSET, 0, FS(0)},
183 { SYMBOL_CHARSET, CP_SYMBOL, FS(31)},
186 /***********************************************************************
187 * LOGFONT conversion functions.
189 static void FONT_LogFontWTo16( const LOGFONTW* font32, LPLOGFONT16 font16 )
191 font16->lfHeight = font32->lfHeight;
192 font16->lfWidth = font32->lfWidth;
193 font16->lfEscapement = font32->lfEscapement;
194 font16->lfOrientation = font32->lfOrientation;
195 font16->lfWeight = font32->lfWeight;
196 font16->lfItalic = font32->lfItalic;
197 font16->lfUnderline = font32->lfUnderline;
198 font16->lfStrikeOut = font32->lfStrikeOut;
199 font16->lfCharSet = font32->lfCharSet;
200 font16->lfOutPrecision = font32->lfOutPrecision;
201 font16->lfClipPrecision = font32->lfClipPrecision;
202 font16->lfQuality = font32->lfQuality;
203 font16->lfPitchAndFamily = font32->lfPitchAndFamily;
204 WideCharToMultiByte( CP_ACP, 0, font32->lfFaceName, -1,
205 font16->lfFaceName, LF_FACESIZE, NULL, NULL );
206 font16->lfFaceName[LF_FACESIZE-1] = 0;
209 static void FONT_LogFont16ToW( const LOGFONT16 *font16, LPLOGFONTW font32 )
211 font32->lfHeight = font16->lfHeight;
212 font32->lfWidth = font16->lfWidth;
213 font32->lfEscapement = font16->lfEscapement;
214 font32->lfOrientation = font16->lfOrientation;
215 font32->lfWeight = font16->lfWeight;
216 font32->lfItalic = font16->lfItalic;
217 font32->lfUnderline = font16->lfUnderline;
218 font32->lfStrikeOut = font16->lfStrikeOut;
219 font32->lfCharSet = font16->lfCharSet;
220 font32->lfOutPrecision = font16->lfOutPrecision;
221 font32->lfClipPrecision = font16->lfClipPrecision;
222 font32->lfQuality = font16->lfQuality;
223 font32->lfPitchAndFamily = font16->lfPitchAndFamily;
224 MultiByteToWideChar( CP_ACP, 0, font16->lfFaceName, -1, font32->lfFaceName, LF_FACESIZE );
225 font32->lfFaceName[LF_FACESIZE-1] = 0;
228 static void FONT_LogFontAToW( const LOGFONTA *fontA, LPLOGFONTW fontW )
230 memcpy(fontW, fontA, sizeof(LOGFONTA) - LF_FACESIZE);
231 MultiByteToWideChar(CP_ACP, 0, fontA->lfFaceName, -1, fontW->lfFaceName,
232 LF_FACESIZE);
233 fontW->lfFaceName[LF_FACESIZE-1] = 0;
236 static void FONT_LogFontWToA( const LOGFONTW *fontW, LPLOGFONTA fontA )
238 memcpy(fontA, fontW, sizeof(LOGFONTA) - LF_FACESIZE);
239 WideCharToMultiByte(CP_ACP, 0, fontW->lfFaceName, -1, fontA->lfFaceName,
240 LF_FACESIZE, NULL, NULL);
241 fontA->lfFaceName[LF_FACESIZE-1] = 0;
244 static void FONT_EnumLogFontExWTo16( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEX16 font16 )
246 FONT_LogFontWTo16( (const LOGFONTW *)fontW, (LPLOGFONT16)font16);
248 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
249 (LPSTR) font16->elfFullName, LF_FULLFACESIZE, NULL, NULL );
250 font16->elfFullName[LF_FULLFACESIZE-1] = '\0';
251 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
252 (LPSTR) font16->elfStyle, LF_FACESIZE, NULL, NULL );
253 font16->elfStyle[LF_FACESIZE-1] = '\0';
254 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
255 (LPSTR) font16->elfScript, LF_FACESIZE, NULL, NULL );
256 font16->elfScript[LF_FACESIZE-1] = '\0';
259 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEXA fontA )
261 FONT_LogFontWToA( (const LOGFONTW *)fontW, (LPLOGFONTA)fontA);
263 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
264 (LPSTR) fontA->elfFullName, LF_FULLFACESIZE, NULL, NULL );
265 fontA->elfFullName[LF_FULLFACESIZE-1] = '\0';
266 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
267 (LPSTR) fontA->elfStyle, LF_FACESIZE, NULL, NULL );
268 fontA->elfStyle[LF_FACESIZE-1] = '\0';
269 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
270 (LPSTR) fontA->elfScript, LF_FACESIZE, NULL, NULL );
271 fontA->elfScript[LF_FACESIZE-1] = '\0';
274 /***********************************************************************
275 * TEXTMETRIC conversion functions.
277 static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
279 ptmA->tmHeight = ptmW->tmHeight;
280 ptmA->tmAscent = ptmW->tmAscent;
281 ptmA->tmDescent = ptmW->tmDescent;
282 ptmA->tmInternalLeading = ptmW->tmInternalLeading;
283 ptmA->tmExternalLeading = ptmW->tmExternalLeading;
284 ptmA->tmAveCharWidth = ptmW->tmAveCharWidth;
285 ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth;
286 ptmA->tmWeight = ptmW->tmWeight;
287 ptmA->tmOverhang = ptmW->tmOverhang;
288 ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX;
289 ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
290 ptmA->tmFirstChar = ptmW->tmFirstChar > 255 ? 255 : ptmW->tmFirstChar;
291 ptmA->tmLastChar = ptmW->tmLastChar > 255 ? 255 : ptmW->tmLastChar;
292 ptmA->tmDefaultChar = ptmW->tmDefaultChar > 255 ? 255 : ptmW->tmDefaultChar;
293 ptmA->tmBreakChar = ptmW->tmBreakChar > 255 ? 255 : ptmW->tmBreakChar;
294 ptmA->tmItalic = ptmW->tmItalic;
295 ptmA->tmUnderlined = ptmW->tmUnderlined;
296 ptmA->tmStruckOut = ptmW->tmStruckOut;
297 ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
298 ptmA->tmCharSet = ptmW->tmCharSet;
302 static void FONT_NewTextMetricExWTo16(const NEWTEXTMETRICEXW *ptmW, LPNEWTEXTMETRICEX16 ptm16 )
304 ptm16->ntmTm.tmHeight = ptmW->ntmTm.tmHeight;
305 ptm16->ntmTm.tmAscent = ptmW->ntmTm.tmAscent;
306 ptm16->ntmTm.tmDescent = ptmW->ntmTm.tmDescent;
307 ptm16->ntmTm.tmInternalLeading = ptmW->ntmTm.tmInternalLeading;
308 ptm16->ntmTm.tmExternalLeading = ptmW->ntmTm.tmExternalLeading;
309 ptm16->ntmTm.tmAveCharWidth = ptmW->ntmTm.tmAveCharWidth;
310 ptm16->ntmTm.tmMaxCharWidth = ptmW->ntmTm.tmMaxCharWidth;
311 ptm16->ntmTm.tmWeight = ptmW->ntmTm.tmWeight;
312 ptm16->ntmTm.tmOverhang = ptmW->ntmTm.tmOverhang;
313 ptm16->ntmTm.tmDigitizedAspectX = ptmW->ntmTm.tmDigitizedAspectX;
314 ptm16->ntmTm.tmDigitizedAspectY = ptmW->ntmTm.tmDigitizedAspectY;
315 ptm16->ntmTm.tmFirstChar = ptmW->ntmTm.tmFirstChar > 255 ? 255 : ptmW->ntmTm.tmFirstChar;
316 ptm16->ntmTm.tmLastChar = ptmW->ntmTm.tmLastChar > 255 ? 255 : ptmW->ntmTm.tmLastChar;
317 ptm16->ntmTm.tmDefaultChar = ptmW->ntmTm.tmDefaultChar > 255 ? 255 : ptmW->ntmTm.tmDefaultChar;
318 ptm16->ntmTm.tmBreakChar = ptmW->ntmTm.tmBreakChar > 255 ? 255 : ptmW->ntmTm.tmBreakChar;
319 ptm16->ntmTm.tmItalic = ptmW->ntmTm.tmItalic;
320 ptm16->ntmTm.tmUnderlined = ptmW->ntmTm.tmUnderlined;
321 ptm16->ntmTm.tmStruckOut = ptmW->ntmTm.tmStruckOut;
322 ptm16->ntmTm.tmPitchAndFamily = ptmW->ntmTm.tmPitchAndFamily;
323 ptm16->ntmTm.tmCharSet = ptmW->ntmTm.tmCharSet;
324 ptm16->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
325 ptm16->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
326 ptm16->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
327 ptm16->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
328 memcpy(&ptm16->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
331 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW *ptmW, NEWTEXTMETRICEXA *ptmA )
333 FONT_TextMetricWToA((const TEXTMETRICW *)ptmW, (LPTEXTMETRICA)ptmA);
334 ptmA->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
335 ptmA->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
336 ptmA->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
337 ptmA->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
338 memcpy(&ptmA->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
342 /***********************************************************************
343 * FONT_mbtowc
345 * Returns a Unicode translation of str using the charset of the
346 * currently selected font in hdc. If count is -1 then str is assumed
347 * to be '\0' terminated, otherwise it contains the number of bytes to
348 * convert. If plenW is non-NULL, on return it will point to the
349 * number of WCHARs that have been written. If pCP is non-NULL, on
350 * return it will point to the codepage used in the conversion. The
351 * caller should free the returned LPWSTR from the process heap
352 * itself.
354 static LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
356 UINT cp = CP_ACP;
357 INT lenW;
358 LPWSTR strW;
359 CHARSETINFO csi;
360 int charset = GetTextCharset(hdc);
362 /* Hmm, nicely designed api this one! */
363 if(TranslateCharsetInfo((DWORD*)charset, &csi, TCI_SRCCHARSET))
364 cp = csi.ciACP;
365 else {
366 switch(charset) {
367 case OEM_CHARSET:
368 cp = GetOEMCP();
369 break;
370 case DEFAULT_CHARSET:
371 cp = GetACP();
372 break;
374 case VISCII_CHARSET:
375 case TCVN_CHARSET:
376 case KOI8_CHARSET:
377 case ISO3_CHARSET:
378 case ISO4_CHARSET:
379 case ISO10_CHARSET:
380 case CELTIC_CHARSET:
381 /* FIXME: These have no place here, but because x11drv
382 enumerates fonts with these (made up) charsets some apps
383 might use them and then the FIXME below would become
384 annoying. Now we could pick the intended codepage for
385 each of these, but since it's broken anyway we'll just
386 use CP_ACP and hope it'll go away...
388 cp = CP_ACP;
389 break;
391 default:
392 FIXME("Can't find codepage for charset %d\n", charset);
393 break;
397 TRACE("charset %d => cp %d\n", charset, cp);
399 if(count == -1) count = strlen(str);
400 lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
401 strW = HeapAlloc(GetProcessHeap(), 0, lenW*sizeof(WCHAR));
402 MultiByteToWideChar(cp, 0, str, count, strW, lenW);
403 TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW));
404 if(plenW) *plenW = lenW;
405 if(pCP) *pCP = cp;
406 return strW;
410 /***********************************************************************
411 * CreateFontIndirectA (GDI32.@)
413 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *plfA )
415 LOGFONTW lfW;
417 if (plfA) {
418 FONT_LogFontAToW( plfA, &lfW );
419 return CreateFontIndirectW( &lfW );
420 } else
421 return CreateFontIndirectW( NULL );
425 /***********************************************************************
426 * CreateFontIndirectW (GDI32.@)
428 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
430 HFONT hFont = 0;
432 if (plf)
434 FONTOBJ* fontPtr;
435 if ((fontPtr = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC,
436 (HGDIOBJ *)&hFont, &font_funcs )))
438 static const WCHAR ItalicW[] = {' ','I','t','a','l','i','c','\0'};
439 static const WCHAR BoldW[] = {' ','B','o','l','d','\0'};
440 WCHAR *pFaceNameItalicSuffix, *pFaceNameBoldSuffix;
441 WCHAR* pFaceNameSuffix = NULL;
443 memcpy( &fontPtr->logfont, plf, sizeof(LOGFONTW) );
445 TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
446 plf->lfHeight, plf->lfWidth,
447 plf->lfEscapement, plf->lfOrientation,
448 plf->lfPitchAndFamily,
449 plf->lfOutPrecision, plf->lfClipPrecision,
450 plf->lfQuality, plf->lfCharSet,
451 debugstr_w(plf->lfFaceName),
452 plf->lfWeight > 400 ? "Bold" : "",
453 plf->lfItalic ? "Italic" : "",
454 plf->lfUnderline ? "Underline" : "", hFont);
456 if (plf->lfEscapement != plf->lfOrientation) {
457 /* this should really depend on whether GM_ADVANCED is set */
458 fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
459 WARN("orientation angle %f set to "
460 "escapement angle %f for new font %p\n",
461 plf->lfOrientation/10., plf->lfEscapement/10., hFont);
464 pFaceNameItalicSuffix = strstrW(fontPtr->logfont.lfFaceName, ItalicW);
465 if (pFaceNameItalicSuffix) {
466 fontPtr->logfont.lfItalic = TRUE;
467 pFaceNameSuffix = pFaceNameItalicSuffix;
470 pFaceNameBoldSuffix = strstrW(fontPtr->logfont.lfFaceName, BoldW);
471 if (pFaceNameBoldSuffix) {
472 if (fontPtr->logfont.lfWeight < FW_BOLD) {
473 fontPtr->logfont.lfWeight = FW_BOLD;
475 if (!pFaceNameSuffix ||
476 (pFaceNameBoldSuffix < pFaceNameSuffix)) {
477 pFaceNameSuffix = pFaceNameBoldSuffix;
481 if (pFaceNameSuffix) *pFaceNameSuffix = 0;
483 GDI_ReleaseObj( hFont );
486 else WARN("(NULL) => NULL\n");
488 return hFont;
491 /*************************************************************************
492 * CreateFontA (GDI32.@)
494 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
495 INT orient, INT weight, DWORD italic,
496 DWORD underline, DWORD strikeout, DWORD charset,
497 DWORD outpres, DWORD clippres, DWORD quality,
498 DWORD pitch, LPCSTR name )
500 LOGFONTA logfont;
502 logfont.lfHeight = height;
503 logfont.lfWidth = width;
504 logfont.lfEscapement = esc;
505 logfont.lfOrientation = orient;
506 logfont.lfWeight = weight;
507 logfont.lfItalic = italic;
508 logfont.lfUnderline = underline;
509 logfont.lfStrikeOut = strikeout;
510 logfont.lfCharSet = charset;
511 logfont.lfOutPrecision = outpres;
512 logfont.lfClipPrecision = clippres;
513 logfont.lfQuality = quality;
514 logfont.lfPitchAndFamily = pitch;
516 if (name)
517 lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
518 else
519 logfont.lfFaceName[0] = '\0';
521 return CreateFontIndirectA( &logfont );
524 /*************************************************************************
525 * CreateFontW (GDI32.@)
527 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
528 INT orient, INT weight, DWORD italic,
529 DWORD underline, DWORD strikeout, DWORD charset,
530 DWORD outpres, DWORD clippres, DWORD quality,
531 DWORD pitch, LPCWSTR name )
533 LOGFONTW logfont;
535 logfont.lfHeight = height;
536 logfont.lfWidth = width;
537 logfont.lfEscapement = esc;
538 logfont.lfOrientation = orient;
539 logfont.lfWeight = weight;
540 logfont.lfItalic = italic;
541 logfont.lfUnderline = underline;
542 logfont.lfStrikeOut = strikeout;
543 logfont.lfCharSet = charset;
544 logfont.lfOutPrecision = outpres;
545 logfont.lfClipPrecision = clippres;
546 logfont.lfQuality = quality;
547 logfont.lfPitchAndFamily = pitch;
549 if (name)
550 lstrcpynW(logfont.lfFaceName, name,
551 sizeof(logfont.lfFaceName) / sizeof(WCHAR));
552 else
553 logfont.lfFaceName[0] = '\0';
555 return CreateFontIndirectW( &logfont );
559 /***********************************************************************
560 * FONT_SelectObject
562 * If the driver supports vector fonts we create a gdi font first and
563 * then call the driver to give it a chance to supply its own device
564 * font. If the driver wants to do this it returns TRUE and we can
565 * delete the gdi font, if the driver wants to use the gdi font it
566 * should return FALSE, to signal an error return GDI_ERROR. For
567 * drivers that don't support vector fonts they must supply their own
568 * font.
570 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, void *obj, HDC hdc )
572 HGDIOBJ ret = 0;
573 DC *dc = DC_GetDCPtr( hdc );
575 if (!dc) return 0;
577 if (dc->hFont != handle || dc->gdiFont == NULL)
579 if(GetDeviceCaps(dc->hSelf, TEXTCAPS) & TC_VA_ABLE)
580 dc->gdiFont = WineEngCreateFontInstance(dc, handle);
583 if (dc->funcs->pSelectFont) ret = dc->funcs->pSelectFont( dc->physDev, handle, dc->gdiFont );
585 if (ret && dc->gdiFont) dc->gdiFont = 0;
587 if (ret == HGDI_ERROR)
588 ret = 0; /* SelectObject returns 0 on error */
589 else
591 ret = dc->hFont;
592 dc->hFont = handle;
594 GDI_ReleaseObj( hdc );
595 return ret;
599 /***********************************************************************
600 * FONT_GetObject16
602 static INT FONT_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
604 FONTOBJ *font = obj;
605 LOGFONT16 lf16;
607 FONT_LogFontWTo16( &font->logfont, &lf16 );
609 if (count > sizeof(LOGFONT16)) count = sizeof(LOGFONT16);
610 memcpy( buffer, &lf16, count );
611 return count;
614 /***********************************************************************
615 * FONT_GetObjectA
617 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
619 FONTOBJ *font = obj;
620 LOGFONTA lfA;
622 if(!buffer)
623 return sizeof(lfA);
624 FONT_LogFontWToA( &font->logfont, &lfA );
626 if (count > sizeof(lfA)) count = sizeof(lfA);
627 memcpy( buffer, &lfA, count );
628 return count;
631 /***********************************************************************
632 * FONT_GetObjectW
634 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
636 FONTOBJ *font = obj;
637 if(!buffer)
638 return sizeof(LOGFONTW);
639 if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
640 memcpy( buffer, &font->logfont, count );
641 return count;
645 /***********************************************************************
646 * FONT_DeleteObject
648 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj )
650 WineEngDestroyFontInstance( handle );
651 return GDI_FreeObject( handle, obj );
655 /***********************************************************************
656 * FONT_EnumInstance16
658 * Called by the device driver layer to pass font info
659 * down to the application.
661 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
662 * We have to use other types because of the FONTENUMPROCW definition.
664 static INT CALLBACK FONT_EnumInstance16( const LOGFONTW *plf, const TEXTMETRICW *ptm,
665 DWORD fType, LPARAM lp )
667 fontEnum16 *pfe = (fontEnum16*)lp;
668 INT ret = 1;
669 DC *dc;
671 if( pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
672 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet )
674 WORD args[7];
675 DWORD result;
677 FONT_EnumLogFontExWTo16((const ENUMLOGFONTEXW *)plf, pfe->lpLogFont);
678 FONT_NewTextMetricExWTo16((const NEWTEXTMETRICEXW *)ptm, pfe->lpTextMetric);
679 pfe->dwFlags |= ENUM_CALLED;
680 GDI_ReleaseObj( pfe->hdc ); /* release the GDI lock */
682 args[6] = SELECTOROF(pfe->segLogFont);
683 args[5] = OFFSETOF(pfe->segLogFont);
684 args[4] = SELECTOROF(pfe->segTextMetric);
685 args[3] = OFFSETOF(pfe->segTextMetric);
686 args[2] = fType;
687 args[1] = HIWORD(pfe->lpData);
688 args[0] = LOWORD(pfe->lpData);
689 WOWCallback16Ex( (DWORD)pfe->lpEnumFunc, WCB16_PASCAL, sizeof(args), args, &result );
690 ret = LOWORD(result);
692 /* get the lock again and make sure the DC is still valid */
693 dc = DC_GetDCPtr( pfe->hdc );
694 if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
696 if (dc) GDI_ReleaseObj( pfe->hdc );
697 pfe->hdc = 0; /* make sure we don't try to release it later on */
698 ret = 0;
701 return ret;
704 /***********************************************************************
705 * FONT_EnumInstance
707 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
708 * We have to use other types because of the FONTENUMPROCW definition.
710 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
711 DWORD fType, LPARAM lp )
713 fontEnum32 *pfe = (fontEnum32*)lp;
714 INT ret = 1;
715 DC *dc;
717 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
718 if((pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
719 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
720 (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
722 /* convert font metrics */
723 ENUMLOGFONTEXA logfont;
724 NEWTEXTMETRICEXA tmA;
726 pfe->dwFlags |= ENUM_CALLED;
727 if (!(pfe->dwFlags & ENUM_UNICODE))
729 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
730 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
731 plf = (LOGFONTW *)&logfont.elfLogFont;
732 ptm = (TEXTMETRICW *)&tmA;
734 GDI_ReleaseObj( pfe->hdc ); /* release the GDI lock */
736 ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
738 /* get the lock again and make sure the DC is still valid */
739 dc = DC_GetDCPtr( pfe->hdc );
740 if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
742 if (dc) GDI_ReleaseObj( pfe->hdc );
743 pfe->hdc = 0; /* make sure we don't try to release it later on */
744 ret = 0;
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 = DC_GetDCPtr( HDC_32(hDC) );
760 NEWTEXTMETRICEX16 tm16;
761 ENUMLOGFONTEX16 lf16;
762 LOGFONTW lfW;
763 BOOL enum_gdi_fonts;
765 if (!dc) return 0;
766 FONT_LogFont16ToW(plf, &lfW);
768 fe16.hdc = HDC_32(hDC);
769 fe16.dc = dc;
770 fe16.physDev = dc->physDev;
771 fe16.lpLogFontParam = plf;
772 fe16.lpEnumFunc = efproc;
773 fe16.lpData = lParam;
774 fe16.lpTextMetric = &tm16;
775 fe16.lpLogFont = &lf16;
776 fe16.segTextMetric = MapLS( &tm16 );
777 fe16.segLogFont = MapLS( &lf16 );
778 fe16.dwFlags = 0;
780 enum_gdi_fonts = GetDeviceCaps(fe16.hdc, TEXTCAPS) & TC_VA_ABLE;
782 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
784 ret = 0;
785 goto done;
788 if (enum_gdi_fonts)
789 ret = WineEngEnumFonts( &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
790 fe16.dwFlags &= ~ENUM_CALLED;
791 if (ret && dc->funcs->pEnumDeviceFonts) {
792 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
793 if(fe16.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
794 ret = ret2;
796 done:
797 UnMapLS( fe16.segTextMetric );
798 UnMapLS( fe16.segLogFont );
799 if (fe16.hdc) GDI_ReleaseObj( fe16.hdc );
800 return ret;
803 /***********************************************************************
804 * FONT_EnumFontFamiliesEx
806 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf,
807 FONTENUMPROCW efproc,
808 LPARAM lParam, DWORD dwUnicode)
810 INT ret = 1, ret2;
811 DC *dc = DC_GetDCPtr( hDC );
812 fontEnum32 fe32;
813 BOOL enum_gdi_fonts;
815 if (!dc) return 0;
817 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName),
818 plf->lfCharSet);
819 fe32.lpLogFontParam = plf;
820 fe32.lpEnumFunc = efproc;
821 fe32.lpData = lParam;
822 fe32.dwFlags = dwUnicode;
823 fe32.hdc = hDC;
824 fe32.dc = dc;
825 fe32.physDev = dc->physDev;
827 enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE;
829 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
831 ret = 0;
832 goto done;
835 if (enum_gdi_fonts)
836 ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
837 fe32.dwFlags &= ~ENUM_CALLED;
838 if (ret && dc->funcs->pEnumDeviceFonts) {
839 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, plf, FONT_EnumInstance, (LPARAM)&fe32 );
840 if(fe32.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
841 ret = ret2;
843 done:
844 if (fe32.hdc) GDI_ReleaseObj( fe32.hdc );
845 return ret;
848 /***********************************************************************
849 * EnumFontFamiliesExW (GDI32.@)
851 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
852 FONTENUMPROCW efproc,
853 LPARAM lParam, DWORD dwFlags )
855 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, ENUM_UNICODE );
858 /***********************************************************************
859 * EnumFontFamiliesExA (GDI32.@)
861 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
862 FONTENUMPROCA efproc,
863 LPARAM lParam, DWORD dwFlags)
865 LOGFONTW lfW;
866 FONT_LogFontAToW( plf, &lfW );
868 return FONT_EnumFontFamiliesEx( hDC, &lfW, (FONTENUMPROCW)efproc, lParam, 0);
871 /***********************************************************************
872 * EnumFontFamilies (GDI.330)
874 INT16 WINAPI EnumFontFamilies16( HDC16 hDC, LPCSTR lpFamily,
875 FONTENUMPROC16 efproc, LPARAM lpData )
877 LOGFONT16 lf;
879 lf.lfCharSet = DEFAULT_CHARSET;
880 if (lpFamily)
882 if (!*lpFamily) return 1;
883 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
885 else lf.lfFaceName[0] = '\0';
887 return EnumFontFamiliesEx16( hDC, &lf, efproc, lpData, 0 );
890 /***********************************************************************
891 * EnumFontFamiliesA (GDI32.@)
893 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
894 FONTENUMPROCA efproc, LPARAM lpData )
896 LOGFONTA lf;
898 lf.lfCharSet = DEFAULT_CHARSET;
899 if (lpFamily)
901 if (!*lpFamily) return 1;
902 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
904 else lf.lfFaceName[0] = lf.lfFaceName[1] = '\0';
906 return EnumFontFamiliesExA( hDC, &lf, efproc, lpData, 0 );
909 /***********************************************************************
910 * EnumFontFamiliesW (GDI32.@)
912 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
913 FONTENUMPROCW efproc, LPARAM lpData )
915 LOGFONTW lf;
917 lf.lfCharSet = DEFAULT_CHARSET;
918 if (lpFamily)
920 if (!*lpFamily) return 1;
921 lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
923 else lf.lfFaceName[0] = 0;
925 return EnumFontFamiliesExW( hDC, &lf, efproc, lpData, 0 );
928 /***********************************************************************
929 * EnumFonts (GDI.70)
931 INT16 WINAPI EnumFonts16( HDC16 hDC, LPCSTR lpName, FONTENUMPROC16 efproc,
932 LPARAM lpData )
934 return EnumFontFamilies16( hDC, lpName, efproc, lpData );
937 /***********************************************************************
938 * EnumFontsA (GDI32.@)
940 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
941 LPARAM lpData )
943 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
946 /***********************************************************************
947 * EnumFontsW (GDI32.@)
949 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
950 LPARAM lpData )
952 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
956 /***********************************************************************
957 * GetTextCharacterExtra (GDI32.@)
959 INT WINAPI GetTextCharacterExtra( HDC hdc )
961 INT ret;
962 DC *dc = DC_GetDCPtr( hdc );
963 if (!dc) return 0x80000000;
964 ret = dc->charExtra;
965 GDI_ReleaseObj( hdc );
966 return ret;
970 /***********************************************************************
971 * SetTextCharacterExtra (GDI32.@)
973 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
975 INT prev;
976 DC * dc = DC_GetDCPtr( hdc );
977 if (!dc) return 0x80000000;
978 if (dc->funcs->pSetTextCharacterExtra)
979 prev = dc->funcs->pSetTextCharacterExtra( dc->physDev, extra );
980 else
982 prev = dc->charExtra;
983 dc->charExtra = extra;
985 GDI_ReleaseObj( hdc );
986 return prev;
990 /***********************************************************************
991 * SetTextJustification (GDI32.@)
993 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
995 BOOL ret = TRUE;
996 DC * dc = DC_GetDCPtr( hdc );
997 if (!dc) return FALSE;
998 if (dc->funcs->pSetTextJustification)
999 ret = dc->funcs->pSetTextJustification( dc->physDev, extra, breaks );
1000 else
1002 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
1003 if (!extra) breaks = 0;
1004 if (breaks)
1006 dc->breakExtra = extra / breaks;
1007 dc->breakRem = extra - (breaks * dc->breakExtra);
1009 else
1011 dc->breakExtra = 0;
1012 dc->breakRem = 0;
1015 GDI_ReleaseObj( hdc );
1016 return ret;
1020 /***********************************************************************
1021 * GetTextFaceA (GDI32.@)
1023 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
1025 INT res = GetTextFaceW(hdc, 0, NULL);
1026 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
1027 GetTextFaceW( hdc, res, nameW );
1029 if (name)
1031 if (count && !WideCharToMultiByte( CP_ACP, 0, nameW, -1, name, count, NULL, NULL))
1032 name[count-1] = 0;
1033 res = strlen(name);
1035 else
1036 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
1037 HeapFree( GetProcessHeap(), 0, nameW );
1038 return res;
1041 /***********************************************************************
1042 * GetTextFaceW (GDI32.@)
1044 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
1046 FONTOBJ *font;
1047 INT ret = 0;
1049 DC * dc = DC_GetDCPtr( hdc );
1050 if (!dc) return 0;
1052 if(dc->gdiFont)
1053 ret = WineEngGetTextFace(dc->gdiFont, count, name);
1054 else if ((font = (FONTOBJ *) GDI_GetObjPtr( dc->hFont, FONT_MAGIC )))
1056 if (name)
1058 lstrcpynW( name, font->logfont.lfFaceName, count );
1059 ret = strlenW(name);
1061 else ret = strlenW(font->logfont.lfFaceName) + 1;
1062 GDI_ReleaseObj( dc->hFont );
1064 GDI_ReleaseObj( hdc );
1065 return ret;
1069 /***********************************************************************
1070 * GetTextExtentPoint32A (GDI32.@)
1072 * See GetTextExtentPoint32W.
1074 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
1075 LPSIZE size )
1077 BOOL ret = FALSE;
1078 INT wlen;
1079 LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1081 if (p) {
1082 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
1083 HeapFree( GetProcessHeap(), 0, p );
1086 TRACE("(%p %s %d %p): returning %d x %d\n",
1087 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
1088 return ret;
1092 /***********************************************************************
1093 * GetTextExtentPoint32W [GDI32.@]
1095 * Computes width/height for a string.
1097 * Computes width and height of the specified string.
1099 * RETURNS
1100 * Success: TRUE
1101 * Failure: FALSE
1103 BOOL WINAPI GetTextExtentPoint32W(
1104 HDC hdc, /* [in] Handle of device context */
1105 LPCWSTR str, /* [in] Address of text string */
1106 INT count, /* [in] Number of characters in string */
1107 LPSIZE size) /* [out] Address of structure for string size */
1109 return GetTextExtentExPointW(hdc, str, count, 0, NULL, NULL, size);
1112 /***********************************************************************
1113 * GetTextExtentPointI [GDI32.@]
1115 * Computes width and height of the array of glyph indices.
1117 * RETURNS
1118 * Success: TRUE
1119 * Failure: FALSE
1121 BOOL WINAPI GetTextExtentPointI(
1122 HDC hdc, /* [in] Handle of device context */
1123 const WORD *indices, /* [in] Address of glyph index array */
1124 INT count, /* [in] Number of glyphs in array */
1125 LPSIZE size) /* [out] Address of structure for string size */
1127 BOOL ret = FALSE;
1128 DC * dc = DC_GetDCPtr( hdc );
1129 if (!dc) return FALSE;
1131 if(dc->gdiFont) {
1132 ret = WineEngGetTextExtentPointI(dc->gdiFont, indices, count, size);
1133 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1134 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1135 size->cx += count * dc->charExtra;
1137 else if(dc->funcs->pGetTextExtentExPoint) {
1138 FIXME("calling GetTextExtentExPoint\n");
1139 ret = dc->funcs->pGetTextExtentExPoint( dc->physDev, (LPCWSTR)indices,
1140 count, 0, NULL, NULL, size );
1143 GDI_ReleaseObj( hdc );
1145 TRACE("(%p %p %d %p): returning %d x %d\n",
1146 hdc, indices, count, size, size->cx, size->cy );
1147 return ret;
1151 /***********************************************************************
1152 * GetTextExtentPointA (GDI32.@)
1154 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
1155 LPSIZE size )
1157 TRACE("not bug compatible.\n");
1158 return GetTextExtentPoint32A( hdc, str, count, size );
1161 /***********************************************************************
1162 * GetTextExtentPointW (GDI32.@)
1164 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1165 LPSIZE size )
1167 TRACE("not bug compatible.\n");
1168 return GetTextExtentPoint32W( hdc, str, count, size );
1172 /***********************************************************************
1173 * GetTextExtentExPointA (GDI32.@)
1175 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1176 INT maxExt, LPINT lpnFit,
1177 LPINT alpDx, LPSIZE size )
1179 BOOL ret;
1180 INT wlen;
1181 INT *walpDx = NULL;
1182 LPWSTR p = NULL;
1184 if (alpDx &&
1185 NULL == (walpDx = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT))))
1186 return FALSE;
1188 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1189 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
1190 if (walpDx)
1192 INT n = lpnFit ? *lpnFit : wlen;
1193 INT i, j;
1194 for(i = 0, j = 0; i < n; i++, j++)
1196 alpDx[j] = walpDx[i];
1197 if (IsDBCSLeadByte(str[j])) alpDx[++j] = walpDx[i];
1200 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1201 HeapFree( GetProcessHeap(), 0, p );
1202 HeapFree( GetProcessHeap(), 0, walpDx );
1203 return ret;
1207 /***********************************************************************
1208 * GetTextExtentExPointW (GDI32.@)
1210 * Return the size of the string as it would be if it was output properly by
1211 * e.g. TextOut.
1213 * This should include
1214 * - Intercharacter spacing
1215 * - justification spacing (not yet done)
1216 * - kerning? see below
1218 * Kerning. Since kerning would be carried out by the rendering code it should
1219 * be done by the driver. However they don't support it yet. Also I am not
1220 * yet persuaded that (certainly under Win95) any kerning is actually done.
1222 * str: According to MSDN this should be null-terminated. That is not true; a
1223 * null will not terminate it early.
1224 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1225 * than count. I have seen it be either the size of the full string or
1226 * 1 less than the size of the full string. I have not seen it bear any
1227 * resemblance to the portion that would fit.
1228 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1229 * trailing intercharacter spacing and any trailing justification.
1231 * FIXME
1232 * Currently we do this by measuring each character etc. We should do it by
1233 * passing the request to the driver, perhaps by extending the
1234 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1235 * thinking about kerning issues and rounding issues in the justification.
1238 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1239 INT maxExt, LPINT lpnFit,
1240 LPINT alpDx, LPSIZE size )
1242 INT nFit = 0;
1243 LPINT dxs = NULL;
1244 DC *dc;
1245 BOOL ret = FALSE;
1246 TEXTMETRICW tm;
1248 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1250 dc = DC_GetDCPtr(hdc);
1251 if (! dc)
1252 return FALSE;
1254 GetTextMetricsW(hdc, &tm);
1256 /* If we need to calculate nFit, then we need the partial extents even if
1257 the user hasn't provided us with an array. */
1258 if (lpnFit)
1260 dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]);
1261 if (! dxs)
1263 GDI_ReleaseObj(hdc);
1264 SetLastError(ERROR_OUTOFMEMORY);
1265 return FALSE;
1268 else
1269 dxs = alpDx;
1271 if (dc->gdiFont)
1272 ret = WineEngGetTextExtentExPoint(dc->gdiFont, str, count,
1273 0, NULL, dxs, size);
1274 else if (dc->funcs->pGetTextExtentExPoint)
1275 ret = dc->funcs->pGetTextExtentExPoint(dc->physDev, str, count,
1276 0, NULL, dxs, size);
1278 /* Perform device size to world size transformations. */
1279 if (ret)
1281 INT extra = dc->charExtra,
1282 breakExtra = dc->breakExtra,
1283 breakRem = dc->breakRem,
1286 if (dxs)
1288 for (i = 0; i < count; ++i)
1290 dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
1291 dxs[i] += (i+1) * extra;
1292 if (count > 1 && (breakExtra || breakRem) && str[i] == tm.tmBreakChar)
1294 dxs[i] += breakExtra;
1295 if (breakRem > 0)
1297 breakRem--;
1298 dxs[i]++;
1301 if (dxs[i] <= maxExt)
1302 ++nFit;
1304 breakRem = dc->breakRem;
1306 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1307 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1309 if (!dxs && count > 1 && (breakExtra || breakRem))
1311 for (i = 0; i < count; i++)
1313 if (str[i] == tm.tmBreakChar)
1315 size->cx += breakExtra;
1316 if (breakRem > 0)
1318 breakRem--;
1319 (size->cx)++;
1326 if (lpnFit)
1327 *lpnFit = nFit;
1329 if (! alpDx)
1330 HeapFree(GetProcessHeap(), 0, dxs);
1332 GDI_ReleaseObj( hdc );
1334 TRACE("returning %d %d x %d\n",nFit,size->cx,size->cy);
1335 return ret;
1338 /***********************************************************************
1339 * GetTextMetricsA (GDI32.@)
1341 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1343 TEXTMETRICW tm32;
1345 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1346 FONT_TextMetricWToA( &tm32, metrics );
1347 return TRUE;
1350 /***********************************************************************
1351 * GetTextMetricsW (GDI32.@)
1353 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1355 BOOL ret = FALSE;
1356 DC * dc = DC_GetDCPtr( hdc );
1357 if (!dc) return FALSE;
1359 if (dc->gdiFont)
1360 ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1361 else if (dc->funcs->pGetTextMetrics)
1362 ret = dc->funcs->pGetTextMetrics( dc->physDev, metrics );
1364 if (ret)
1366 /* device layer returns values in device units
1367 * therefore we have to convert them to logical */
1369 #define WDPTOLP(x) ((x<0)? \
1370 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1371 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1372 #define HDPTOLP(y) ((y<0)? \
1373 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1374 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1376 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1377 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1378 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1379 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1380 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1381 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1382 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1383 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1384 ret = TRUE;
1385 #undef WDPTOLP
1386 #undef HDPTOLP
1387 TRACE("text metrics:\n"
1388 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1389 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1390 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1391 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1392 " PitchAndFamily = %02x\n"
1393 " --------------------\n"
1394 " InternalLeading = %i\n"
1395 " Ascent = %i\n"
1396 " Descent = %i\n"
1397 " Height = %i\n",
1398 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1399 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1400 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1401 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1402 metrics->tmPitchAndFamily,
1403 metrics->tmInternalLeading,
1404 metrics->tmAscent,
1405 metrics->tmDescent,
1406 metrics->tmHeight );
1408 GDI_ReleaseObj( hdc );
1409 return ret;
1413 /***********************************************************************
1414 * GetOutlineTextMetrics [GDI.308] Gets metrics for TrueType fonts.
1416 * NOTES
1417 * lpOTM should be LPOUTLINETEXTMETRIC
1419 * RETURNS
1420 * Success: Non-zero or size of required buffer
1421 * Failure: 0
1423 UINT16 WINAPI GetOutlineTextMetrics16(
1424 HDC16 hdc, /* [in] Handle of device context */
1425 UINT16 cbData, /* [in] Size of metric data array */
1426 LPOUTLINETEXTMETRIC16 lpOTM) /* [out] Address of metric data array */
1428 FIXME("(%04x,%04x,%p): stub\n", hdc,cbData,lpOTM);
1429 return 0;
1433 /***********************************************************************
1434 * GetOutlineTextMetricsA (GDI32.@)
1435 * Gets metrics for TrueType fonts.
1437 * NOTES
1438 * If the supplied buffer isn't big enough Windows partially fills it up to
1439 * its given length and returns that length.
1441 * RETURNS
1442 * Success: Non-zero or size of required buffer
1443 * Failure: 0
1445 UINT WINAPI GetOutlineTextMetricsA(
1446 HDC hdc, /* [in] Handle of device context */
1447 UINT cbData, /* [in] Size of metric data array */
1448 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1450 char buf[512], *ptr;
1451 UINT ret, needed;
1452 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1453 OUTLINETEXTMETRICA *output = lpOTM;
1454 INT left, len;
1456 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1457 return 0;
1458 if(ret > sizeof(buf))
1459 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1460 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1462 needed = sizeof(OUTLINETEXTMETRICA);
1463 if(lpOTMW->otmpFamilyName)
1464 needed += WideCharToMultiByte(CP_ACP, 0,
1465 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1466 NULL, 0, NULL, NULL);
1467 if(lpOTMW->otmpFaceName)
1468 needed += WideCharToMultiByte(CP_ACP, 0,
1469 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1470 NULL, 0, NULL, NULL);
1471 if(lpOTMW->otmpStyleName)
1472 needed += WideCharToMultiByte(CP_ACP, 0,
1473 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1474 NULL, 0, NULL, NULL);
1475 if(lpOTMW->otmpFullName)
1476 needed += WideCharToMultiByte(CP_ACP, 0,
1477 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1478 NULL, 0, NULL, NULL);
1480 if(!lpOTM) {
1481 ret = needed;
1482 goto end;
1485 TRACE("needed = %d\n", needed);
1486 if(needed > cbData)
1487 /* Since the supplied buffer isn't big enough, we'll alloc one
1488 that is and memcpy the first cbData bytes into the lpOTM at
1489 the end. */
1490 output = HeapAlloc(GetProcessHeap(), 0, needed);
1492 ret = output->otmSize = min(needed, cbData);
1493 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1494 output->otmFiller = 0;
1495 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1496 output->otmfsSelection = lpOTMW->otmfsSelection;
1497 output->otmfsType = lpOTMW->otmfsType;
1498 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1499 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1500 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1501 output->otmEMSquare = lpOTMW->otmEMSquare;
1502 output->otmAscent = lpOTMW->otmAscent;
1503 output->otmDescent = lpOTMW->otmDescent;
1504 output->otmLineGap = lpOTMW->otmLineGap;
1505 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1506 output->otmsXHeight = lpOTMW->otmsXHeight;
1507 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1508 output->otmMacAscent = lpOTMW->otmMacAscent;
1509 output->otmMacDescent = lpOTMW->otmMacDescent;
1510 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1511 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1512 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1513 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1514 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1515 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1516 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1517 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1518 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1519 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1522 ptr = (char*)(output + 1);
1523 left = needed - sizeof(*output);
1525 if(lpOTMW->otmpFamilyName) {
1526 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1527 len = WideCharToMultiByte(CP_ACP, 0,
1528 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1529 ptr, left, NULL, NULL);
1530 left -= len;
1531 ptr += len;
1532 } else
1533 output->otmpFamilyName = 0;
1535 if(lpOTMW->otmpFaceName) {
1536 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1537 len = WideCharToMultiByte(CP_ACP, 0,
1538 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1539 ptr, left, NULL, NULL);
1540 left -= len;
1541 ptr += len;
1542 } else
1543 output->otmpFaceName = 0;
1545 if(lpOTMW->otmpStyleName) {
1546 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1547 len = WideCharToMultiByte(CP_ACP, 0,
1548 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1549 ptr, left, NULL, NULL);
1550 left -= len;
1551 ptr += len;
1552 } else
1553 output->otmpStyleName = 0;
1555 if(lpOTMW->otmpFullName) {
1556 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1557 len = WideCharToMultiByte(CP_ACP, 0,
1558 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1559 ptr, left, NULL, NULL);
1560 left -= len;
1561 } else
1562 output->otmpFullName = 0;
1564 assert(left == 0);
1566 if(output != lpOTM) {
1567 memcpy(lpOTM, output, cbData);
1568 HeapFree(GetProcessHeap(), 0, output);
1570 /* check if the string offsets really fit into the provided size */
1571 /* FIXME: should we check string length as well? */
1572 /* make sure that we don't read/write beyond the provided buffer */
1573 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(LPSTR))
1575 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1576 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1579 /* make sure that we don't read/write beyond the provided buffer */
1580 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(LPSTR))
1582 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1583 lpOTM->otmpFaceName = 0; /* doesn't fit */
1586 /* make sure that we don't read/write beyond the provided buffer */
1587 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(LPSTR))
1589 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1590 lpOTM->otmpStyleName = 0; /* doesn't fit */
1593 /* make sure that we don't read/write beyond the provided buffer */
1594 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(LPSTR))
1596 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1597 lpOTM->otmpFullName = 0; /* doesn't fit */
1601 end:
1602 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1603 HeapFree(GetProcessHeap(), 0, lpOTMW);
1605 return ret;
1609 /***********************************************************************
1610 * GetOutlineTextMetricsW [GDI32.@]
1612 UINT WINAPI GetOutlineTextMetricsW(
1613 HDC hdc, /* [in] Handle of device context */
1614 UINT cbData, /* [in] Size of metric data array */
1615 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1617 DC *dc = DC_GetDCPtr( hdc );
1618 OUTLINETEXTMETRICW *output = lpOTM;
1619 UINT ret;
1621 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1622 if(!dc) return 0;
1624 if(dc->gdiFont) {
1625 ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, output);
1626 if(lpOTM && ret) {
1627 if(ret > cbData) {
1628 output = HeapAlloc(GetProcessHeap(), 0, ret);
1629 WineEngGetOutlineTextMetrics(dc->gdiFont, ret, output);
1632 #define WDPTOLP(x) ((x<0)? \
1633 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1634 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1635 #define HDPTOLP(y) ((y<0)? \
1636 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1637 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1639 output->otmTextMetrics.tmHeight = HDPTOLP(output->otmTextMetrics.tmHeight);
1640 output->otmTextMetrics.tmAscent = HDPTOLP(output->otmTextMetrics.tmAscent);
1641 output->otmTextMetrics.tmDescent = HDPTOLP(output->otmTextMetrics.tmDescent);
1642 output->otmTextMetrics.tmInternalLeading = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1643 output->otmTextMetrics.tmExternalLeading = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1644 output->otmTextMetrics.tmAveCharWidth = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1645 output->otmTextMetrics.tmMaxCharWidth = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1646 output->otmTextMetrics.tmOverhang = WDPTOLP(output->otmTextMetrics.tmOverhang);
1647 output->otmAscent = HDPTOLP(output->otmAscent);
1648 output->otmDescent = HDPTOLP(output->otmDescent);
1649 output->otmLineGap = HDPTOLP(output->otmLineGap);
1650 output->otmsCapEmHeight = HDPTOLP(output->otmsCapEmHeight);
1651 output->otmsXHeight = HDPTOLP(output->otmsXHeight);
1652 output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1653 output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1654 output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1655 output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1656 output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1657 output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1658 output->otmMacLineGap = HDPTOLP(output->otmMacLineGap);
1659 output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1660 output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1661 output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1662 output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1663 output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1664 output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1665 output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1666 output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1667 output->otmsStrikeoutSize = HDPTOLP(output->otmsStrikeoutSize);
1668 output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1669 output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1670 output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1671 #undef WDPTOLP
1672 #undef HDPTOLP
1673 if(output != lpOTM) {
1674 memcpy(lpOTM, output, cbData);
1675 HeapFree(GetProcessHeap(), 0, output);
1676 ret = cbData;
1681 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1682 but really this should just be a return 0. */
1684 ret = sizeof(*lpOTM);
1685 if (lpOTM) {
1686 if(cbData < ret)
1687 ret = 0;
1688 else {
1689 memset(lpOTM, 0, ret);
1690 lpOTM->otmSize = sizeof(*lpOTM);
1691 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1693 Further fill of the structure not implemented,
1694 Needs real values for the structure members
1699 GDI_ReleaseObj(hdc);
1700 return ret;
1704 /***********************************************************************
1705 * GetCharWidthW (GDI32.@)
1706 * GetCharWidth32W (GDI32.@)
1708 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1709 LPINT buffer )
1711 UINT i;
1712 BOOL ret = FALSE;
1713 DC * dc = DC_GetDCPtr( hdc );
1714 if (!dc) return FALSE;
1716 if (dc->gdiFont)
1717 ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1718 else if (dc->funcs->pGetCharWidth)
1719 ret = dc->funcs->pGetCharWidth( dc->physDev, firstChar, lastChar, buffer);
1721 if (ret)
1723 /* convert device units to logical */
1724 for( i = firstChar; i <= lastChar; i++, buffer++ )
1725 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1726 ret = TRUE;
1728 GDI_ReleaseObj( hdc );
1729 return ret;
1733 /***********************************************************************
1734 * GetCharWidthA (GDI32.@)
1735 * GetCharWidth32A (GDI32.@)
1737 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1738 LPINT buffer )
1740 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1741 LPSTR str;
1742 LPWSTR wstr;
1743 BOOL ret = TRUE;
1745 if(count <= 0) return FALSE;
1747 str = HeapAlloc(GetProcessHeap(), 0, count);
1748 for(i = 0; i < count; i++)
1749 str[i] = (BYTE)(firstChar + i);
1751 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1753 for(i = 0; i < wlen; i++)
1755 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1757 ret = FALSE;
1758 break;
1760 buffer++;
1763 HeapFree(GetProcessHeap(), 0, str);
1764 HeapFree(GetProcessHeap(), 0, wstr);
1766 return ret;
1770 /***********************************************************************
1771 * ExtTextOutA (GDI32.@)
1773 * See ExtTextOutW.
1775 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1776 const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1778 INT wlen;
1779 UINT codepage;
1780 LPWSTR p;
1781 BOOL ret;
1782 LPINT lpDxW = NULL;
1784 if (flags & ETO_GLYPH_INDEX)
1785 return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
1787 p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
1789 if (lpDx) {
1790 unsigned int i = 0, j = 0;
1792 lpDxW = HeapAlloc( GetProcessHeap(), 0, wlen*sizeof(INT));
1793 while(i < count) {
1794 if(IsDBCSLeadByteEx(codepage, str[i])) {
1795 lpDxW[j++] = lpDx[i] + lpDx[i+1];
1796 i = i + 2;
1797 } else {
1798 lpDxW[j++] = lpDx[i];
1799 i = i + 1;
1804 ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1806 HeapFree( GetProcessHeap(), 0, p );
1807 HeapFree( GetProcessHeap(), 0, lpDxW );
1808 return ret;
1812 /***********************************************************************
1813 * ExtTextOutW (GDI32.@)
1815 * Draws text using the currently selected font, background color, and text color.
1818 * PARAMS
1819 * x,y [I] coordinates of string
1820 * flags [I]
1821 * ETO_GRAYED - undocumented on MSDN
1822 * ETO_OPAQUE - use background color for fill the rectangle
1823 * ETO_CLIPPED - clipping text to the rectangle
1824 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1825 * than encoded characters. Implies ETO_IGNORELANGUAGE
1826 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1827 * Affects BiDi ordering
1828 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1829 * ETO_PDY - unimplemented
1830 * ETO_NUMERICSLATIN - unimplemented always assumed -
1831 * do not translate numbers into locale representations
1832 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1833 * lprect [I] dimensions for clipping or/and opaquing
1834 * str [I] text string
1835 * count [I] number of symbols in string
1836 * lpDx [I] optional parameter with distance between drawing characters
1838 * RETURNS
1839 * Success: TRUE
1840 * Failure: FALSE
1842 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1843 const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1845 BOOL ret = FALSE;
1846 LPWSTR reordered_str = (LPWSTR)str;
1847 WORD *glyphs = NULL;
1848 UINT align = GetTextAlign( hdc );
1849 POINT pt;
1850 TEXTMETRICW tm;
1851 LOGFONTW lf;
1852 double cosEsc, sinEsc;
1853 INT *deltas = NULL, char_extra;
1854 SIZE sz;
1855 RECT rc;
1856 BOOL done_extents = FALSE;
1857 INT width = 0, xwidth = 0, ywidth = 0;
1858 DWORD type;
1859 DC * dc = DC_GetDCUpdate( hdc );
1860 INT breakRem;
1862 if (!dc) return FALSE;
1864 breakRem = dc->breakRem;
1866 if (flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY))
1867 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY unimplemented\n");
1869 if (!dc->funcs->pExtTextOut && !PATH_IsPathOpen(dc->path))
1871 GDI_ReleaseObj( hdc );
1872 return ret;
1875 type = GetObjectType(hdc);
1876 if(type == OBJ_METADC || type == OBJ_ENHMETADC)
1878 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, flags, lprect, str, count, lpDx);
1879 GDI_ReleaseObj( hdc );
1880 return ret;
1883 if (!lprect)
1884 flags &= ~ETO_CLIPPED;
1886 if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && BidiAvail && count > 0 )
1888 reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1890 BIDI_Reorder( str, count, GCP_REORDER,
1891 ((flags&ETO_RTLREADING)!=0 || (GetTextAlign(hdc)&TA_RTLREADING)!=0)?
1892 WINE_GCPW_FORCE_RTL:WINE_GCPW_FORCE_LTR,
1893 reordered_str, count, NULL );
1895 flags |= ETO_IGNORELANGUAGE;
1898 TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc, x, y, flags,
1899 lprect, debugstr_wn(str, count), count, lpDx);
1901 if(flags & ETO_GLYPH_INDEX)
1902 glyphs = reordered_str;
1904 if(lprect)
1905 TRACE("rect: %d,%d - %d,%d\n", lprect->left, lprect->top, lprect->right,
1906 lprect->bottom);
1907 TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
1909 if(align & TA_UPDATECP)
1911 GetCurrentPositionEx( hdc, &pt );
1912 x = pt.x;
1913 y = pt.y;
1916 GetTextMetricsW(hdc, &tm);
1917 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1919 if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
1920 lf.lfEscapement = 0;
1922 if(lf.lfEscapement != 0)
1924 cosEsc = cos(lf.lfEscapement * M_PI / 1800);
1925 sinEsc = sin(lf.lfEscapement * M_PI / 1800);
1927 else
1929 cosEsc = 1;
1930 sinEsc = 0;
1933 if(flags & (ETO_CLIPPED | ETO_OPAQUE))
1935 if(!lprect)
1937 if(flags & ETO_GLYPH_INDEX)
1938 GetTextExtentPointI(hdc, glyphs, count, &sz);
1939 else
1940 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1942 done_extents = TRUE;
1943 rc.left = x;
1944 rc.top = y;
1945 rc.right = x + sz.cx;
1946 rc.bottom = y + sz.cy;
1948 else
1950 rc = *lprect;
1953 LPtoDP(hdc, (POINT*)&rc, 2);
1955 if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
1956 if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
1959 if ((flags & ETO_OPAQUE) && !PATH_IsPathOpen(dc->path))
1960 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1962 if(count == 0)
1964 ret = TRUE;
1965 goto done;
1968 pt.x = x;
1969 pt.y = y;
1970 LPtoDP(hdc, &pt, 1);
1971 x = pt.x;
1972 y = pt.y;
1974 char_extra = GetTextCharacterExtra(hdc);
1975 if(char_extra || dc->breakExtra || breakRem || lpDx)
1977 UINT i;
1978 SIZE tmpsz;
1979 deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT));
1980 for(i = 0; i < count; i++)
1982 if(lpDx && (flags & ETO_PDY))
1983 deltas[i] = lpDx[i*2] + char_extra;
1984 else if(lpDx)
1985 deltas[i] = lpDx[i] + char_extra;
1986 else
1988 if(flags & ETO_GLYPH_INDEX)
1989 GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
1990 else
1991 GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
1993 deltas[i] = tmpsz.cx;
1996 if (!(flags & ETO_GLYPH_INDEX) && (dc->breakExtra || breakRem) && reordered_str[i] == tm.tmBreakChar)
1998 deltas[i] = deltas[i] + dc->breakExtra;
1999 if (breakRem > 0)
2001 breakRem--;
2002 deltas[i]++;
2005 deltas[i] = INTERNAL_XWSTODS(dc, deltas[i]);
2006 width += deltas[i];
2009 else
2011 if(!done_extents)
2013 if(flags & ETO_GLYPH_INDEX)
2014 GetTextExtentPointI(hdc, glyphs, count, &sz);
2015 else
2016 GetTextExtentPointW(hdc, reordered_str, count, &sz);
2017 done_extents = TRUE;
2019 width = INTERNAL_XWSTODS(dc, sz.cx);
2021 xwidth = width * cosEsc;
2022 ywidth = width * sinEsc;
2024 tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
2025 tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
2026 switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
2028 case TA_LEFT:
2029 if (align & TA_UPDATECP)
2031 pt.x = x + xwidth;
2032 pt.y = y - ywidth;
2033 DPtoLP(hdc, &pt, 1);
2034 MoveToEx(hdc, pt.x, pt.y, NULL);
2036 break;
2038 case TA_CENTER:
2039 x -= xwidth / 2;
2040 y += ywidth / 2;
2041 break;
2043 case TA_RIGHT:
2044 x -= xwidth;
2045 y += ywidth;
2046 if (align & TA_UPDATECP)
2048 pt.x = x;
2049 pt.y = y;
2050 DPtoLP(hdc, &pt, 1);
2051 MoveToEx(hdc, pt.x, pt.y, NULL);
2053 break;
2056 switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
2058 case TA_TOP:
2059 y += tm.tmAscent * cosEsc;
2060 x += tm.tmAscent * sinEsc;
2061 break;
2063 case TA_BOTTOM:
2064 y -= tm.tmDescent * cosEsc;
2065 x -= tm.tmDescent * sinEsc;
2066 break;
2068 case TA_BASELINE:
2069 break;
2072 if (GetBkMode(hdc) != TRANSPARENT && !PATH_IsPathOpen(dc->path))
2074 if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
2076 if(!(flags & ETO_OPAQUE) || x < rc.left || x + width >= rc.right ||
2077 y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
2079 RECT rc;
2080 rc.left = x;
2081 rc.right = x + width;
2082 rc.top = y - tm.tmAscent;
2083 rc.bottom = y + tm.tmDescent;
2084 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
2089 if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
2091 HFONT orig_font = dc->hFont, cur_font;
2092 UINT glyph;
2093 INT span = 0, *offsets = NULL, i;
2095 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2096 for(i = 0; i < count; i++)
2098 WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
2099 if(cur_font != dc->hFont)
2101 if(!offsets)
2103 int j;
2104 offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
2105 offsets[0] = 0;
2106 if(!deltas)
2108 SIZE tmpsz;
2109 for(j = 1; j < count; j++)
2111 GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
2112 offsets[j] = offsets[j-1] + INTERNAL_XWSTODS(dc, tmpsz.cx);
2115 else
2117 for(j = 1; j < count; j++)
2118 offsets[j] = offsets[j-1] + deltas[j];
2121 if(span)
2123 if (PATH_IsPathOpen(dc->path))
2124 ret = PATH_ExtTextOut(dc, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
2125 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2126 glyphs, span, deltas ? deltas + i - span : NULL);
2127 else
2128 dc->funcs->pExtTextOut(dc->physDev, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
2129 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2130 glyphs, span, deltas ? deltas + i - span : NULL);
2131 span = 0;
2133 SelectObject(hdc, cur_font);
2135 glyphs[span++] = glyph;
2137 if(i == count - 1)
2139 if (PATH_IsPathOpen(dc->path))
2140 ret = PATH_ExtTextOut(dc, x + (offsets ? offsets[count - span] * cosEsc : 0),
2141 y - (offsets ? offsets[count - span] * sinEsc : 0),
2142 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2143 glyphs, span, deltas ? deltas + count - span : NULL);
2144 else
2145 ret = dc->funcs->pExtTextOut(dc->physDev, x + (offsets ? offsets[count - span] * cosEsc : 0),
2146 y - (offsets ? offsets[count - span] * sinEsc : 0),
2147 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2148 glyphs, span, deltas ? deltas + count - span : NULL);
2149 SelectObject(hdc, orig_font);
2150 HeapFree(GetProcessHeap(), 0, offsets);
2154 else
2156 if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
2158 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2159 GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
2160 flags |= ETO_GLYPH_INDEX;
2163 if (PATH_IsPathOpen(dc->path))
2164 ret = PATH_ExtTextOut(dc, x, y, (flags & ~ETO_OPAQUE), &rc,
2165 glyphs ? glyphs : reordered_str, count, deltas);
2166 else
2167 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, (flags & ~ETO_OPAQUE), &rc,
2168 glyphs ? glyphs : reordered_str, count, deltas);
2171 done:
2172 HeapFree(GetProcessHeap(), 0, deltas);
2173 if(glyphs != reordered_str)
2174 HeapFree(GetProcessHeap(), 0, glyphs);
2175 if(reordered_str != str)
2176 HeapFree(GetProcessHeap(), 0, reordered_str);
2178 GDI_ReleaseObj( hdc );
2180 if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2182 int underlinePos, strikeoutPos;
2183 int underlineWidth, strikeoutWidth;
2184 UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2185 OUTLINETEXTMETRICW* otm = NULL;
2187 if(!size)
2189 underlinePos = 0;
2190 underlineWidth = tm.tmAscent / 20 + 1;
2191 strikeoutPos = tm.tmAscent / 2;
2192 strikeoutWidth = underlineWidth;
2194 else
2196 otm = HeapAlloc(GetProcessHeap(), 0, size);
2197 GetOutlineTextMetricsW(hdc, size, otm);
2198 underlinePos = otm->otmsUnderscorePosition;
2199 underlineWidth = otm->otmsUnderscoreSize;
2200 strikeoutPos = otm->otmsStrikeoutPosition;
2201 strikeoutWidth = otm->otmsStrikeoutSize;
2202 HeapFree(GetProcessHeap(), 0, otm);
2205 if (PATH_IsPathOpen(dc->path))
2207 POINT pts[5];
2208 HPEN hpen;
2209 HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2211 hbrush = SelectObject(hdc, hbrush);
2212 hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2214 if (lf.lfUnderline)
2216 pts[0].x = x - underlinePos * sinEsc;
2217 pts[0].y = y - underlinePos * cosEsc;
2218 pts[1].x = x + xwidth - underlinePos * sinEsc;
2219 pts[1].y = y - ywidth - underlinePos * cosEsc;
2220 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2221 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2222 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2223 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2224 pts[4].x = pts[0].x;
2225 pts[4].y = pts[0].y;
2226 DPtoLP(hdc, pts, 5);
2227 Polygon(hdc, pts, 5);
2230 if (lf.lfStrikeOut)
2232 pts[0].x = x - strikeoutPos * sinEsc;
2233 pts[0].y = y - strikeoutPos * cosEsc;
2234 pts[1].x = x + xwidth - strikeoutPos * sinEsc;
2235 pts[1].y = y - ywidth - strikeoutPos * cosEsc;
2236 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2237 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2238 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2239 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2240 pts[4].x = pts[0].x;
2241 pts[4].y = pts[0].y;
2242 DPtoLP(hdc, pts, 5);
2243 Polygon(hdc, pts, 5);
2246 SelectObject(hdc, hpen);
2247 hbrush = SelectObject(hdc, hbrush);
2248 DeleteObject(hbrush);
2250 else
2252 POINT pts[2], oldpt;
2253 HPEN hpen;
2255 if (lf.lfUnderline)
2257 hpen = CreatePen(PS_SOLID, underlineWidth, GetTextColor(hdc));
2258 hpen = SelectObject(hdc, hpen);
2259 pts[0].x = x;
2260 pts[0].y = y;
2261 pts[1].x = x + xwidth;
2262 pts[1].y = y - ywidth;
2263 DPtoLP(hdc, pts, 2);
2264 MoveToEx(hdc, pts[0].x - underlinePos * sinEsc, pts[0].y - underlinePos * cosEsc, &oldpt);
2265 LineTo(hdc, pts[1].x - underlinePos * sinEsc, pts[1].y - underlinePos * cosEsc);
2266 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2267 DeleteObject(SelectObject(hdc, hpen));
2270 if (lf.lfStrikeOut)
2272 hpen = CreatePen(PS_SOLID, strikeoutWidth, GetTextColor(hdc));
2273 hpen = SelectObject(hdc, hpen);
2274 pts[0].x = x;
2275 pts[0].y = y;
2276 pts[1].x = x + xwidth;
2277 pts[1].y = y - ywidth;
2278 DPtoLP(hdc, pts, 2);
2279 MoveToEx(hdc, pts[0].x - strikeoutPos * sinEsc, pts[0].y - strikeoutPos * cosEsc, &oldpt);
2280 LineTo(hdc, pts[1].x - strikeoutPos * sinEsc, pts[1].y - strikeoutPos * cosEsc);
2281 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2282 DeleteObject(SelectObject(hdc, hpen));
2287 return ret;
2291 /***********************************************************************
2292 * TextOutA (GDI32.@)
2294 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2296 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2300 /***********************************************************************
2301 * TextOutW (GDI32.@)
2303 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2305 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2309 /***********************************************************************
2310 * PolyTextOutA (GDI32.@)
2312 * See PolyTextOutW.
2314 BOOL WINAPI PolyTextOutA ( HDC hdc, /* [in] Handle to device context */
2315 PPOLYTEXTA pptxt, /* [in] Array of strings */
2316 INT cStrings ) /* [in] Number of strings in array */
2318 for (; cStrings>0; cStrings--, pptxt++)
2319 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2320 return FALSE;
2321 return TRUE;
2326 /***********************************************************************
2327 * PolyTextOutW (GDI32.@)
2329 * Draw several Strings
2331 * RETURNS
2332 * TRUE: Success.
2333 * FALSE: Failure.
2335 BOOL WINAPI PolyTextOutW ( HDC hdc, /* [in] Handle to device context */
2336 PPOLYTEXTW pptxt, /* [in] Array of strings */
2337 INT cStrings ) /* [in] Number of strings in array */
2339 for (; cStrings>0; cStrings--, pptxt++)
2340 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2341 return FALSE;
2342 return TRUE;
2346 /* FIXME: all following APIs ******************************************/
2349 /***********************************************************************
2350 * SetMapperFlags (GDI32.@)
2352 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
2354 DC *dc = DC_GetDCPtr( hDC );
2355 DWORD ret = 0;
2356 if(!dc) return 0;
2357 if(dc->funcs->pSetMapperFlags)
2359 ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
2360 /* FIXME: ret is just a success flag, we should return a proper value */
2362 else
2363 FIXME("(%p, 0x%08x): stub - harmless\n", hDC, dwFlag);
2364 GDI_ReleaseObj( hDC );
2365 return ret;
2368 /***********************************************************************
2369 * GetAspectRatioFilterEx (GDI.486)
2371 BOOL16 WINAPI GetAspectRatioFilterEx16( HDC16 hdc, LPSIZE16 pAspectRatio )
2373 FIXME("(%04x, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2374 return FALSE;
2377 /***********************************************************************
2378 * GetAspectRatioFilterEx (GDI32.@)
2380 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2382 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2383 return FALSE;
2387 /***********************************************************************
2388 * GetCharABCWidthsA (GDI32.@)
2390 * See GetCharABCWidthsW.
2392 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2393 LPABC abc )
2395 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
2396 LPSTR str;
2397 LPWSTR wstr;
2398 BOOL ret = TRUE;
2400 if(count <= 0) return FALSE;
2402 str = HeapAlloc(GetProcessHeap(), 0, count);
2403 for(i = 0; i < count; i++)
2404 str[i] = (BYTE)(firstChar + i);
2406 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
2408 for(i = 0; i < wlen; i++)
2410 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2412 ret = FALSE;
2413 break;
2415 abc++;
2418 HeapFree(GetProcessHeap(), 0, str);
2419 HeapFree(GetProcessHeap(), 0, wstr);
2421 return ret;
2425 /******************************************************************************
2426 * GetCharABCWidthsW [GDI32.@]
2428 * Retrieves widths of characters in range.
2430 * PARAMS
2431 * hdc [I] Handle of device context
2432 * firstChar [I] First character in range to query
2433 * lastChar [I] Last character in range to query
2434 * abc [O] Address of character-width structure
2436 * NOTES
2437 * Only works with TrueType fonts
2439 * RETURNS
2440 * Success: TRUE
2441 * Failure: FALSE
2443 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2444 LPABC abc )
2446 DC *dc = DC_GetDCPtr(hdc);
2447 unsigned int i;
2448 BOOL ret = FALSE;
2450 if (!dc) return FALSE;
2452 if(dc->gdiFont)
2453 ret = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
2454 else
2455 FIXME(": stub\n");
2457 if (ret)
2459 /* convert device units to logical */
2460 for( i = firstChar; i <= lastChar; i++, abc++ ) {
2461 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2462 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2463 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2465 ret = TRUE;
2468 GDI_ReleaseObj(hdc);
2469 return ret;
2473 /******************************************************************************
2474 * GetCharABCWidthsI [GDI32.@]
2476 * Retrieves widths of characters in range.
2478 * PARAMS
2479 * hdc [I] Handle of device context
2480 * firstChar [I] First glyphs in range to query
2481 * count [I] Last glyphs in range to query
2482 * pgi [i] Array of glyphs to query
2483 * abc [O] Address of character-width structure
2485 * NOTES
2486 * Only works with TrueType fonts
2488 * RETURNS
2489 * Success: TRUE
2490 * Failure: FALSE
2492 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2493 LPWORD pgi, LPABC abc)
2495 DC *dc = DC_GetDCPtr(hdc);
2496 unsigned int i;
2497 BOOL ret = FALSE;
2499 if (!dc) return FALSE;
2501 if(dc->gdiFont)
2502 ret = WineEngGetCharABCWidthsI( dc->gdiFont, firstChar, count, pgi, abc );
2503 else
2504 FIXME(": stub\n");
2506 if (ret)
2508 /* convert device units to logical */
2509 for( i = 0; i < count; i++, abc++ ) {
2510 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2511 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2512 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2514 ret = TRUE;
2517 GDI_ReleaseObj(hdc);
2518 return ret;
2522 /***********************************************************************
2523 * GetGlyphOutlineA (GDI32.@)
2525 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2526 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2527 LPVOID lpBuffer, const MAT2 *lpmat2 )
2529 LPWSTR p = NULL;
2530 DWORD ret;
2531 UINT c;
2533 if(!(fuFormat & GGO_GLYPH_INDEX)) {
2534 int len;
2535 char mbchs[2];
2536 if(uChar > 0xff) { /* but, 2 bytes character only */
2537 len = 2;
2538 mbchs[0] = (uChar & 0xff00) >> 8;
2539 mbchs[1] = (uChar & 0xff);
2540 } else {
2541 len = 1;
2542 mbchs[0] = (uChar & 0xff);
2544 p = FONT_mbtowc(hdc, mbchs, len, NULL, NULL);
2545 c = p[0];
2546 } else
2547 c = uChar;
2548 ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
2549 lpmat2);
2550 HeapFree(GetProcessHeap(), 0, p);
2551 return ret;
2554 /***********************************************************************
2555 * GetGlyphOutlineW (GDI32.@)
2557 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2558 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2559 LPVOID lpBuffer, const MAT2 *lpmat2 )
2561 DC *dc = DC_GetDCPtr(hdc);
2562 DWORD ret;
2564 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2565 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2567 if(!dc) return GDI_ERROR;
2569 if(dc->gdiFont)
2570 ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
2571 cbBuffer, lpBuffer, lpmat2);
2572 else
2573 ret = GDI_ERROR;
2575 GDI_ReleaseObj(hdc);
2576 return ret;
2580 /***********************************************************************
2581 * CreateScalableFontResourceA (GDI32.@)
2583 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2584 LPCSTR lpszResourceFile,
2585 LPCSTR lpszFontFile,
2586 LPCSTR lpszCurrentPath )
2588 HANDLE f;
2590 /* fHidden=1 - only visible for the calling app, read-only, not
2591 * enumbered with EnumFonts/EnumFontFamilies
2592 * lpszCurrentPath can be NULL
2594 FIXME("(%d,%s,%s,%s): stub\n",
2595 fHidden, debugstr_a(lpszResourceFile), debugstr_a(lpszFontFile),
2596 debugstr_a(lpszCurrentPath) );
2598 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2599 if ((f = CreateFileA(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2600 CloseHandle(f);
2601 SetLastError(ERROR_FILE_EXISTS);
2602 return FALSE;
2604 return FALSE; /* create failed */
2607 /***********************************************************************
2608 * CreateScalableFontResourceW (GDI32.@)
2610 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2611 LPCWSTR lpszResourceFile,
2612 LPCWSTR lpszFontFile,
2613 LPCWSTR lpszCurrentPath )
2615 FIXME("(%d,%p,%p,%p): stub\n",
2616 fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
2617 return FALSE; /* create failed */
2620 /*************************************************************************
2621 * GetKerningPairsA (GDI32.@)
2623 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2624 LPKERNINGPAIR kern_pairA )
2626 INT charset;
2627 CHARSETINFO csi;
2628 CPINFO cpi;
2629 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2630 KERNINGPAIR *kern_pairW;
2632 if (!cPairs && kern_pairA)
2634 SetLastError(ERROR_INVALID_PARAMETER);
2635 return 0;
2638 charset = GetTextCharset(hDC);
2639 if (!TranslateCharsetInfo((DWORD *)charset, &csi, TCI_SRCCHARSET))
2641 FIXME("Can't find codepage for charset %d\n", charset);
2642 return 0;
2644 if (!GetCPInfo(csi.ciACP, &cpi))
2646 FIXME("Can't find codepage %u info\n", csi.ciACP);
2647 return 0;
2649 TRACE("charset %d => codepage %u\n", charset, csi.ciACP);
2651 total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2652 if (!total_kern_pairs) return 0;
2654 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2655 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2657 for (i = 0; i < total_kern_pairs; i++)
2659 char first, second;
2661 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2662 continue;
2664 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2665 continue;
2667 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2668 continue;
2670 if (kern_pairA)
2672 if (kern_pairs_copied >= cPairs) break;
2674 kern_pairA->wFirst = (BYTE)first;
2675 kern_pairA->wSecond = (BYTE)second;
2676 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2677 kern_pairA++;
2679 kern_pairs_copied++;
2682 HeapFree(GetProcessHeap(), 0, kern_pairW);
2684 return kern_pairs_copied;
2687 /*************************************************************************
2688 * GetKerningPairsW (GDI32.@)
2690 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2691 LPKERNINGPAIR lpKerningPairs )
2693 DC *dc;
2694 DWORD ret = 0;
2696 TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2698 if (!cPairs && lpKerningPairs)
2700 SetLastError(ERROR_INVALID_PARAMETER);
2701 return 0;
2704 dc = DC_GetDCPtr(hDC);
2705 if (!dc) return 0;
2707 if (dc->gdiFont)
2708 ret = WineEngGetKerningPairs(dc->gdiFont, cPairs, lpKerningPairs);
2710 GDI_ReleaseObj(hDC);
2711 return ret;
2714 /*************************************************************************
2715 * TranslateCharsetInfo [GDI32.@]
2717 * Fills a CHARSETINFO structure for a character set, code page, or
2718 * font. This allows making the correspondance between different labelings
2719 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2720 * of the same encoding.
2722 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2723 * only one codepage should be set in *lpSrc.
2725 * RETURNS
2726 * TRUE on success, FALSE on failure.
2729 BOOL WINAPI TranslateCharsetInfo(
2730 LPDWORD lpSrc, /* [in]
2731 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2732 if flags == TCI_SRCCHARSET: a character set value
2733 if flags == TCI_SRCCODEPAGE: a code page value
2735 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2736 DWORD flags /* [in] determines interpretation of lpSrc */)
2738 int index = 0;
2739 switch (flags) {
2740 case TCI_SRCFONTSIG:
2741 while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
2742 break;
2743 case TCI_SRCCODEPAGE:
2744 while ((UINT) (lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
2745 break;
2746 case TCI_SRCCHARSET:
2747 while ((UINT) (lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
2748 break;
2749 default:
2750 return FALSE;
2752 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2753 memcpy(lpCs, &FONT_tci[index], sizeof(CHARSETINFO));
2754 return TRUE;
2757 /*************************************************************************
2758 * GetFontLanguageInfo (GDI32.@)
2760 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2762 FONTSIGNATURE fontsig;
2763 static const DWORD GCP_DBCS_MASK=0x003F0000,
2764 GCP_DIACRITIC_MASK=0x00000000,
2765 FLI_GLYPHS_MASK=0x00000000,
2766 GCP_GLYPHSHAPE_MASK=0x00000040,
2767 GCP_KASHIDA_MASK=0x00000000,
2768 GCP_LIGATE_MASK=0x00000000,
2769 GCP_USEKERNING_MASK=0x00000000,
2770 GCP_REORDER_MASK=0x00000060;
2772 DWORD result=0;
2774 GetTextCharsetInfo( hdc, &fontsig, 0 );
2775 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2777 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2778 result|=GCP_DBCS;
2780 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2781 result|=GCP_DIACRITIC;
2783 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2784 result|=FLI_GLYPHS;
2786 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2787 result|=GCP_GLYPHSHAPE;
2789 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2790 result|=GCP_KASHIDA;
2792 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2793 result|=GCP_LIGATE;
2795 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2796 result|=GCP_USEKERNING;
2798 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2799 if( GetTextAlign( hdc) & TA_RTLREADING )
2800 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2801 result|=GCP_REORDER;
2803 return result;
2807 /*************************************************************************
2808 * GetFontData [GDI32.@]
2810 * Retrieve data for TrueType font.
2812 * RETURNS
2814 * success: Number of bytes returned
2815 * failure: GDI_ERROR
2817 * NOTES
2819 * Calls SetLastError()
2822 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2823 LPVOID buffer, DWORD length)
2825 DC *dc = DC_GetDCPtr(hdc);
2826 DWORD ret = GDI_ERROR;
2828 if(!dc) return GDI_ERROR;
2830 if(dc->gdiFont)
2831 ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2833 GDI_ReleaseObj(hdc);
2834 return ret;
2837 /*************************************************************************
2838 * GetGlyphIndicesA [GDI32.@]
2840 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2841 LPWORD pgi, DWORD flags)
2843 DWORD ret;
2844 WCHAR *lpstrW;
2845 INT countW;
2847 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2848 hdc, debugstr_an(lpstr, count), count, pgi, flags);
2850 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2851 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2852 HeapFree(GetProcessHeap(), 0, lpstrW);
2854 return ret;
2857 /*************************************************************************
2858 * GetGlyphIndicesW [GDI32.@]
2860 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2861 LPWORD pgi, DWORD flags)
2863 DC *dc = DC_GetDCPtr(hdc);
2864 DWORD ret = GDI_ERROR;
2866 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2867 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2869 if(!dc) return GDI_ERROR;
2871 if(dc->gdiFont)
2872 ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2874 GDI_ReleaseObj(hdc);
2875 return ret;
2878 /*************************************************************************
2879 * GetCharacterPlacementA [GDI32.@]
2881 * See GetCharacterPlacementW.
2883 * NOTES:
2884 * the web browser control of ie4 calls this with dwFlags=0
2886 DWORD WINAPI
2887 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2888 INT nMaxExtent, GCP_RESULTSA *lpResults,
2889 DWORD dwFlags)
2891 WCHAR *lpStringW;
2892 INT uCountW;
2893 GCP_RESULTSW resultsW;
2894 DWORD ret;
2895 UINT font_cp;
2897 TRACE("%s, %d, %d, 0x%08x\n",
2898 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2900 /* both structs are equal in size */
2901 memcpy(&resultsW, lpResults, sizeof(resultsW));
2903 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2904 if(lpResults->lpOutString)
2905 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2907 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2909 lpResults->nGlyphs = resultsW.nGlyphs;
2910 lpResults->nMaxFit = resultsW.nMaxFit;
2912 if(lpResults->lpOutString) {
2913 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2914 lpResults->lpOutString, uCount, NULL, NULL );
2917 HeapFree(GetProcessHeap(), 0, lpStringW);
2918 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2920 return ret;
2923 /*************************************************************************
2924 * GetCharacterPlacementW [GDI32.@]
2926 * Retrieve information about a string. This includes the width, reordering,
2927 * Glyphing and so on.
2929 * RETURNS
2931 * The width and height of the string if successful, 0 if failed.
2933 * BUGS
2935 * All flags except GCP_REORDER are not yet implemented.
2936 * Reordering is not 100% complient to the Windows BiDi method.
2937 * Caret positioning is not yet implemented for BiDi.
2938 * Classes are not yet implemented.
2941 DWORD WINAPI
2942 GetCharacterPlacementW(
2943 HDC hdc, /* [in] Device context for which the rendering is to be done */
2944 LPCWSTR lpString, /* [in] The string for which information is to be returned */
2945 INT uCount, /* [in] Number of WORDS in string. */
2946 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
2947 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2948 DWORD dwFlags /* [in] Flags specifying how to process the string */
2951 DWORD ret=0;
2952 SIZE size;
2953 UINT i, nSet;
2955 TRACE("%s, %d, %d, 0x%08x\n",
2956 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2958 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2959 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2960 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2961 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2962 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2964 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08x ignored\n", dwFlags);
2965 if(lpResults->lpClass) FIXME("classes not implemented\n");
2966 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2967 FIXME("Caret positions for complex scripts not implemented\n");
2969 nSet = (UINT)uCount;
2970 if(nSet > lpResults->nGlyphs)
2971 nSet = lpResults->nGlyphs;
2973 /* return number of initialized fields */
2974 lpResults->nGlyphs = nSet;
2976 if((dwFlags&GCP_REORDER)==0 || !BidiAvail)
2978 /* Treat the case where no special handling was requested in a fastpath way */
2979 /* copy will do if the GCP_REORDER flag is not set */
2980 if(lpResults->lpOutString)
2981 memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
2983 if(lpResults->lpOrder)
2985 for(i = 0; i < nSet; i++)
2986 lpResults->lpOrder[i] = i;
2988 } else
2990 BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
2991 nSet, lpResults->lpOrder );
2994 /* FIXME: Will use the placement chars */
2995 if (lpResults->lpDx)
2997 int c;
2998 for (i = 0; i < nSet; i++)
3000 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
3001 lpResults->lpDx[i]= c;
3005 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
3007 int pos = 0;
3009 lpResults->lpCaretPos[0] = 0;
3010 for (i = 1; i < nSet; i++)
3011 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
3012 lpResults->lpCaretPos[i] = (pos += size.cx);
3015 if(lpResults->lpGlyphs)
3016 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
3018 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
3019 ret = MAKELONG(size.cx, size.cy);
3021 return ret;
3024 /*************************************************************************
3025 * GetCharABCWidthsFloatA [GDI32.@]
3027 * See GetCharABCWidthsFloatW.
3029 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3031 INT i, wlen, count = (INT)(last - first + 1);
3032 LPSTR str;
3033 LPWSTR wstr;
3034 BOOL ret = TRUE;
3036 if (count <= 0) return FALSE;
3038 str = HeapAlloc(GetProcessHeap(), 0, count);
3040 for(i = 0; i < count; i++)
3041 str[i] = (BYTE)(first + i);
3043 wstr = FONT_mbtowc( hdc, str, count, &wlen, NULL );
3045 for (i = 0; i < wlen; i++)
3047 if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
3049 ret = FALSE;
3050 break;
3052 abcf++;
3055 HeapFree( GetProcessHeap(), 0, str );
3056 HeapFree( GetProcessHeap(), 0, wstr );
3058 return ret;
3061 /*************************************************************************
3062 * GetCharABCWidthsFloatW [GDI32.@]
3064 * Retrieves widths of a range of characters.
3066 * PARAMS
3067 * hdc [I] Handle to device context.
3068 * first [I] First character in range to query.
3069 * last [I] Last character in range to query.
3070 * abcf [O] Array of LPABCFLOAT structures.
3072 * RETURNS
3073 * Success: TRUE
3074 * Failure: FALSE
3076 * BUGS
3077 * Only works with TrueType fonts. It also doesn't return real
3078 * floats but converted integers because it's implemented on
3079 * top of GetCharABCWidthsW.
3081 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3083 ABC *abc;
3084 unsigned int i, size = sizeof(ABC) * (last - first + 1);
3085 BOOL ret;
3087 TRACE("%p, %d, %d, %p - partial stub\n", hdc, first, last, abcf);
3089 abc = HeapAlloc( GetProcessHeap(), 0, size );
3090 if (!abc) return FALSE;
3092 ret = GetCharABCWidthsW( hdc, first, last, abc );
3093 if (ret)
3095 for (i = first; i <= last; i++, abc++, abcf++)
3097 abcf->abcfA = abc->abcA;
3098 abcf->abcfB = abc->abcB;
3099 abcf->abcfC = abc->abcC;
3102 HeapFree( GetProcessHeap(), 0, abc );
3103 return ret;
3106 /*************************************************************************
3107 * GetCharWidthFloatA [GDI32.@]
3109 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
3110 UINT iLastChar, PFLOAT pxBuffer)
3112 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3113 return 0;
3116 /*************************************************************************
3117 * GetCharWidthFloatW [GDI32.@]
3119 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
3120 UINT iLastChar, PFLOAT pxBuffer)
3122 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3123 return 0;
3127 /***********************************************************************
3129 * Font Resource API *
3131 ***********************************************************************/
3133 /***********************************************************************
3134 * AddFontResourceA (GDI32.@)
3136 INT WINAPI AddFontResourceA( LPCSTR str )
3138 return AddFontResourceExA( str, 0, NULL);
3141 /***********************************************************************
3142 * AddFontResourceW (GDI32.@)
3144 INT WINAPI AddFontResourceW( LPCWSTR str )
3146 return AddFontResourceExW(str, 0, NULL);
3150 /***********************************************************************
3151 * AddFontResourceExA (GDI32.@)
3153 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3155 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3156 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3157 INT ret;
3159 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3160 ret = AddFontResourceExW(strW, fl, pdv);
3161 HeapFree(GetProcessHeap(), 0, strW);
3162 return ret;
3165 /***********************************************************************
3166 * AddFontResourceExW (GDI32.@)
3168 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3170 return WineEngAddFontResourceEx(str, fl, pdv);
3173 /***********************************************************************
3174 * RemoveFontResourceA (GDI32.@)
3176 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3178 return RemoveFontResourceExA(str, 0, 0);
3181 /***********************************************************************
3182 * RemoveFontResourceW (GDI32.@)
3184 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3186 return RemoveFontResourceExW(str, 0, 0);
3189 /***********************************************************************
3190 * AddFontMemResourceEx (GDI32.@)
3192 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3194 FIXME("(%p,%08x,%p,%p): stub\n", pbFont, cbFont, pdv, pcFonts);
3195 return NULL;
3198 /***********************************************************************
3199 * RemoveFontResourceExA (GDI32.@)
3201 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3203 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3204 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3205 INT ret;
3207 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3208 ret = RemoveFontResourceExW(strW, fl, pdv);
3209 HeapFree(GetProcessHeap(), 0, strW);
3210 return ret;
3213 /***********************************************************************
3214 * RemoveFontResourceExW (GDI32.@)
3216 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3218 return WineEngRemoveFontResourceEx(str, fl, pdv);
3221 /***********************************************************************
3222 * GetTextCharset (GDI32.@)
3224 UINT WINAPI GetTextCharset(HDC hdc)
3226 /* MSDN docs say this is equivalent */
3227 return GetTextCharsetInfo(hdc, NULL, 0);
3230 /***********************************************************************
3231 * GetTextCharsetInfo (GDI32.@)
3233 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3235 UINT ret = DEFAULT_CHARSET;
3236 DC *dc = DC_GetDCPtr(hdc);
3238 if (dc)
3240 if (dc->gdiFont)
3241 ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
3243 GDI_ReleaseObj(hdc);
3246 if (ret == DEFAULT_CHARSET && fs)
3247 memset(fs, 0, sizeof(FONTSIGNATURE));
3248 return ret;
3251 /***********************************************************************
3252 * GdiGetCharDimensions (GDI32.@)
3254 * Gets the average width of the characters in the English alphabet.
3256 * PARAMS
3257 * hdc [I] Handle to the device context to measure on.
3258 * lptm [O] Pointer to memory to store the text metrics into.
3259 * height [O] On exit, the maximum height of characters in the English alphabet.
3261 * RETURNS
3262 * The average width of characters in the English alphabet.
3264 * NOTES
3265 * This function is used by the dialog manager to get the size of a dialog
3266 * unit. It should also be used by other pieces of code that need to know
3267 * the size of a dialog unit in logical units without having access to the
3268 * window handle of the dialog.
3269 * Windows caches the font metrics from this function, but we don't and
3270 * there doesn't appear to be an immediate advantage to do so.
3272 * SEE ALSO
3273 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3275 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3277 SIZE sz;
3278 static const WCHAR alphabet[] = {
3279 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3280 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3281 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3283 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3285 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3287 if (height) *height = sz.cy;
3288 return (sz.cx / 26 + 1) / 2;
3291 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3293 FIXME("(%d): stub\n", fEnableEUDC);
3294 return FALSE;
3297 /***********************************************************************
3298 * GetCharWidthI (GDI32.@)
3300 * Retrieve widths of characters.
3302 * PARAMS
3303 * hdc [I] Handle to a device context.
3304 * first [I] First glyph in range to query.
3305 * count [I] Number of glyph indices to query.
3306 * glyphs [I] Array of glyphs to query.
3307 * buffer [O] Buffer to receive character widths.
3309 * NOTES
3310 * Only works with TrueType fonts.
3312 * RETURNS
3313 * Success: TRUE
3314 * Failure: FALSE
3316 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3318 ABC *abc;
3319 unsigned int i;
3321 TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3323 if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3324 return FALSE;
3326 if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3328 HeapFree(GetProcessHeap(), 0, abc);
3329 return FALSE;
3332 for (i = 0; i < count; i++)
3333 buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3335 HeapFree(GetProcessHeap(), 0, abc);
3336 return TRUE;
3339 /***********************************************************************
3340 * GetFontUnicodeRanges (GDI32.@)
3342 * Retrieve a list of supported Unicode characters in a font.
3344 * PARAMS
3345 * hdc [I] Handle to a device context.
3346 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3348 * RETURNS
3349 * Success: Number of bytes written to the buffer pointed to by lpgs.
3350 * Failure: 0
3353 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3355 return WineEngGetFontUnicodeRanges(hdc, lpgs);