Changes in crossover-wine-src-6.1.0 except for configure
[wine/hacks.git] / dlls / gdi32 / font.c
blob120dca3642dd276b3ce598fbecd05febf5e5d63d
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 = min(ptmW->tmFirstChar, 255);
291 if (ptmW->tmCharSet == SYMBOL_CHARSET)
293 UINT last_char = ptmW->tmLastChar;
294 if (last_char > 0xf000) last_char -= 0xf000;
295 ptmA->tmLastChar = min(last_char, 255);
297 else
298 ptmA->tmLastChar = min(ptmW->tmLastChar, 255);
299 ptmA->tmDefaultChar = min(ptmW->tmDefaultChar, 255);
300 ptmA->tmBreakChar = min(ptmW->tmBreakChar, 255);
301 ptmA->tmItalic = ptmW->tmItalic;
302 ptmA->tmUnderlined = ptmW->tmUnderlined;
303 ptmA->tmStruckOut = ptmW->tmStruckOut;
304 ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
305 ptmA->tmCharSet = ptmW->tmCharSet;
309 static void FONT_NewTextMetricExWTo16(const NEWTEXTMETRICEXW *ptmW, LPNEWTEXTMETRICEX16 ptm16 )
311 ptm16->ntmTm.tmHeight = ptmW->ntmTm.tmHeight;
312 ptm16->ntmTm.tmAscent = ptmW->ntmTm.tmAscent;
313 ptm16->ntmTm.tmDescent = ptmW->ntmTm.tmDescent;
314 ptm16->ntmTm.tmInternalLeading = ptmW->ntmTm.tmInternalLeading;
315 ptm16->ntmTm.tmExternalLeading = ptmW->ntmTm.tmExternalLeading;
316 ptm16->ntmTm.tmAveCharWidth = ptmW->ntmTm.tmAveCharWidth;
317 ptm16->ntmTm.tmMaxCharWidth = ptmW->ntmTm.tmMaxCharWidth;
318 ptm16->ntmTm.tmWeight = ptmW->ntmTm.tmWeight;
319 ptm16->ntmTm.tmOverhang = ptmW->ntmTm.tmOverhang;
320 ptm16->ntmTm.tmDigitizedAspectX = ptmW->ntmTm.tmDigitizedAspectX;
321 ptm16->ntmTm.tmDigitizedAspectY = ptmW->ntmTm.tmDigitizedAspectY;
322 ptm16->ntmTm.tmFirstChar = ptmW->ntmTm.tmFirstChar > 255 ? 255 : ptmW->ntmTm.tmFirstChar;
323 ptm16->ntmTm.tmLastChar = ptmW->ntmTm.tmLastChar > 255 ? 255 : ptmW->ntmTm.tmLastChar;
324 ptm16->ntmTm.tmDefaultChar = ptmW->ntmTm.tmDefaultChar > 255 ? 255 : ptmW->ntmTm.tmDefaultChar;
325 ptm16->ntmTm.tmBreakChar = ptmW->ntmTm.tmBreakChar > 255 ? 255 : ptmW->ntmTm.tmBreakChar;
326 ptm16->ntmTm.tmItalic = ptmW->ntmTm.tmItalic;
327 ptm16->ntmTm.tmUnderlined = ptmW->ntmTm.tmUnderlined;
328 ptm16->ntmTm.tmStruckOut = ptmW->ntmTm.tmStruckOut;
329 ptm16->ntmTm.tmPitchAndFamily = ptmW->ntmTm.tmPitchAndFamily;
330 ptm16->ntmTm.tmCharSet = ptmW->ntmTm.tmCharSet;
331 ptm16->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
332 ptm16->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
333 ptm16->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
334 ptm16->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
335 memcpy(&ptm16->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
338 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW *ptmW, NEWTEXTMETRICEXA *ptmA )
340 FONT_TextMetricWToA((const TEXTMETRICW *)ptmW, (LPTEXTMETRICA)ptmA);
341 ptmA->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
342 ptmA->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
343 ptmA->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
344 ptmA->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
345 memcpy(&ptmA->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
349 /***********************************************************************
350 * GdiGetCodePage (GDI32.@)
352 DWORD WINAPI GdiGetCodePage( HDC hdc )
354 UINT cp = CP_ACP;
355 CHARSETINFO csi;
356 int charset = GetTextCharset(hdc);
358 /* Hmm, nicely designed api this one! */
359 if(TranslateCharsetInfo((DWORD*)charset, &csi, TCI_SRCCHARSET))
360 cp = csi.ciACP;
361 else {
362 switch(charset) {
363 case OEM_CHARSET:
364 cp = GetOEMCP();
365 break;
366 case DEFAULT_CHARSET:
367 cp = GetACP();
368 break;
370 case VISCII_CHARSET:
371 case TCVN_CHARSET:
372 case KOI8_CHARSET:
373 case ISO3_CHARSET:
374 case ISO4_CHARSET:
375 case ISO10_CHARSET:
376 case CELTIC_CHARSET:
377 /* FIXME: These have no place here, but because x11drv
378 enumerates fonts with these (made up) charsets some apps
379 might use them and then the FIXME below would become
380 annoying. Now we could pick the intended codepage for
381 each of these, but since it's broken anyway we'll just
382 use CP_ACP and hope it'll go away...
384 cp = CP_ACP;
385 break;
387 default:
388 FIXME("Can't find codepage for charset %d\n", charset);
389 break;
393 TRACE("charset %d => cp %d\n", charset, cp);
394 return cp;
397 /***********************************************************************
398 * FONT_mbtowc
400 * Returns a Unicode translation of str using the charset of the
401 * currently selected font in hdc. If count is -1 then str is assumed
402 * to be '\0' terminated, otherwise it contains the number of bytes to
403 * convert. If plenW is non-NULL, on return it will point to the
404 * number of WCHARs that have been written. If pCP is non-NULL, on
405 * return it will point to the codepage used in the conversion. The
406 * caller should free the returned LPWSTR from the process heap
407 * itself.
409 static LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
411 UINT cp;
412 INT lenW;
413 LPWSTR strW;
415 cp = GdiGetCodePage( hdc );
417 if(count == -1) count = strlen(str);
418 lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
419 strW = HeapAlloc(GetProcessHeap(), 0, lenW*sizeof(WCHAR));
420 MultiByteToWideChar(cp, 0, str, count, strW, lenW);
421 TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW));
422 if(plenW) *plenW = lenW;
423 if(pCP) *pCP = cp;
424 return strW;
428 /***********************************************************************
429 * CreateFontIndirectA (GDI32.@)
431 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *plfA )
433 LOGFONTW lfW;
435 if (plfA) {
436 FONT_LogFontAToW( plfA, &lfW );
437 return CreateFontIndirectW( &lfW );
438 } else
439 return CreateFontIndirectW( NULL );
443 /***********************************************************************
444 * CreateFontIndirectW (GDI32.@)
446 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
448 HFONT hFont = 0;
450 if (plf)
452 FONTOBJ* fontPtr;
453 if ((fontPtr = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC,
454 (HGDIOBJ *)&hFont, &font_funcs )))
456 static const WCHAR ItalicW[] = {' ','I','t','a','l','i','c','\0'};
457 static const WCHAR BoldW[] = {' ','B','o','l','d','\0'};
458 WCHAR *pFaceNameItalicSuffix, *pFaceNameBoldSuffix;
459 WCHAR* pFaceNameSuffix = NULL;
461 memcpy( &fontPtr->logfont, plf, sizeof(LOGFONTW) );
463 TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
464 plf->lfHeight, plf->lfWidth,
465 plf->lfEscapement, plf->lfOrientation,
466 plf->lfPitchAndFamily,
467 plf->lfOutPrecision, plf->lfClipPrecision,
468 plf->lfQuality, plf->lfCharSet,
469 debugstr_w(plf->lfFaceName),
470 plf->lfWeight > 400 ? "Bold" : "",
471 plf->lfItalic ? "Italic" : "",
472 plf->lfUnderline ? "Underline" : "", hFont);
474 if (plf->lfEscapement != plf->lfOrientation) {
475 /* this should really depend on whether GM_ADVANCED is set */
476 fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
477 WARN("orientation angle %f set to "
478 "escapement angle %f for new font %p\n",
479 plf->lfOrientation/10., plf->lfEscapement/10., hFont);
482 pFaceNameItalicSuffix = strstrW(fontPtr->logfont.lfFaceName, ItalicW);
483 if (pFaceNameItalicSuffix) {
484 fontPtr->logfont.lfItalic = TRUE;
485 pFaceNameSuffix = pFaceNameItalicSuffix;
488 pFaceNameBoldSuffix = strstrW(fontPtr->logfont.lfFaceName, BoldW);
489 if (pFaceNameBoldSuffix) {
490 if (fontPtr->logfont.lfWeight < FW_BOLD) {
491 fontPtr->logfont.lfWeight = FW_BOLD;
493 if (!pFaceNameSuffix ||
494 (pFaceNameBoldSuffix < pFaceNameSuffix)) {
495 pFaceNameSuffix = pFaceNameBoldSuffix;
499 if (pFaceNameSuffix) *pFaceNameSuffix = 0;
501 GDI_ReleaseObj( hFont );
504 else WARN("(NULL) => NULL\n");
506 return hFont;
509 /*************************************************************************
510 * CreateFontA (GDI32.@)
512 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
513 INT orient, INT weight, DWORD italic,
514 DWORD underline, DWORD strikeout, DWORD charset,
515 DWORD outpres, DWORD clippres, DWORD quality,
516 DWORD pitch, LPCSTR name )
518 LOGFONTA logfont;
520 logfont.lfHeight = height;
521 logfont.lfWidth = width;
522 logfont.lfEscapement = esc;
523 logfont.lfOrientation = orient;
524 logfont.lfWeight = weight;
525 logfont.lfItalic = italic;
526 logfont.lfUnderline = underline;
527 logfont.lfStrikeOut = strikeout;
528 logfont.lfCharSet = charset;
529 logfont.lfOutPrecision = outpres;
530 logfont.lfClipPrecision = clippres;
531 logfont.lfQuality = quality;
532 logfont.lfPitchAndFamily = pitch;
534 if (name)
535 lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
536 else
537 logfont.lfFaceName[0] = '\0';
539 return CreateFontIndirectA( &logfont );
542 /*************************************************************************
543 * CreateFontW (GDI32.@)
545 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
546 INT orient, INT weight, DWORD italic,
547 DWORD underline, DWORD strikeout, DWORD charset,
548 DWORD outpres, DWORD clippres, DWORD quality,
549 DWORD pitch, LPCWSTR name )
551 LOGFONTW logfont;
553 logfont.lfHeight = height;
554 logfont.lfWidth = width;
555 logfont.lfEscapement = esc;
556 logfont.lfOrientation = orient;
557 logfont.lfWeight = weight;
558 logfont.lfItalic = italic;
559 logfont.lfUnderline = underline;
560 logfont.lfStrikeOut = strikeout;
561 logfont.lfCharSet = charset;
562 logfont.lfOutPrecision = outpres;
563 logfont.lfClipPrecision = clippres;
564 logfont.lfQuality = quality;
565 logfont.lfPitchAndFamily = pitch;
567 if (name)
568 lstrcpynW(logfont.lfFaceName, name,
569 sizeof(logfont.lfFaceName) / sizeof(WCHAR));
570 else
571 logfont.lfFaceName[0] = '\0';
573 return CreateFontIndirectW( &logfont );
577 /***********************************************************************
578 * FONT_SelectObject
580 * If the driver supports vector fonts we create a gdi font first and
581 * then call the driver to give it a chance to supply its own device
582 * font. If the driver wants to do this it returns TRUE and we can
583 * delete the gdi font, if the driver wants to use the gdi font it
584 * should return FALSE, to signal an error return GDI_ERROR. For
585 * drivers that don't support vector fonts they must supply their own
586 * font.
588 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, void *obj, HDC hdc )
590 HGDIOBJ ret = 0;
591 DC *dc = DC_GetDCPtr( hdc );
593 if (!dc) return 0;
595 if(GetDeviceCaps(dc->hSelf, TEXTCAPS) & TC_VA_ABLE)
596 dc->gdiFont = WineEngCreateFontInstance(dc, handle);
598 if (dc->funcs->pSelectFont) ret = dc->funcs->pSelectFont( dc->physDev, handle, dc->gdiFont );
600 if (ret && dc->gdiFont) dc->gdiFont = 0;
602 if (ret == HGDI_ERROR)
603 ret = 0; /* SelectObject returns 0 on error */
604 else
606 ret = dc->hFont;
607 dc->hFont = handle;
609 GDI_ReleaseObj( hdc );
610 return ret;
614 /***********************************************************************
615 * FONT_GetObject16
617 static INT FONT_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
619 FONTOBJ *font = obj;
620 LOGFONT16 lf16;
622 FONT_LogFontWTo16( &font->logfont, &lf16 );
624 if (count > sizeof(LOGFONT16)) count = sizeof(LOGFONT16);
625 memcpy( buffer, &lf16, count );
626 return count;
629 /***********************************************************************
630 * FONT_GetObjectA
632 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
634 FONTOBJ *font = obj;
635 LOGFONTA lfA;
637 if(!buffer)
638 return sizeof(lfA);
639 FONT_LogFontWToA( &font->logfont, &lfA );
641 if (count > sizeof(lfA)) count = sizeof(lfA);
642 memcpy( buffer, &lfA, count );
643 return count;
646 /***********************************************************************
647 * FONT_GetObjectW
649 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
651 FONTOBJ *font = obj;
652 if(!buffer)
653 return sizeof(LOGFONTW);
654 if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
655 memcpy( buffer, &font->logfont, count );
656 return count;
660 /***********************************************************************
661 * FONT_DeleteObject
663 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj )
665 WineEngDestroyFontInstance( handle );
666 return GDI_FreeObject( handle, obj );
670 /***********************************************************************
671 * FONT_EnumInstance16
673 * Called by the device driver layer to pass font info
674 * down to the application.
676 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
677 * We have to use other types because of the FONTENUMPROCW definition.
679 static INT CALLBACK FONT_EnumInstance16( const LOGFONTW *plf, const TEXTMETRICW *ptm,
680 DWORD fType, LPARAM lp )
682 fontEnum16 *pfe = (fontEnum16*)lp;
683 INT ret = 1;
684 DC *dc;
686 if( pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
687 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet )
689 WORD args[7];
690 DWORD result;
692 FONT_EnumLogFontExWTo16((const ENUMLOGFONTEXW *)plf, pfe->lpLogFont);
693 FONT_NewTextMetricExWTo16((const NEWTEXTMETRICEXW *)ptm, pfe->lpTextMetric);
694 pfe->dwFlags |= ENUM_CALLED;
695 GDI_ReleaseObj( pfe->hdc ); /* release the GDI lock */
697 args[6] = SELECTOROF(pfe->segLogFont);
698 args[5] = OFFSETOF(pfe->segLogFont);
699 args[4] = SELECTOROF(pfe->segTextMetric);
700 args[3] = OFFSETOF(pfe->segTextMetric);
701 args[2] = fType;
702 args[1] = HIWORD(pfe->lpData);
703 args[0] = LOWORD(pfe->lpData);
704 WOWCallback16Ex( (DWORD)pfe->lpEnumFunc, WCB16_PASCAL, sizeof(args), args, &result );
705 ret = LOWORD(result);
707 /* get the lock again and make sure the DC is still valid */
708 dc = DC_GetDCPtr( pfe->hdc );
709 if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
711 if (dc) GDI_ReleaseObj( pfe->hdc );
712 pfe->hdc = 0; /* make sure we don't try to release it later on */
713 ret = 0;
716 return ret;
719 /***********************************************************************
720 * FONT_EnumInstance
722 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
723 * We have to use other types because of the FONTENUMPROCW definition.
725 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
726 DWORD fType, LPARAM lp )
728 fontEnum32 *pfe = (fontEnum32*)lp;
729 INT ret = 1;
730 DC *dc;
732 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
733 if((pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
734 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
735 (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
737 /* convert font metrics */
738 ENUMLOGFONTEXA logfont;
739 NEWTEXTMETRICEXA tmA;
741 pfe->dwFlags |= ENUM_CALLED;
742 if (!(pfe->dwFlags & ENUM_UNICODE))
744 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
745 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
746 plf = (LOGFONTW *)&logfont.elfLogFont;
747 ptm = (TEXTMETRICW *)&tmA;
749 GDI_ReleaseObj( pfe->hdc ); /* release the GDI lock */
751 ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
753 /* get the lock again and make sure the DC is still valid */
754 dc = DC_GetDCPtr( pfe->hdc );
755 if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
757 if (dc) GDI_ReleaseObj( pfe->hdc );
758 pfe->hdc = 0; /* make sure we don't try to release it later on */
759 ret = 0;
762 return ret;
765 /***********************************************************************
766 * EnumFontFamiliesEx (GDI.613)
768 INT16 WINAPI EnumFontFamiliesEx16( HDC16 hDC, LPLOGFONT16 plf,
769 FONTENUMPROC16 efproc, LPARAM lParam,
770 DWORD dwFlags)
772 fontEnum16 fe16;
773 INT16 ret = 1, ret2;
774 DC* dc = DC_GetDCPtr( HDC_32(hDC) );
775 NEWTEXTMETRICEX16 tm16;
776 ENUMLOGFONTEX16 lf16;
777 LOGFONTW lfW;
778 BOOL enum_gdi_fonts;
780 if (!dc) return 0;
781 FONT_LogFont16ToW(plf, &lfW);
783 fe16.hdc = HDC_32(hDC);
784 fe16.dc = dc;
785 fe16.physDev = dc->physDev;
786 fe16.lpLogFontParam = plf;
787 fe16.lpEnumFunc = efproc;
788 fe16.lpData = lParam;
789 fe16.lpTextMetric = &tm16;
790 fe16.lpLogFont = &lf16;
791 fe16.segTextMetric = MapLS( &tm16 );
792 fe16.segLogFont = MapLS( &lf16 );
793 fe16.dwFlags = 0;
795 enum_gdi_fonts = GetDeviceCaps(fe16.hdc, TEXTCAPS) & TC_VA_ABLE;
797 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
799 ret = 0;
800 goto done;
803 if (enum_gdi_fonts)
804 ret = WineEngEnumFonts( &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
805 fe16.dwFlags &= ~ENUM_CALLED;
806 if (ret && dc->funcs->pEnumDeviceFonts) {
807 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
808 if(fe16.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
809 ret = ret2;
811 done:
812 UnMapLS( fe16.segTextMetric );
813 UnMapLS( fe16.segLogFont );
814 if (fe16.hdc) GDI_ReleaseObj( fe16.hdc );
815 return ret;
818 /***********************************************************************
819 * FONT_EnumFontFamiliesEx
821 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf,
822 FONTENUMPROCW efproc,
823 LPARAM lParam, DWORD dwUnicode)
825 INT ret = 1, ret2;
826 DC *dc = DC_GetDCPtr( hDC );
827 fontEnum32 fe32;
828 BOOL enum_gdi_fonts;
830 if (!dc) return 0;
832 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName),
833 plf->lfCharSet);
834 fe32.lpLogFontParam = plf;
835 fe32.lpEnumFunc = efproc;
836 fe32.lpData = lParam;
837 fe32.dwFlags = dwUnicode;
838 fe32.hdc = hDC;
839 fe32.dc = dc;
840 fe32.physDev = dc->physDev;
842 enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE;
844 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
846 ret = 0;
847 goto done;
850 if (enum_gdi_fonts)
851 ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
852 fe32.dwFlags &= ~ENUM_CALLED;
853 if (ret && dc->funcs->pEnumDeviceFonts) {
854 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, plf, FONT_EnumInstance, (LPARAM)&fe32 );
855 if(fe32.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
856 ret = ret2;
858 done:
859 if (fe32.hdc) GDI_ReleaseObj( fe32.hdc );
860 return ret;
863 /***********************************************************************
864 * EnumFontFamiliesExW (GDI32.@)
866 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
867 FONTENUMPROCW efproc,
868 LPARAM lParam, DWORD dwFlags )
870 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, ENUM_UNICODE );
873 /***********************************************************************
874 * EnumFontFamiliesExA (GDI32.@)
876 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
877 FONTENUMPROCA efproc,
878 LPARAM lParam, DWORD dwFlags)
880 LOGFONTW lfW;
881 FONT_LogFontAToW( plf, &lfW );
883 return FONT_EnumFontFamiliesEx( hDC, &lfW, (FONTENUMPROCW)efproc, lParam, 0);
886 /***********************************************************************
887 * EnumFontFamilies (GDI.330)
889 INT16 WINAPI EnumFontFamilies16( HDC16 hDC, LPCSTR lpFamily,
890 FONTENUMPROC16 efproc, LPARAM lpData )
892 LOGFONT16 lf;
894 lf.lfCharSet = DEFAULT_CHARSET;
895 if (lpFamily)
897 if (!*lpFamily) return 1;
898 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
900 else lf.lfFaceName[0] = '\0';
902 return EnumFontFamiliesEx16( hDC, &lf, efproc, lpData, 0 );
905 /***********************************************************************
906 * EnumFontFamiliesA (GDI32.@)
908 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
909 FONTENUMPROCA efproc, LPARAM lpData )
911 LOGFONTA lf;
913 lf.lfCharSet = DEFAULT_CHARSET;
914 if (lpFamily)
916 if (!*lpFamily) return 1;
917 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
919 else lf.lfFaceName[0] = lf.lfFaceName[1] = '\0';
921 return EnumFontFamiliesExA( hDC, &lf, efproc, lpData, 0 );
924 /***********************************************************************
925 * EnumFontFamiliesW (GDI32.@)
927 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
928 FONTENUMPROCW efproc, LPARAM lpData )
930 LOGFONTW lf;
932 lf.lfCharSet = DEFAULT_CHARSET;
933 if (lpFamily)
935 if (!*lpFamily) return 1;
936 lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
938 else lf.lfFaceName[0] = 0;
940 return EnumFontFamiliesExW( hDC, &lf, efproc, lpData, 0 );
943 /***********************************************************************
944 * EnumFonts (GDI.70)
946 INT16 WINAPI EnumFonts16( HDC16 hDC, LPCSTR lpName, FONTENUMPROC16 efproc,
947 LPARAM lpData )
949 return EnumFontFamilies16( hDC, lpName, efproc, lpData );
952 /***********************************************************************
953 * EnumFontsA (GDI32.@)
955 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
956 LPARAM lpData )
958 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
961 /***********************************************************************
962 * EnumFontsW (GDI32.@)
964 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
965 LPARAM lpData )
967 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
971 /***********************************************************************
972 * GetTextCharacterExtra (GDI32.@)
974 INT WINAPI GetTextCharacterExtra( HDC hdc )
976 INT ret;
977 DC *dc = DC_GetDCPtr( hdc );
978 if (!dc) return 0x80000000;
979 ret = dc->charExtra;
980 GDI_ReleaseObj( hdc );
981 return ret;
985 /***********************************************************************
986 * SetTextCharacterExtra (GDI32.@)
988 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
990 INT prev;
991 DC * dc = DC_GetDCPtr( hdc );
992 if (!dc) return 0x80000000;
993 if (dc->funcs->pSetTextCharacterExtra)
994 prev = dc->funcs->pSetTextCharacterExtra( dc->physDev, extra );
995 else
997 prev = dc->charExtra;
998 dc->charExtra = extra;
1000 GDI_ReleaseObj( hdc );
1001 return prev;
1005 /***********************************************************************
1006 * SetTextJustification (GDI32.@)
1008 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
1010 BOOL ret = TRUE;
1011 DC * dc = DC_GetDCPtr( hdc );
1012 if (!dc) return FALSE;
1013 if (dc->funcs->pSetTextJustification)
1014 ret = dc->funcs->pSetTextJustification( dc->physDev, extra, breaks );
1015 else
1017 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
1018 if (!extra) breaks = 0;
1019 if (breaks)
1021 dc->breakExtra = extra / breaks;
1022 dc->breakRem = extra - (breaks * dc->breakExtra);
1024 else
1026 dc->breakExtra = 0;
1027 dc->breakRem = 0;
1030 GDI_ReleaseObj( hdc );
1031 return ret;
1035 /***********************************************************************
1036 * GetTextFaceA (GDI32.@)
1038 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
1040 INT res = GetTextFaceW(hdc, 0, NULL);
1041 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
1042 GetTextFaceW( hdc, res, nameW );
1044 if (name)
1046 if (count && !WideCharToMultiByte( CP_ACP, 0, nameW, -1, name, count, NULL, NULL))
1047 name[count-1] = 0;
1048 res = strlen(name);
1050 else
1051 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
1052 HeapFree( GetProcessHeap(), 0, nameW );
1053 return res;
1056 /***********************************************************************
1057 * GetTextFaceW (GDI32.@)
1059 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
1061 FONTOBJ *font;
1062 INT ret = 0;
1064 DC * dc = DC_GetDCPtr( hdc );
1065 if (!dc) return 0;
1067 if(dc->gdiFont)
1068 ret = WineEngGetTextFace(dc->gdiFont, count, name);
1069 else if ((font = (FONTOBJ *) GDI_GetObjPtr( dc->hFont, FONT_MAGIC )))
1071 if (name)
1073 lstrcpynW( name, font->logfont.lfFaceName, count );
1074 ret = strlenW(name);
1076 else ret = strlenW(font->logfont.lfFaceName) + 1;
1077 GDI_ReleaseObj( dc->hFont );
1079 GDI_ReleaseObj( hdc );
1080 return ret;
1084 /***********************************************************************
1085 * GetTextExtentPoint32A (GDI32.@)
1087 * See GetTextExtentPoint32W.
1089 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
1090 LPSIZE size )
1092 BOOL ret = FALSE;
1093 INT wlen;
1094 LPWSTR p;
1096 if(count < 0) return FALSE;
1098 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1099 if (p) {
1100 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
1101 HeapFree( GetProcessHeap(), 0, p );
1104 TRACE("(%p %s %d %p): returning %d x %d\n",
1105 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
1106 return ret;
1110 /***********************************************************************
1111 * GetTextExtentPoint32W [GDI32.@]
1113 * Computes width/height for a string.
1115 * Computes width and height of the specified string.
1117 * RETURNS
1118 * Success: TRUE
1119 * Failure: FALSE
1121 BOOL WINAPI GetTextExtentPoint32W(
1122 HDC hdc, /* [in] Handle of device context */
1123 LPCWSTR str, /* [in] Address of text string */
1124 INT count, /* [in] Number of characters in string */
1125 LPSIZE size) /* [out] Address of structure for string size */
1127 return GetTextExtentExPointW(hdc, str, count, 0, NULL, NULL, size);
1130 /***********************************************************************
1131 * GetTextExtentPointI [GDI32.@]
1133 * Computes width and height of the array of glyph indices.
1135 * RETURNS
1136 * Success: TRUE
1137 * Failure: FALSE
1139 BOOL WINAPI GetTextExtentPointI(
1140 HDC hdc, /* [in] Handle of device context */
1141 const WORD *indices, /* [in] Address of glyph index array */
1142 INT count, /* [in] Number of glyphs in array */
1143 LPSIZE size) /* [out] Address of structure for string size */
1145 BOOL ret = FALSE;
1146 DC *dc;
1148 if (count < 0) return FALSE;
1150 dc = DC_GetDCPtr( hdc );
1151 if (!dc) return FALSE;
1153 if(dc->gdiFont) {
1154 ret = WineEngGetTextExtentPointI(dc->gdiFont, indices, count, size);
1155 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1156 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1157 size->cx += count * dc->charExtra;
1159 else if(dc->funcs->pGetTextExtentExPoint) {
1160 FIXME("calling GetTextExtentExPoint\n");
1161 ret = dc->funcs->pGetTextExtentExPoint( dc->physDev, (LPCWSTR)indices,
1162 count, 0, NULL, NULL, size );
1165 GDI_ReleaseObj( hdc );
1167 TRACE("(%p %p %d %p): returning %d x %d\n",
1168 hdc, indices, count, size, size->cx, size->cy );
1169 return ret;
1173 /***********************************************************************
1174 * GetTextExtentPointA (GDI32.@)
1176 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
1177 LPSIZE size )
1179 TRACE("not bug compatible.\n");
1180 return GetTextExtentPoint32A( hdc, str, count, size );
1183 /***********************************************************************
1184 * GetTextExtentPointW (GDI32.@)
1186 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1187 LPSIZE size )
1189 TRACE("not bug compatible.\n");
1190 return GetTextExtentPoint32W( hdc, str, count, size );
1194 /***********************************************************************
1195 * GetTextExtentExPointA (GDI32.@)
1197 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1198 INT maxExt, LPINT lpnFit,
1199 LPINT alpDx, LPSIZE size )
1201 BOOL ret;
1202 INT wlen;
1203 INT *walpDx = NULL;
1204 LPWSTR p = NULL;
1206 if (alpDx &&
1207 NULL == (walpDx = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT))))
1208 return FALSE;
1210 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1211 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
1212 if (walpDx)
1214 INT n = lpnFit ? *lpnFit : wlen;
1215 INT i, j;
1216 for(i = 0, j = 0; i < n; i++, j++)
1218 alpDx[j] = walpDx[i];
1219 if (IsDBCSLeadByte(str[j])) alpDx[++j] = walpDx[i];
1222 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1223 HeapFree( GetProcessHeap(), 0, p );
1224 HeapFree( GetProcessHeap(), 0, walpDx );
1225 return ret;
1229 /***********************************************************************
1230 * GetTextExtentExPointW (GDI32.@)
1232 * Return the size of the string as it would be if it was output properly by
1233 * e.g. TextOut.
1235 * This should include
1236 * - Intercharacter spacing
1237 * - justification spacing (not yet done)
1238 * - kerning? see below
1240 * Kerning. Since kerning would be carried out by the rendering code it should
1241 * be done by the driver. However they don't support it yet. Also I am not
1242 * yet persuaded that (certainly under Win95) any kerning is actually done.
1244 * str: According to MSDN this should be null-terminated. That is not true; a
1245 * null will not terminate it early.
1246 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1247 * than count. I have seen it be either the size of the full string or
1248 * 1 less than the size of the full string. I have not seen it bear any
1249 * resemblance to the portion that would fit.
1250 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1251 * trailing intercharacter spacing and any trailing justification.
1253 * FIXME
1254 * Currently we do this by measuring each character etc. We should do it by
1255 * passing the request to the driver, perhaps by extending the
1256 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1257 * thinking about kerning issues and rounding issues in the justification.
1260 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1261 INT maxExt, LPINT lpnFit,
1262 LPINT alpDx, LPSIZE size )
1264 INT nFit = 0;
1265 LPINT dxs = NULL;
1266 DC *dc;
1267 BOOL ret = FALSE;
1268 TEXTMETRICW tm;
1270 if (count < 0) return FALSE;
1272 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1274 dc = DC_GetDCPtr(hdc);
1275 if (! dc)
1276 return FALSE;
1278 GetTextMetricsW(hdc, &tm);
1280 /* If we need to calculate nFit, then we need the partial extents even if
1281 the user hasn't provided us with an array. */
1282 if (lpnFit)
1284 dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]);
1285 if (! dxs)
1287 GDI_ReleaseObj(hdc);
1288 SetLastError(ERROR_OUTOFMEMORY);
1289 return FALSE;
1292 else
1293 dxs = alpDx;
1295 if (dc->gdiFont)
1296 ret = WineEngGetTextExtentExPoint(dc->gdiFont, str, count,
1297 0, NULL, dxs, size);
1298 else if (dc->funcs->pGetTextExtentExPoint)
1299 ret = dc->funcs->pGetTextExtentExPoint(dc->physDev, str, count,
1300 0, NULL, dxs, size);
1302 /* Perform device size to world size transformations. */
1303 if (ret)
1305 INT extra = dc->charExtra,
1306 breakExtra = dc->breakExtra,
1307 breakRem = dc->breakRem,
1310 if (dxs)
1312 for (i = 0; i < count; ++i)
1314 dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
1315 dxs[i] += (i+1) * extra;
1316 if (count > 1 && (breakExtra || breakRem) && str[i] == tm.tmBreakChar)
1318 dxs[i] += breakExtra;
1319 if (breakRem > 0)
1321 breakRem--;
1322 dxs[i]++;
1325 if (dxs[i] <= maxExt)
1326 ++nFit;
1328 breakRem = dc->breakRem;
1330 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1331 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1333 if (!dxs && count > 1 && (breakExtra || breakRem))
1335 for (i = 0; i < count; i++)
1337 if (str[i] == tm.tmBreakChar)
1339 size->cx += breakExtra;
1340 if (breakRem > 0)
1342 breakRem--;
1343 (size->cx)++;
1350 if (lpnFit)
1351 *lpnFit = nFit;
1353 if (! alpDx)
1354 HeapFree(GetProcessHeap(), 0, dxs);
1356 GDI_ReleaseObj( hdc );
1358 TRACE("returning %d %d x %d\n",nFit,size->cx,size->cy);
1359 return ret;
1362 /***********************************************************************
1363 * GetTextMetricsA (GDI32.@)
1365 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1367 TEXTMETRICW tm32;
1369 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1370 FONT_TextMetricWToA( &tm32, metrics );
1371 return TRUE;
1374 /***********************************************************************
1375 * GetTextMetricsW (GDI32.@)
1377 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1379 BOOL ret = FALSE;
1380 DC * dc = DC_GetDCPtr( hdc );
1381 if (!dc) return FALSE;
1383 if (dc->gdiFont)
1384 ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1385 else if (dc->funcs->pGetTextMetrics)
1386 ret = dc->funcs->pGetTextMetrics( dc->physDev, metrics );
1388 if (ret)
1390 /* device layer returns values in device units
1391 * therefore we have to convert them to logical */
1393 metrics->tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1394 metrics->tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1396 #define WDPTOLP(x) ((x<0)? \
1397 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1398 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1399 #define HDPTOLP(y) ((y<0)? \
1400 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1401 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1403 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1404 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1405 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1406 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1407 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1408 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1409 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1410 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1411 ret = TRUE;
1412 #undef WDPTOLP
1413 #undef HDPTOLP
1414 TRACE("text metrics:\n"
1415 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1416 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1417 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1418 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1419 " PitchAndFamily = %02x\n"
1420 " --------------------\n"
1421 " InternalLeading = %i\n"
1422 " Ascent = %i\n"
1423 " Descent = %i\n"
1424 " Height = %i\n",
1425 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1426 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1427 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1428 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1429 metrics->tmPitchAndFamily,
1430 metrics->tmInternalLeading,
1431 metrics->tmAscent,
1432 metrics->tmDescent,
1433 metrics->tmHeight );
1435 GDI_ReleaseObj( hdc );
1436 return ret;
1440 /***********************************************************************
1441 * GetOutlineTextMetrics [GDI.308] Gets metrics for TrueType fonts.
1443 * NOTES
1444 * lpOTM should be LPOUTLINETEXTMETRIC
1446 * RETURNS
1447 * Success: Non-zero or size of required buffer
1448 * Failure: 0
1450 UINT16 WINAPI GetOutlineTextMetrics16(
1451 HDC16 hdc, /* [in] Handle of device context */
1452 UINT16 cbData, /* [in] Size of metric data array */
1453 LPOUTLINETEXTMETRIC16 lpOTM) /* [out] Address of metric data array */
1455 FIXME("(%04x,%04x,%p): stub\n", hdc,cbData,lpOTM);
1456 return 0;
1460 /***********************************************************************
1461 * GetOutlineTextMetricsA (GDI32.@)
1462 * Gets metrics for TrueType fonts.
1464 * NOTES
1465 * If the supplied buffer isn't big enough Windows partially fills it up to
1466 * its given length and returns that length.
1468 * RETURNS
1469 * Success: Non-zero or size of required buffer
1470 * Failure: 0
1472 UINT WINAPI GetOutlineTextMetricsA(
1473 HDC hdc, /* [in] Handle of device context */
1474 UINT cbData, /* [in] Size of metric data array */
1475 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1477 char buf[512], *ptr;
1478 UINT ret, needed;
1479 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1480 OUTLINETEXTMETRICA *output = lpOTM;
1481 INT left, len;
1483 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1484 return 0;
1485 if(ret > sizeof(buf))
1486 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1487 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1489 needed = sizeof(OUTLINETEXTMETRICA);
1490 if(lpOTMW->otmpFamilyName)
1491 needed += WideCharToMultiByte(CP_ACP, 0,
1492 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1493 NULL, 0, NULL, NULL);
1494 if(lpOTMW->otmpFaceName)
1495 needed += WideCharToMultiByte(CP_ACP, 0,
1496 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1497 NULL, 0, NULL, NULL);
1498 if(lpOTMW->otmpStyleName)
1499 needed += WideCharToMultiByte(CP_ACP, 0,
1500 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1501 NULL, 0, NULL, NULL);
1502 if(lpOTMW->otmpFullName)
1503 needed += WideCharToMultiByte(CP_ACP, 0,
1504 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1505 NULL, 0, NULL, NULL);
1507 if(!lpOTM) {
1508 ret = needed;
1509 goto end;
1512 TRACE("needed = %d\n", needed);
1513 if(needed > cbData)
1514 /* Since the supplied buffer isn't big enough, we'll alloc one
1515 that is and memcpy the first cbData bytes into the lpOTM at
1516 the end. */
1517 output = HeapAlloc(GetProcessHeap(), 0, needed);
1519 ret = output->otmSize = min(needed, cbData);
1520 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1521 output->otmFiller = 0;
1522 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1523 output->otmfsSelection = lpOTMW->otmfsSelection;
1524 output->otmfsType = lpOTMW->otmfsType;
1525 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1526 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1527 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1528 output->otmEMSquare = lpOTMW->otmEMSquare;
1529 output->otmAscent = lpOTMW->otmAscent;
1530 output->otmDescent = lpOTMW->otmDescent;
1531 output->otmLineGap = lpOTMW->otmLineGap;
1532 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1533 output->otmsXHeight = lpOTMW->otmsXHeight;
1534 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1535 output->otmMacAscent = lpOTMW->otmMacAscent;
1536 output->otmMacDescent = lpOTMW->otmMacDescent;
1537 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1538 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1539 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1540 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1541 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1542 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1543 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1544 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1545 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1546 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1549 ptr = (char*)(output + 1);
1550 left = needed - sizeof(*output);
1552 if(lpOTMW->otmpFamilyName) {
1553 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1554 len = WideCharToMultiByte(CP_ACP, 0,
1555 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1556 ptr, left, NULL, NULL);
1557 left -= len;
1558 ptr += len;
1559 } else
1560 output->otmpFamilyName = 0;
1562 if(lpOTMW->otmpFaceName) {
1563 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1564 len = WideCharToMultiByte(CP_ACP, 0,
1565 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1566 ptr, left, NULL, NULL);
1567 left -= len;
1568 ptr += len;
1569 } else
1570 output->otmpFaceName = 0;
1572 if(lpOTMW->otmpStyleName) {
1573 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1574 len = WideCharToMultiByte(CP_ACP, 0,
1575 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1576 ptr, left, NULL, NULL);
1577 left -= len;
1578 ptr += len;
1579 } else
1580 output->otmpStyleName = 0;
1582 if(lpOTMW->otmpFullName) {
1583 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1584 len = WideCharToMultiByte(CP_ACP, 0,
1585 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1586 ptr, left, NULL, NULL);
1587 left -= len;
1588 } else
1589 output->otmpFullName = 0;
1591 assert(left == 0);
1593 if(output != lpOTM) {
1594 memcpy(lpOTM, output, cbData);
1595 HeapFree(GetProcessHeap(), 0, output);
1597 /* check if the string offsets really fit into the provided size */
1598 /* FIXME: should we check string length as well? */
1599 /* make sure that we don't read/write beyond the provided buffer */
1600 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(LPSTR))
1602 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1603 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1606 /* make sure that we don't read/write beyond the provided buffer */
1607 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(LPSTR))
1609 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1610 lpOTM->otmpFaceName = 0; /* doesn't fit */
1613 /* make sure that we don't read/write beyond the provided buffer */
1614 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(LPSTR))
1616 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1617 lpOTM->otmpStyleName = 0; /* doesn't fit */
1620 /* make sure that we don't read/write beyond the provided buffer */
1621 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(LPSTR))
1623 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1624 lpOTM->otmpFullName = 0; /* doesn't fit */
1628 end:
1629 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1630 HeapFree(GetProcessHeap(), 0, lpOTMW);
1632 return ret;
1636 /***********************************************************************
1637 * GetOutlineTextMetricsW [GDI32.@]
1639 UINT WINAPI GetOutlineTextMetricsW(
1640 HDC hdc, /* [in] Handle of device context */
1641 UINT cbData, /* [in] Size of metric data array */
1642 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1644 DC *dc = DC_GetDCPtr( hdc );
1645 OUTLINETEXTMETRICW *output = lpOTM;
1646 UINT ret;
1648 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1649 if(!dc) return 0;
1651 if(dc->gdiFont) {
1652 ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, output);
1653 if(lpOTM && ret) {
1654 if(ret > cbData) {
1655 output = HeapAlloc(GetProcessHeap(), 0, ret);
1656 WineEngGetOutlineTextMetrics(dc->gdiFont, ret, output);
1659 #define WDPTOLP(x) ((x<0)? \
1660 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1661 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1662 #define HDPTOLP(y) ((y<0)? \
1663 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1664 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1666 output->otmTextMetrics.tmHeight = HDPTOLP(output->otmTextMetrics.tmHeight);
1667 output->otmTextMetrics.tmAscent = HDPTOLP(output->otmTextMetrics.tmAscent);
1668 output->otmTextMetrics.tmDescent = HDPTOLP(output->otmTextMetrics.tmDescent);
1669 output->otmTextMetrics.tmInternalLeading = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1670 output->otmTextMetrics.tmExternalLeading = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1671 output->otmTextMetrics.tmAveCharWidth = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1672 output->otmTextMetrics.tmMaxCharWidth = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1673 output->otmTextMetrics.tmOverhang = WDPTOLP(output->otmTextMetrics.tmOverhang);
1674 output->otmAscent = HDPTOLP(output->otmAscent);
1675 output->otmDescent = HDPTOLP(output->otmDescent);
1676 output->otmLineGap = HDPTOLP(output->otmLineGap);
1677 output->otmsCapEmHeight = HDPTOLP(output->otmsCapEmHeight);
1678 output->otmsXHeight = HDPTOLP(output->otmsXHeight);
1679 output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1680 output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1681 output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1682 output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1683 output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1684 output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1685 output->otmMacLineGap = HDPTOLP(output->otmMacLineGap);
1686 output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1687 output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1688 output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1689 output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1690 output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1691 output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1692 output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1693 output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1694 output->otmsStrikeoutSize = HDPTOLP(output->otmsStrikeoutSize);
1695 output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1696 output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1697 output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1698 #undef WDPTOLP
1699 #undef HDPTOLP
1700 if(output != lpOTM) {
1701 memcpy(lpOTM, output, cbData);
1702 HeapFree(GetProcessHeap(), 0, output);
1703 ret = cbData;
1708 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1709 but really this should just be a return 0. */
1711 ret = sizeof(*lpOTM);
1712 if (lpOTM) {
1713 if(cbData < ret)
1714 ret = 0;
1715 else {
1716 memset(lpOTM, 0, ret);
1717 lpOTM->otmSize = sizeof(*lpOTM);
1718 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1720 Further fill of the structure not implemented,
1721 Needs real values for the structure members
1726 GDI_ReleaseObj(hdc);
1727 return ret;
1731 /***********************************************************************
1732 * GetCharWidthW (GDI32.@)
1733 * GetCharWidth32W (GDI32.@)
1735 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1736 LPINT buffer )
1738 UINT i;
1739 BOOL ret = FALSE;
1740 DC * dc = DC_GetDCPtr( hdc );
1741 if (!dc) return FALSE;
1743 if (dc->gdiFont)
1744 ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1745 else if (dc->funcs->pGetCharWidth)
1746 ret = dc->funcs->pGetCharWidth( dc->physDev, firstChar, lastChar, buffer);
1748 if (ret)
1750 /* convert device units to logical */
1751 for( i = firstChar; i <= lastChar; i++, buffer++ )
1752 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1753 ret = TRUE;
1755 GDI_ReleaseObj( hdc );
1756 return ret;
1760 /***********************************************************************
1761 * GetCharWidthA (GDI32.@)
1762 * GetCharWidth32A (GDI32.@)
1764 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1765 LPINT buffer )
1767 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1768 LPSTR str;
1769 LPWSTR wstr;
1770 BOOL ret = TRUE;
1772 if(count <= 0) return FALSE;
1774 str = HeapAlloc(GetProcessHeap(), 0, count);
1775 for(i = 0; i < count; i++)
1776 str[i] = (BYTE)(firstChar + i);
1778 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1780 for(i = 0; i < wlen; i++)
1782 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1784 ret = FALSE;
1785 break;
1787 buffer++;
1790 HeapFree(GetProcessHeap(), 0, str);
1791 HeapFree(GetProcessHeap(), 0, wstr);
1793 return ret;
1797 /***********************************************************************
1798 * ExtTextOutA (GDI32.@)
1800 * See ExtTextOutW.
1802 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1803 const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1805 INT wlen;
1806 UINT codepage;
1807 LPWSTR p;
1808 BOOL ret;
1809 LPINT lpDxW = NULL;
1810 unsigned int i;
1812 if (flags & ETO_GLYPH_INDEX)
1813 return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
1815 if(GetObjectType(hdc) != OBJ_METADC) {
1816 p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
1818 if (lpDx) {
1819 unsigned int i = 0, j = 0;
1821 lpDxW = HeapAlloc( GetProcessHeap(), 0, wlen*sizeof(INT));
1822 while(i < count) {
1823 if(IsDBCSLeadByteEx(codepage, str[i])) {
1824 lpDxW[j++] = lpDx[i] + lpDx[i+1];
1825 i = i + 2;
1826 } else {
1827 lpDxW[j++] = lpDx[i];
1828 i = i + 1;
1832 } else { /* Special case for metafiles. Just do a straight copy */
1833 p = HeapAlloc(GetProcessHeap(), 0, (count + 1) * sizeof(WCHAR));
1834 for(i = 0; i < count; i++)
1835 p[i] = (BYTE)str[i];
1836 p[count] = '\0';
1837 wlen = count;
1838 if(lpDx) {
1839 lpDxW = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT));
1840 for(i = 0; i < count; i++)
1841 lpDxW[i] = lpDx[i];
1845 ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1847 HeapFree( GetProcessHeap(), 0, p );
1848 HeapFree( GetProcessHeap(), 0, lpDxW );
1849 return ret;
1853 /***********************************************************************
1854 * ExtTextOutW (GDI32.@)
1856 * Draws text using the currently selected font, background color, and text color.
1859 * PARAMS
1860 * x,y [I] coordinates of string
1861 * flags [I]
1862 * ETO_GRAYED - undocumented on MSDN
1863 * ETO_OPAQUE - use background color for fill the rectangle
1864 * ETO_CLIPPED - clipping text to the rectangle
1865 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1866 * than encoded characters. Implies ETO_IGNORELANGUAGE
1867 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1868 * Affects BiDi ordering
1869 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1870 * ETO_PDY - unimplemented
1871 * ETO_NUMERICSLATIN - unimplemented always assumed -
1872 * do not translate numbers into locale representations
1873 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1874 * lprect [I] dimensions for clipping or/and opaquing
1875 * str [I] text string
1876 * count [I] number of symbols in string
1877 * lpDx [I] optional parameter with distance between drawing characters
1879 * RETURNS
1880 * Success: TRUE
1881 * Failure: FALSE
1883 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1884 const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1886 BOOL ret = FALSE;
1887 LPWSTR reordered_str = (LPWSTR)str;
1888 WORD *glyphs = NULL;
1889 UINT align = GetTextAlign( hdc );
1890 POINT pt;
1891 TEXTMETRICW tm;
1892 LOGFONTW lf;
1893 double cosEsc, sinEsc;
1894 INT *deltas = NULL, char_extra;
1895 SIZE sz;
1896 RECT rc;
1897 BOOL done_extents = FALSE;
1898 INT width = 0, xwidth = 0, ywidth = 0;
1899 DWORD type;
1900 DC * dc = DC_GetDCUpdate( hdc );
1901 INT breakRem;
1903 if (!dc) return FALSE;
1905 breakRem = dc->breakRem;
1907 if (flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY))
1908 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY unimplemented\n");
1910 if (!dc->funcs->pExtTextOut && !PATH_IsPathOpen(dc->path))
1912 GDI_ReleaseObj( hdc );
1913 return ret;
1916 type = GetObjectType(hdc);
1917 if(type == OBJ_METADC || type == OBJ_ENHMETADC)
1919 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, flags, lprect, str, count, lpDx);
1920 GDI_ReleaseObj( hdc );
1921 return ret;
1924 if (!lprect)
1925 flags &= ~ETO_CLIPPED;
1927 if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && BidiAvail && count > 0 )
1929 reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1931 BIDI_Reorder( str, count, GCP_REORDER,
1932 ((flags&ETO_RTLREADING)!=0 || (GetTextAlign(hdc)&TA_RTLREADING)!=0)?
1933 WINE_GCPW_FORCE_RTL:WINE_GCPW_FORCE_LTR,
1934 reordered_str, count, NULL );
1936 flags |= ETO_IGNORELANGUAGE;
1939 TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc, x, y, flags,
1940 lprect, debugstr_wn(str, count), count, lpDx);
1942 if(flags & ETO_GLYPH_INDEX)
1943 glyphs = reordered_str;
1945 if(lprect)
1946 TRACE("rect: %d,%d - %d,%d\n", lprect->left, lprect->top, lprect->right,
1947 lprect->bottom);
1948 TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
1950 if(align & TA_UPDATECP)
1952 GetCurrentPositionEx( hdc, &pt );
1953 x = pt.x;
1954 y = pt.y;
1957 GetTextMetricsW(hdc, &tm);
1958 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1960 if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
1961 lf.lfEscapement = 0;
1963 if(lf.lfEscapement != 0)
1965 cosEsc = cos(lf.lfEscapement * M_PI / 1800);
1966 sinEsc = sin(lf.lfEscapement * M_PI / 1800);
1968 else
1970 cosEsc = 1;
1971 sinEsc = 0;
1974 if(flags & (ETO_CLIPPED | ETO_OPAQUE))
1976 if(!lprect)
1978 if(flags & ETO_GLYPH_INDEX)
1979 GetTextExtentPointI(hdc, glyphs, count, &sz);
1980 else
1981 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1983 done_extents = TRUE;
1984 rc.left = x;
1985 rc.top = y;
1986 rc.right = x + sz.cx;
1987 rc.bottom = y + sz.cy;
1989 else
1991 rc = *lprect;
1994 LPtoDP(hdc, (POINT*)&rc, 2);
1996 if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
1997 if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
2000 if ((flags & ETO_OPAQUE) && !PATH_IsPathOpen(dc->path))
2001 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
2003 if(count == 0)
2005 ret = TRUE;
2006 goto done;
2009 pt.x = x;
2010 pt.y = y;
2011 LPtoDP(hdc, &pt, 1);
2012 x = pt.x;
2013 y = pt.y;
2015 char_extra = GetTextCharacterExtra(hdc);
2016 if(char_extra || dc->breakExtra || breakRem || lpDx)
2018 UINT i;
2019 SIZE tmpsz;
2020 deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT));
2021 for(i = 0; i < count; i++)
2023 if(lpDx && (flags & ETO_PDY))
2024 deltas[i] = lpDx[i*2] + char_extra;
2025 else if(lpDx)
2026 deltas[i] = lpDx[i] + char_extra;
2027 else
2029 if(flags & ETO_GLYPH_INDEX)
2030 GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
2031 else
2032 GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
2034 deltas[i] = tmpsz.cx;
2037 if (!(flags & ETO_GLYPH_INDEX) && (dc->breakExtra || breakRem) && reordered_str[i] == tm.tmBreakChar)
2039 deltas[i] = deltas[i] + dc->breakExtra;
2040 if (breakRem > 0)
2042 breakRem--;
2043 deltas[i]++;
2046 deltas[i] = INTERNAL_XWSTODS(dc, deltas[i]);
2047 width += deltas[i];
2050 else
2052 if(!done_extents)
2054 if(flags & ETO_GLYPH_INDEX)
2055 GetTextExtentPointI(hdc, glyphs, count, &sz);
2056 else
2057 GetTextExtentPointW(hdc, reordered_str, count, &sz);
2058 done_extents = TRUE;
2060 width = INTERNAL_XWSTODS(dc, sz.cx);
2062 xwidth = width * cosEsc;
2063 ywidth = width * sinEsc;
2065 tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
2066 tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
2067 switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
2069 case TA_LEFT:
2070 if (align & TA_UPDATECP)
2072 pt.x = x + xwidth;
2073 pt.y = y - ywidth;
2074 DPtoLP(hdc, &pt, 1);
2075 MoveToEx(hdc, pt.x, pt.y, NULL);
2077 break;
2079 case TA_CENTER:
2080 x -= xwidth / 2;
2081 y += ywidth / 2;
2082 break;
2084 case TA_RIGHT:
2085 x -= xwidth;
2086 y += ywidth;
2087 if (align & TA_UPDATECP)
2089 pt.x = x;
2090 pt.y = y;
2091 DPtoLP(hdc, &pt, 1);
2092 MoveToEx(hdc, pt.x, pt.y, NULL);
2094 break;
2097 switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
2099 case TA_TOP:
2100 y += tm.tmAscent * cosEsc;
2101 x += tm.tmAscent * sinEsc;
2102 break;
2104 case TA_BOTTOM:
2105 y -= tm.tmDescent * cosEsc;
2106 x -= tm.tmDescent * sinEsc;
2107 break;
2109 case TA_BASELINE:
2110 break;
2113 if (GetBkMode(hdc) != TRANSPARENT && !PATH_IsPathOpen(dc->path))
2115 if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
2117 if(!(flags & ETO_OPAQUE) || x < rc.left || x + width >= rc.right ||
2118 y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
2120 RECT rc;
2121 rc.left = x;
2122 rc.right = x + width;
2123 rc.top = y - tm.tmAscent;
2124 rc.bottom = y + tm.tmDescent;
2125 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
2130 if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
2132 HFONT orig_font = dc->hFont, cur_font;
2133 UINT glyph;
2134 INT span = 0, *offsets = NULL, i;
2136 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2137 for(i = 0; i < count; i++)
2139 WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
2140 if(cur_font != dc->hFont)
2142 if(!offsets)
2144 int j;
2145 offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
2146 offsets[0] = 0;
2147 if(!deltas)
2149 SIZE tmpsz;
2150 for(j = 1; j < count; j++)
2152 GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
2153 offsets[j] = offsets[j-1] + INTERNAL_XWSTODS(dc, tmpsz.cx);
2156 else
2158 for(j = 1; j < count; j++)
2159 offsets[j] = offsets[j-1] + deltas[j];
2162 if(span)
2164 if (PATH_IsPathOpen(dc->path))
2165 ret = PATH_ExtTextOut(dc, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
2166 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2167 glyphs, span, deltas ? deltas + i - span : NULL);
2168 else
2169 dc->funcs->pExtTextOut(dc->physDev, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
2170 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2171 glyphs, span, deltas ? deltas + i - span : NULL);
2172 span = 0;
2174 SelectObject(hdc, cur_font);
2176 glyphs[span++] = glyph;
2178 if(i == count - 1)
2180 if (PATH_IsPathOpen(dc->path))
2181 ret = PATH_ExtTextOut(dc, x + (offsets ? offsets[count - span] * cosEsc : 0),
2182 y - (offsets ? offsets[count - span] * sinEsc : 0),
2183 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2184 glyphs, span, deltas ? deltas + count - span : NULL);
2185 else
2186 ret = dc->funcs->pExtTextOut(dc->physDev, x + (offsets ? offsets[count - span] * cosEsc : 0),
2187 y - (offsets ? offsets[count - span] * sinEsc : 0),
2188 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2189 glyphs, span, deltas ? deltas + count - span : NULL);
2190 SelectObject(hdc, orig_font);
2191 HeapFree(GetProcessHeap(), 0, offsets);
2195 else
2197 if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
2199 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2200 GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
2201 flags |= ETO_GLYPH_INDEX;
2204 if (PATH_IsPathOpen(dc->path))
2205 ret = PATH_ExtTextOut(dc, x, y, (flags & ~ETO_OPAQUE), &rc,
2206 glyphs ? glyphs : reordered_str, count, deltas);
2207 else
2208 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, (flags & ~ETO_OPAQUE), &rc,
2209 glyphs ? glyphs : reordered_str, count, deltas);
2212 done:
2213 HeapFree(GetProcessHeap(), 0, deltas);
2214 if(glyphs != reordered_str)
2215 HeapFree(GetProcessHeap(), 0, glyphs);
2216 if(reordered_str != str)
2217 HeapFree(GetProcessHeap(), 0, reordered_str);
2219 GDI_ReleaseObj( hdc );
2221 if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2223 int underlinePos, strikeoutPos;
2224 int underlineWidth, strikeoutWidth;
2225 UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2226 OUTLINETEXTMETRICW* otm = NULL;
2228 if(!size)
2230 underlinePos = 0;
2231 underlineWidth = tm.tmAscent / 20 + 1;
2232 strikeoutPos = tm.tmAscent / 2;
2233 strikeoutWidth = underlineWidth;
2235 else
2237 otm = HeapAlloc(GetProcessHeap(), 0, size);
2238 GetOutlineTextMetricsW(hdc, size, otm);
2239 underlinePos = otm->otmsUnderscorePosition;
2240 underlineWidth = otm->otmsUnderscoreSize;
2241 strikeoutPos = otm->otmsStrikeoutPosition;
2242 strikeoutWidth = otm->otmsStrikeoutSize;
2243 HeapFree(GetProcessHeap(), 0, otm);
2246 if (PATH_IsPathOpen(dc->path))
2248 POINT pts[5];
2249 HPEN hpen;
2250 HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2252 hbrush = SelectObject(hdc, hbrush);
2253 hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2255 if (lf.lfUnderline)
2257 pts[0].x = x - underlinePos * sinEsc;
2258 pts[0].y = y - underlinePos * cosEsc;
2259 pts[1].x = x + xwidth - underlinePos * sinEsc;
2260 pts[1].y = y - ywidth - underlinePos * cosEsc;
2261 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2262 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2263 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2264 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2265 pts[4].x = pts[0].x;
2266 pts[4].y = pts[0].y;
2267 DPtoLP(hdc, pts, 5);
2268 Polygon(hdc, pts, 5);
2271 if (lf.lfStrikeOut)
2273 pts[0].x = x - strikeoutPos * sinEsc;
2274 pts[0].y = y - strikeoutPos * cosEsc;
2275 pts[1].x = x + xwidth - strikeoutPos * sinEsc;
2276 pts[1].y = y - ywidth - strikeoutPos * cosEsc;
2277 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2278 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2279 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2280 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2281 pts[4].x = pts[0].x;
2282 pts[4].y = pts[0].y;
2283 DPtoLP(hdc, pts, 5);
2284 Polygon(hdc, pts, 5);
2287 SelectObject(hdc, hpen);
2288 hbrush = SelectObject(hdc, hbrush);
2289 DeleteObject(hbrush);
2291 else
2293 POINT pts[2], oldpt;
2294 HPEN hpen;
2296 if (lf.lfUnderline)
2298 hpen = CreatePen(PS_SOLID, underlineWidth, GetTextColor(hdc));
2299 hpen = SelectObject(hdc, hpen);
2300 pts[0].x = x;
2301 pts[0].y = y;
2302 pts[1].x = x + xwidth;
2303 pts[1].y = y - ywidth;
2304 DPtoLP(hdc, pts, 2);
2305 MoveToEx(hdc, pts[0].x - underlinePos * sinEsc, pts[0].y - underlinePos * cosEsc, &oldpt);
2306 LineTo(hdc, pts[1].x - underlinePos * sinEsc, pts[1].y - underlinePos * cosEsc);
2307 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2308 DeleteObject(SelectObject(hdc, hpen));
2311 if (lf.lfStrikeOut)
2313 hpen = CreatePen(PS_SOLID, strikeoutWidth, GetTextColor(hdc));
2314 hpen = SelectObject(hdc, hpen);
2315 pts[0].x = x;
2316 pts[0].y = y;
2317 pts[1].x = x + xwidth;
2318 pts[1].y = y - ywidth;
2319 DPtoLP(hdc, pts, 2);
2320 MoveToEx(hdc, pts[0].x - strikeoutPos * sinEsc, pts[0].y - strikeoutPos * cosEsc, &oldpt);
2321 LineTo(hdc, pts[1].x - strikeoutPos * sinEsc, pts[1].y - strikeoutPos * cosEsc);
2322 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2323 DeleteObject(SelectObject(hdc, hpen));
2328 return ret;
2332 /***********************************************************************
2333 * TextOutA (GDI32.@)
2335 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2337 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2341 /***********************************************************************
2342 * TextOutW (GDI32.@)
2344 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2346 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2350 /***********************************************************************
2351 * PolyTextOutA (GDI32.@)
2353 * See PolyTextOutW.
2355 BOOL WINAPI PolyTextOutA ( HDC hdc, /* [in] Handle to device context */
2356 PPOLYTEXTA pptxt, /* [in] Array of strings */
2357 INT cStrings ) /* [in] Number of strings in array */
2359 for (; cStrings>0; cStrings--, pptxt++)
2360 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2361 return FALSE;
2362 return TRUE;
2367 /***********************************************************************
2368 * PolyTextOutW (GDI32.@)
2370 * Draw several Strings
2372 * RETURNS
2373 * TRUE: Success.
2374 * FALSE: Failure.
2376 BOOL WINAPI PolyTextOutW ( HDC hdc, /* [in] Handle to device context */
2377 PPOLYTEXTW pptxt, /* [in] Array of strings */
2378 INT cStrings ) /* [in] Number of strings in array */
2380 for (; cStrings>0; cStrings--, pptxt++)
2381 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2382 return FALSE;
2383 return TRUE;
2387 /* FIXME: all following APIs ******************************************/
2390 /***********************************************************************
2391 * SetMapperFlags (GDI32.@)
2393 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
2395 DC *dc = DC_GetDCPtr( hDC );
2396 DWORD ret = 0;
2397 if(!dc) return 0;
2398 if(dc->funcs->pSetMapperFlags)
2400 ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
2401 /* FIXME: ret is just a success flag, we should return a proper value */
2403 else
2404 FIXME("(%p, 0x%08x): stub - harmless\n", hDC, dwFlag);
2405 GDI_ReleaseObj( hDC );
2406 return ret;
2409 /***********************************************************************
2410 * GetAspectRatioFilterEx (GDI.486)
2412 BOOL16 WINAPI GetAspectRatioFilterEx16( HDC16 hdc, LPSIZE16 pAspectRatio )
2414 FIXME("(%04x, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2415 return FALSE;
2418 /***********************************************************************
2419 * GetAspectRatioFilterEx (GDI32.@)
2421 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2423 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2424 return FALSE;
2428 /***********************************************************************
2429 * GetCharABCWidthsA (GDI32.@)
2431 * See GetCharABCWidthsW.
2433 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2434 LPABC abc )
2436 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
2437 LPSTR str;
2438 LPWSTR wstr;
2439 BOOL ret = TRUE;
2441 if(count <= 0) return FALSE;
2443 str = HeapAlloc(GetProcessHeap(), 0, count);
2444 for(i = 0; i < count; i++)
2445 str[i] = (BYTE)(firstChar + i);
2447 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
2449 for(i = 0; i < wlen; i++)
2451 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2453 ret = FALSE;
2454 break;
2456 abc++;
2459 HeapFree(GetProcessHeap(), 0, str);
2460 HeapFree(GetProcessHeap(), 0, wstr);
2462 return ret;
2466 /******************************************************************************
2467 * GetCharABCWidthsW [GDI32.@]
2469 * Retrieves widths of characters in range.
2471 * PARAMS
2472 * hdc [I] Handle of device context
2473 * firstChar [I] First character in range to query
2474 * lastChar [I] Last character in range to query
2475 * abc [O] Address of character-width structure
2477 * NOTES
2478 * Only works with TrueType fonts
2480 * RETURNS
2481 * Success: TRUE
2482 * Failure: FALSE
2484 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2485 LPABC abc )
2487 DC *dc = DC_GetDCPtr(hdc);
2488 unsigned int i;
2489 BOOL ret = FALSE;
2491 if (!dc) return FALSE;
2493 if(dc->gdiFont)
2494 ret = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
2495 else
2496 FIXME(": stub\n");
2498 if (ret)
2500 /* convert device units to logical */
2501 for( i = firstChar; i <= lastChar; i++, abc++ ) {
2502 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2503 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2504 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2506 ret = TRUE;
2509 GDI_ReleaseObj(hdc);
2510 return ret;
2514 /******************************************************************************
2515 * GetCharABCWidthsI [GDI32.@]
2517 * Retrieves widths of characters in range.
2519 * PARAMS
2520 * hdc [I] Handle of device context
2521 * firstChar [I] First glyphs in range to query
2522 * count [I] Last glyphs in range to query
2523 * pgi [i] Array of glyphs to query
2524 * abc [O] Address of character-width structure
2526 * NOTES
2527 * Only works with TrueType fonts
2529 * RETURNS
2530 * Success: TRUE
2531 * Failure: FALSE
2533 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2534 LPWORD pgi, LPABC abc)
2536 DC *dc = DC_GetDCPtr(hdc);
2537 unsigned int i;
2538 BOOL ret = FALSE;
2540 if (!dc) return FALSE;
2542 if(dc->gdiFont)
2543 ret = WineEngGetCharABCWidthsI( dc->gdiFont, firstChar, count, pgi, abc );
2544 else
2545 FIXME(": stub\n");
2547 if (ret)
2549 /* convert device units to logical */
2550 for( i = 0; i < count; i++, abc++ ) {
2551 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2552 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2553 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2555 ret = TRUE;
2558 GDI_ReleaseObj(hdc);
2559 return ret;
2563 /***********************************************************************
2564 * GetGlyphOutlineA (GDI32.@)
2566 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2567 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2568 LPVOID lpBuffer, const MAT2 *lpmat2 )
2570 LPWSTR p = NULL;
2571 DWORD ret;
2572 UINT c;
2574 if(!(fuFormat & GGO_GLYPH_INDEX)) {
2575 int len;
2576 char mbchs[2];
2577 if(uChar > 0xff) { /* but, 2 bytes character only */
2578 len = 2;
2579 mbchs[0] = (uChar & 0xff00) >> 8;
2580 mbchs[1] = (uChar & 0xff);
2581 } else {
2582 len = 1;
2583 mbchs[0] = (uChar & 0xff);
2585 p = FONT_mbtowc(hdc, mbchs, len, NULL, NULL);
2586 c = p[0];
2587 } else
2588 c = uChar;
2589 ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
2590 lpmat2);
2591 HeapFree(GetProcessHeap(), 0, p);
2592 return ret;
2595 /***********************************************************************
2596 * GetGlyphOutlineW (GDI32.@)
2598 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2599 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2600 LPVOID lpBuffer, const MAT2 *lpmat2 )
2602 DC *dc = DC_GetDCPtr(hdc);
2603 DWORD ret;
2605 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2606 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2608 if(!dc) return GDI_ERROR;
2610 if(dc->gdiFont)
2611 ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
2612 cbBuffer, lpBuffer, lpmat2);
2613 else
2614 ret = GDI_ERROR;
2616 GDI_ReleaseObj(hdc);
2617 return ret;
2621 /***********************************************************************
2622 * CreateScalableFontResourceA (GDI32.@)
2624 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2625 LPCSTR lpszResourceFile,
2626 LPCSTR lpszFontFile,
2627 LPCSTR lpszCurrentPath )
2629 HANDLE f;
2631 /* fHidden=1 - only visible for the calling app, read-only, not
2632 * enumbered with EnumFonts/EnumFontFamilies
2633 * lpszCurrentPath can be NULL
2635 FIXME("(%d,%s,%s,%s): stub\n",
2636 fHidden, debugstr_a(lpszResourceFile), debugstr_a(lpszFontFile),
2637 debugstr_a(lpszCurrentPath) );
2639 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2640 if ((f = CreateFileA(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2641 CloseHandle(f);
2642 SetLastError(ERROR_FILE_EXISTS);
2643 return FALSE;
2645 return FALSE; /* create failed */
2648 /***********************************************************************
2649 * CreateScalableFontResourceW (GDI32.@)
2651 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2652 LPCWSTR lpszResourceFile,
2653 LPCWSTR lpszFontFile,
2654 LPCWSTR lpszCurrentPath )
2656 FIXME("(%d,%p,%p,%p): stub\n",
2657 fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
2658 return FALSE; /* create failed */
2661 /*************************************************************************
2662 * GetKerningPairsA (GDI32.@)
2664 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2665 LPKERNINGPAIR kern_pairA )
2667 INT charset;
2668 CHARSETINFO csi;
2669 CPINFO cpi;
2670 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2671 KERNINGPAIR *kern_pairW;
2673 if (!cPairs && kern_pairA)
2675 SetLastError(ERROR_INVALID_PARAMETER);
2676 return 0;
2679 charset = GetTextCharset(hDC);
2680 if (!TranslateCharsetInfo((DWORD *)charset, &csi, TCI_SRCCHARSET))
2682 FIXME("Can't find codepage for charset %d\n", charset);
2683 return 0;
2685 if (!GetCPInfo(csi.ciACP, &cpi))
2687 FIXME("Can't find codepage %u info\n", csi.ciACP);
2688 return 0;
2690 TRACE("charset %d => codepage %u\n", charset, csi.ciACP);
2692 total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2693 if (!total_kern_pairs) return 0;
2695 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2696 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2698 for (i = 0; i < total_kern_pairs; i++)
2700 char first, second;
2702 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2703 continue;
2705 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2706 continue;
2708 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2709 continue;
2711 if (kern_pairA)
2713 if (kern_pairs_copied >= cPairs) break;
2715 kern_pairA->wFirst = (BYTE)first;
2716 kern_pairA->wSecond = (BYTE)second;
2717 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2718 kern_pairA++;
2720 kern_pairs_copied++;
2723 HeapFree(GetProcessHeap(), 0, kern_pairW);
2725 return kern_pairs_copied;
2728 /*************************************************************************
2729 * GetKerningPairsW (GDI32.@)
2731 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2732 LPKERNINGPAIR lpKerningPairs )
2734 DC *dc;
2735 DWORD ret = 0;
2737 TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2739 if (!cPairs && lpKerningPairs)
2741 SetLastError(ERROR_INVALID_PARAMETER);
2742 return 0;
2745 dc = DC_GetDCPtr(hDC);
2746 if (!dc) return 0;
2748 if (dc->gdiFont)
2749 ret = WineEngGetKerningPairs(dc->gdiFont, cPairs, lpKerningPairs);
2751 GDI_ReleaseObj(hDC);
2752 return ret;
2755 /*************************************************************************
2756 * TranslateCharsetInfo [GDI32.@]
2758 * Fills a CHARSETINFO structure for a character set, code page, or
2759 * font. This allows making the correspondance between different labelings
2760 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2761 * of the same encoding.
2763 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2764 * only one codepage should be set in *lpSrc.
2766 * RETURNS
2767 * TRUE on success, FALSE on failure.
2770 BOOL WINAPI TranslateCharsetInfo(
2771 LPDWORD lpSrc, /* [in]
2772 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2773 if flags == TCI_SRCCHARSET: a character set value
2774 if flags == TCI_SRCCODEPAGE: a code page value
2776 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2777 DWORD flags /* [in] determines interpretation of lpSrc */)
2779 int index = 0;
2780 switch (flags) {
2781 case TCI_SRCFONTSIG:
2782 while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
2783 break;
2784 case TCI_SRCCODEPAGE:
2785 while ((UINT) (lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
2786 break;
2787 case TCI_SRCCHARSET:
2788 while ((UINT) (lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
2789 break;
2790 default:
2791 return FALSE;
2793 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2794 memcpy(lpCs, &FONT_tci[index], sizeof(CHARSETINFO));
2795 return TRUE;
2798 /*************************************************************************
2799 * GetFontLanguageInfo (GDI32.@)
2801 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2803 FONTSIGNATURE fontsig;
2804 static const DWORD GCP_DBCS_MASK=0x003F0000,
2805 GCP_DIACRITIC_MASK=0x00000000,
2806 FLI_GLYPHS_MASK=0x00000000,
2807 GCP_GLYPHSHAPE_MASK=0x00000040,
2808 GCP_KASHIDA_MASK=0x00000000,
2809 GCP_LIGATE_MASK=0x00000000,
2810 GCP_USEKERNING_MASK=0x00000000,
2811 GCP_REORDER_MASK=0x00000060;
2813 DWORD result=0;
2815 GetTextCharsetInfo( hdc, &fontsig, 0 );
2816 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2818 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2819 result|=GCP_DBCS;
2821 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2822 result|=GCP_DIACRITIC;
2824 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2825 result|=FLI_GLYPHS;
2827 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2828 result|=GCP_GLYPHSHAPE;
2830 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2831 result|=GCP_KASHIDA;
2833 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2834 result|=GCP_LIGATE;
2836 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2837 result|=GCP_USEKERNING;
2839 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2840 if( GetTextAlign( hdc) & TA_RTLREADING )
2841 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2842 result|=GCP_REORDER;
2844 return result;
2848 /*************************************************************************
2849 * GetFontData [GDI32.@]
2851 * Retrieve data for TrueType font.
2853 * RETURNS
2855 * success: Number of bytes returned
2856 * failure: GDI_ERROR
2858 * NOTES
2860 * Calls SetLastError()
2863 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2864 LPVOID buffer, DWORD length)
2866 DC *dc = DC_GetDCPtr(hdc);
2867 DWORD ret = GDI_ERROR;
2869 if(!dc) return GDI_ERROR;
2871 if(dc->gdiFont)
2872 ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2874 GDI_ReleaseObj(hdc);
2875 return ret;
2878 /*************************************************************************
2879 * GetGlyphIndicesA [GDI32.@]
2881 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2882 LPWORD pgi, DWORD flags)
2884 DWORD ret;
2885 WCHAR *lpstrW;
2886 INT countW;
2888 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2889 hdc, debugstr_an(lpstr, count), count, pgi, flags);
2891 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2892 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2893 HeapFree(GetProcessHeap(), 0, lpstrW);
2895 return ret;
2898 /*************************************************************************
2899 * GetGlyphIndicesW [GDI32.@]
2901 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2902 LPWORD pgi, DWORD flags)
2904 DC *dc = DC_GetDCPtr(hdc);
2905 DWORD ret = GDI_ERROR;
2907 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2908 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2910 if(!dc) return GDI_ERROR;
2912 if(dc->gdiFont)
2913 ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2915 GDI_ReleaseObj(hdc);
2916 return ret;
2919 /*************************************************************************
2920 * GetCharacterPlacementA [GDI32.@]
2922 * See GetCharacterPlacementW.
2924 * NOTES:
2925 * the web browser control of ie4 calls this with dwFlags=0
2927 DWORD WINAPI
2928 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2929 INT nMaxExtent, GCP_RESULTSA *lpResults,
2930 DWORD dwFlags)
2932 WCHAR *lpStringW;
2933 INT uCountW;
2934 GCP_RESULTSW resultsW;
2935 DWORD ret;
2936 UINT font_cp;
2938 TRACE("%s, %d, %d, 0x%08x\n",
2939 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2941 /* both structs are equal in size */
2942 memcpy(&resultsW, lpResults, sizeof(resultsW));
2944 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2945 if(lpResults->lpOutString)
2946 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2948 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2950 lpResults->nGlyphs = resultsW.nGlyphs;
2951 lpResults->nMaxFit = resultsW.nMaxFit;
2953 if(lpResults->lpOutString) {
2954 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2955 lpResults->lpOutString, uCount, NULL, NULL );
2958 HeapFree(GetProcessHeap(), 0, lpStringW);
2959 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2961 return ret;
2964 /*************************************************************************
2965 * GetCharacterPlacementW [GDI32.@]
2967 * Retrieve information about a string. This includes the width, reordering,
2968 * Glyphing and so on.
2970 * RETURNS
2972 * The width and height of the string if successful, 0 if failed.
2974 * BUGS
2976 * All flags except GCP_REORDER are not yet implemented.
2977 * Reordering is not 100% complient to the Windows BiDi method.
2978 * Caret positioning is not yet implemented for BiDi.
2979 * Classes are not yet implemented.
2982 DWORD WINAPI
2983 GetCharacterPlacementW(
2984 HDC hdc, /* [in] Device context for which the rendering is to be done */
2985 LPCWSTR lpString, /* [in] The string for which information is to be returned */
2986 INT uCount, /* [in] Number of WORDS in string. */
2987 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
2988 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2989 DWORD dwFlags /* [in] Flags specifying how to process the string */
2992 DWORD ret=0;
2993 SIZE size;
2994 UINT i, nSet;
2996 TRACE("%s, %d, %d, 0x%08x\n",
2997 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2999 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
3000 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
3001 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
3002 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
3003 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
3005 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08x ignored\n", dwFlags);
3006 if(lpResults->lpClass) FIXME("classes not implemented\n");
3007 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
3008 FIXME("Caret positions for complex scripts not implemented\n");
3010 nSet = (UINT)uCount;
3011 if(nSet > lpResults->nGlyphs)
3012 nSet = lpResults->nGlyphs;
3014 /* return number of initialized fields */
3015 lpResults->nGlyphs = nSet;
3017 if((dwFlags&GCP_REORDER)==0 || !BidiAvail)
3019 /* Treat the case where no special handling was requested in a fastpath way */
3020 /* copy will do if the GCP_REORDER flag is not set */
3021 if(lpResults->lpOutString)
3022 memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
3024 if(lpResults->lpOrder)
3026 for(i = 0; i < nSet; i++)
3027 lpResults->lpOrder[i] = i;
3029 } else
3031 BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
3032 nSet, lpResults->lpOrder );
3035 /* FIXME: Will use the placement chars */
3036 if (lpResults->lpDx)
3038 int c;
3039 for (i = 0; i < nSet; i++)
3041 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
3042 lpResults->lpDx[i]= c;
3046 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
3048 int pos = 0;
3050 lpResults->lpCaretPos[0] = 0;
3051 for (i = 1; i < nSet; i++)
3052 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
3053 lpResults->lpCaretPos[i] = (pos += size.cx);
3056 if(lpResults->lpGlyphs)
3057 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
3059 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
3060 ret = MAKELONG(size.cx, size.cy);
3062 return ret;
3065 /*************************************************************************
3066 * GetCharABCWidthsFloatA [GDI32.@]
3068 * See GetCharABCWidthsFloatW.
3070 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3072 INT i, wlen, count = (INT)(last - first + 1);
3073 LPSTR str;
3074 LPWSTR wstr;
3075 BOOL ret = TRUE;
3077 if (count <= 0) return FALSE;
3079 str = HeapAlloc(GetProcessHeap(), 0, count);
3081 for(i = 0; i < count; i++)
3082 str[i] = (BYTE)(first + i);
3084 wstr = FONT_mbtowc( hdc, str, count, &wlen, NULL );
3086 for (i = 0; i < wlen; i++)
3088 if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
3090 ret = FALSE;
3091 break;
3093 abcf++;
3096 HeapFree( GetProcessHeap(), 0, str );
3097 HeapFree( GetProcessHeap(), 0, wstr );
3099 return ret;
3102 /*************************************************************************
3103 * GetCharABCWidthsFloatW [GDI32.@]
3105 * Retrieves widths of a range of characters.
3107 * PARAMS
3108 * hdc [I] Handle to device context.
3109 * first [I] First character in range to query.
3110 * last [I] Last character in range to query.
3111 * abcf [O] Array of LPABCFLOAT structures.
3113 * RETURNS
3114 * Success: TRUE
3115 * Failure: FALSE
3117 * BUGS
3118 * Only works with TrueType fonts. It also doesn't return real
3119 * floats but converted integers because it's implemented on
3120 * top of GetCharABCWidthsW.
3122 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3124 ABC *abc;
3125 unsigned int i, size = sizeof(ABC) * (last - first + 1);
3126 BOOL ret;
3128 TRACE("%p, %d, %d, %p - partial stub\n", hdc, first, last, abcf);
3130 abc = HeapAlloc( GetProcessHeap(), 0, size );
3131 if (!abc) return FALSE;
3133 ret = GetCharABCWidthsW( hdc, first, last, abc );
3134 if (ret)
3136 for (i = first; i <= last; i++, abc++, abcf++)
3138 abcf->abcfA = abc->abcA;
3139 abcf->abcfB = abc->abcB;
3140 abcf->abcfC = abc->abcC;
3143 HeapFree( GetProcessHeap(), 0, abc );
3144 return ret;
3147 /*************************************************************************
3148 * GetCharWidthFloatA [GDI32.@]
3150 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
3151 UINT iLastChar, PFLOAT pxBuffer)
3153 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3154 return 0;
3157 /*************************************************************************
3158 * GetCharWidthFloatW [GDI32.@]
3160 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
3161 UINT iLastChar, PFLOAT pxBuffer)
3163 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3164 return 0;
3168 /***********************************************************************
3170 * Font Resource API *
3172 ***********************************************************************/
3174 /***********************************************************************
3175 * AddFontResourceA (GDI32.@)
3177 INT WINAPI AddFontResourceA( LPCSTR str )
3179 return AddFontResourceExA( str, 0, NULL);
3182 /***********************************************************************
3183 * AddFontResourceW (GDI32.@)
3185 INT WINAPI AddFontResourceW( LPCWSTR str )
3187 return AddFontResourceExW(str, 0, NULL);
3191 /***********************************************************************
3192 * AddFontResourceExA (GDI32.@)
3194 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3196 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3197 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3198 INT ret;
3200 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3201 ret = AddFontResourceExW(strW, fl, pdv);
3202 HeapFree(GetProcessHeap(), 0, strW);
3203 return ret;
3206 /***********************************************************************
3207 * AddFontResourceExW (GDI32.@)
3209 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3211 return WineEngAddFontResourceEx(str, fl, pdv);
3214 /***********************************************************************
3215 * RemoveFontResourceA (GDI32.@)
3217 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3219 return RemoveFontResourceExA(str, 0, 0);
3222 /***********************************************************************
3223 * RemoveFontResourceW (GDI32.@)
3225 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3227 return RemoveFontResourceExW(str, 0, 0);
3230 /***********************************************************************
3231 * AddFontMemResourceEx (GDI32.@)
3233 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3235 FIXME("(%p,%08x,%p,%p): stub\n", pbFont, cbFont, pdv, pcFonts);
3236 return NULL;
3239 /***********************************************************************
3240 * RemoveFontResourceExA (GDI32.@)
3242 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3244 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3245 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3246 INT ret;
3248 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3249 ret = RemoveFontResourceExW(strW, fl, pdv);
3250 HeapFree(GetProcessHeap(), 0, strW);
3251 return ret;
3254 /***********************************************************************
3255 * RemoveFontResourceExW (GDI32.@)
3257 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3259 return WineEngRemoveFontResourceEx(str, fl, pdv);
3262 /***********************************************************************
3263 * GetTextCharset (GDI32.@)
3265 UINT WINAPI GetTextCharset(HDC hdc)
3267 /* MSDN docs say this is equivalent */
3268 return GetTextCharsetInfo(hdc, NULL, 0);
3271 /***********************************************************************
3272 * GetTextCharsetInfo (GDI32.@)
3274 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3276 UINT ret = DEFAULT_CHARSET;
3277 DC *dc = DC_GetDCPtr(hdc);
3279 if (dc)
3281 if (dc->gdiFont)
3282 ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
3284 GDI_ReleaseObj(hdc);
3287 if (ret == DEFAULT_CHARSET && fs)
3288 memset(fs, 0, sizeof(FONTSIGNATURE));
3289 return ret;
3292 /***********************************************************************
3293 * GdiGetCharDimensions (GDI32.@)
3295 * Gets the average width of the characters in the English alphabet.
3297 * PARAMS
3298 * hdc [I] Handle to the device context to measure on.
3299 * lptm [O] Pointer to memory to store the text metrics into.
3300 * height [O] On exit, the maximum height of characters in the English alphabet.
3302 * RETURNS
3303 * The average width of characters in the English alphabet.
3305 * NOTES
3306 * This function is used by the dialog manager to get the size of a dialog
3307 * unit. It should also be used by other pieces of code that need to know
3308 * the size of a dialog unit in logical units without having access to the
3309 * window handle of the dialog.
3310 * Windows caches the font metrics from this function, but we don't and
3311 * there doesn't appear to be an immediate advantage to do so.
3313 * SEE ALSO
3314 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3316 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3318 SIZE sz;
3319 static const WCHAR alphabet[] = {
3320 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3321 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3322 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3324 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3326 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3328 if (height) *height = sz.cy;
3329 return (sz.cx / 26 + 1) / 2;
3332 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3334 FIXME("(%d): stub\n", fEnableEUDC);
3335 return FALSE;
3338 /***********************************************************************
3339 * GetCharWidthI (GDI32.@)
3341 * Retrieve widths of characters.
3343 * PARAMS
3344 * hdc [I] Handle to a device context.
3345 * first [I] First glyph in range to query.
3346 * count [I] Number of glyph indices to query.
3347 * glyphs [I] Array of glyphs to query.
3348 * buffer [O] Buffer to receive character widths.
3350 * NOTES
3351 * Only works with TrueType fonts.
3353 * RETURNS
3354 * Success: TRUE
3355 * Failure: FALSE
3357 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3359 ABC *abc;
3360 unsigned int i;
3362 TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3364 if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3365 return FALSE;
3367 if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3369 HeapFree(GetProcessHeap(), 0, abc);
3370 return FALSE;
3373 for (i = 0; i < count; i++)
3374 buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3376 HeapFree(GetProcessHeap(), 0, abc);
3377 return TRUE;
3380 /***********************************************************************
3381 * GetFontUnicodeRanges (GDI32.@)
3383 * Retrieve a list of supported Unicode characters in a font.
3385 * PARAMS
3386 * hdc [I] Handle to a device context.
3387 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3389 * RETURNS
3390 * Success: Number of bytes written to the buffer pointed to by lpgs.
3391 * Failure: 0
3394 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3396 return WineEngGetFontUnicodeRanges(hdc, lpgs);