crypt32: Test and implement getting the encoded signers from an encoded signed message.
[wine/multimedia.git] / dlls / gdi32 / font.c
blobfa9954db5cb6f72e1f0d197669bd1cbb3edabb84
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(ULongToPtr(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 (dc->hFont != handle || dc->gdiFont == NULL)
597 if(GetDeviceCaps(dc->hSelf, TEXTCAPS) & TC_VA_ABLE)
598 dc->gdiFont = WineEngCreateFontInstance(dc, handle);
601 if (dc->funcs->pSelectFont) ret = dc->funcs->pSelectFont( dc->physDev, handle, dc->gdiFont );
603 if (ret && dc->gdiFont) dc->gdiFont = 0;
605 if (ret == HGDI_ERROR)
606 ret = 0; /* SelectObject returns 0 on error */
607 else
609 ret = dc->hFont;
610 dc->hFont = handle;
612 GDI_ReleaseObj( hdc );
613 return ret;
617 /***********************************************************************
618 * FONT_GetObject16
620 static INT FONT_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
622 FONTOBJ *font = obj;
623 LOGFONT16 lf16;
625 FONT_LogFontWTo16( &font->logfont, &lf16 );
627 if (count > sizeof(LOGFONT16)) count = sizeof(LOGFONT16);
628 memcpy( buffer, &lf16, count );
629 return count;
632 /***********************************************************************
633 * FONT_GetObjectA
635 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
637 FONTOBJ *font = obj;
638 LOGFONTA lfA;
640 if(!buffer)
641 return sizeof(lfA);
642 FONT_LogFontWToA( &font->logfont, &lfA );
644 if (count > sizeof(lfA)) count = sizeof(lfA);
645 memcpy( buffer, &lfA, count );
646 return count;
649 /***********************************************************************
650 * FONT_GetObjectW
652 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
654 FONTOBJ *font = obj;
655 if(!buffer)
656 return sizeof(LOGFONTW);
657 if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
658 memcpy( buffer, &font->logfont, count );
659 return count;
663 /***********************************************************************
664 * FONT_DeleteObject
666 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj )
668 WineEngDestroyFontInstance( handle );
669 return GDI_FreeObject( handle, obj );
673 /***********************************************************************
674 * FONT_EnumInstance16
676 * Called by the device driver layer to pass font info
677 * down to the application.
679 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
680 * We have to use other types because of the FONTENUMPROCW definition.
682 static INT CALLBACK FONT_EnumInstance16( const LOGFONTW *plf, const TEXTMETRICW *ptm,
683 DWORD fType, LPARAM lp )
685 fontEnum16 *pfe = (fontEnum16*)lp;
686 INT ret = 1;
687 DC *dc;
689 if( pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
690 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet )
692 WORD args[7];
693 DWORD result;
695 FONT_EnumLogFontExWTo16((const ENUMLOGFONTEXW *)plf, pfe->lpLogFont);
696 FONT_NewTextMetricExWTo16((const NEWTEXTMETRICEXW *)ptm, pfe->lpTextMetric);
697 pfe->dwFlags |= ENUM_CALLED;
698 GDI_ReleaseObj( pfe->hdc ); /* release the GDI lock */
700 args[6] = SELECTOROF(pfe->segLogFont);
701 args[5] = OFFSETOF(pfe->segLogFont);
702 args[4] = SELECTOROF(pfe->segTextMetric);
703 args[3] = OFFSETOF(pfe->segTextMetric);
704 args[2] = fType;
705 args[1] = HIWORD(pfe->lpData);
706 args[0] = LOWORD(pfe->lpData);
707 WOWCallback16Ex( (DWORD)pfe->lpEnumFunc, WCB16_PASCAL, sizeof(args), args, &result );
708 ret = LOWORD(result);
710 /* get the lock again and make sure the DC is still valid */
711 dc = DC_GetDCPtr( pfe->hdc );
712 if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
714 if (dc) GDI_ReleaseObj( pfe->hdc );
715 pfe->hdc = 0; /* make sure we don't try to release it later on */
716 ret = 0;
719 return ret;
722 /***********************************************************************
723 * FONT_EnumInstance
725 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
726 * We have to use other types because of the FONTENUMPROCW definition.
728 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
729 DWORD fType, LPARAM lp )
731 fontEnum32 *pfe = (fontEnum32*)lp;
732 INT ret = 1;
733 DC *dc;
735 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
736 if((pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
737 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
738 (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
740 /* convert font metrics */
741 ENUMLOGFONTEXA logfont;
742 NEWTEXTMETRICEXA tmA;
744 pfe->dwFlags |= ENUM_CALLED;
745 if (!(pfe->dwFlags & ENUM_UNICODE))
747 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
748 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
749 plf = (LOGFONTW *)&logfont.elfLogFont;
750 ptm = (TEXTMETRICW *)&tmA;
752 GDI_ReleaseObj( pfe->hdc ); /* release the GDI lock */
754 ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
756 /* get the lock again and make sure the DC is still valid */
757 dc = DC_GetDCPtr( pfe->hdc );
758 if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
760 if (dc) GDI_ReleaseObj( pfe->hdc );
761 pfe->hdc = 0; /* make sure we don't try to release it later on */
762 ret = 0;
765 return ret;
768 /***********************************************************************
769 * EnumFontFamiliesEx (GDI.613)
771 INT16 WINAPI EnumFontFamiliesEx16( HDC16 hDC, LPLOGFONT16 plf,
772 FONTENUMPROC16 efproc, LPARAM lParam,
773 DWORD dwFlags)
775 fontEnum16 fe16;
776 INT16 ret = 1, ret2;
777 DC* dc = DC_GetDCPtr( HDC_32(hDC) );
778 NEWTEXTMETRICEX16 tm16;
779 ENUMLOGFONTEX16 lf16;
780 LOGFONTW lfW;
781 BOOL enum_gdi_fonts;
783 if (!dc) return 0;
784 FONT_LogFont16ToW(plf, &lfW);
786 fe16.hdc = HDC_32(hDC);
787 fe16.dc = dc;
788 fe16.physDev = dc->physDev;
789 fe16.lpLogFontParam = plf;
790 fe16.lpEnumFunc = efproc;
791 fe16.lpData = lParam;
792 fe16.lpTextMetric = &tm16;
793 fe16.lpLogFont = &lf16;
794 fe16.segTextMetric = MapLS( &tm16 );
795 fe16.segLogFont = MapLS( &lf16 );
796 fe16.dwFlags = 0;
798 enum_gdi_fonts = GetDeviceCaps(fe16.hdc, TEXTCAPS) & TC_VA_ABLE;
800 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
802 ret = 0;
803 goto done;
806 if (enum_gdi_fonts)
807 ret = WineEngEnumFonts( &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
808 fe16.dwFlags &= ~ENUM_CALLED;
809 if (ret && dc->funcs->pEnumDeviceFonts) {
810 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
811 if(fe16.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
812 ret = ret2;
814 done:
815 UnMapLS( fe16.segTextMetric );
816 UnMapLS( fe16.segLogFont );
817 if (fe16.hdc) GDI_ReleaseObj( fe16.hdc );
818 return ret;
821 /***********************************************************************
822 * FONT_EnumFontFamiliesEx
824 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf,
825 FONTENUMPROCW efproc,
826 LPARAM lParam, DWORD dwUnicode)
828 INT ret = 1, ret2;
829 DC *dc = DC_GetDCPtr( hDC );
830 fontEnum32 fe32;
831 BOOL enum_gdi_fonts;
833 if (!dc) return 0;
835 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName),
836 plf->lfCharSet);
837 fe32.lpLogFontParam = plf;
838 fe32.lpEnumFunc = efproc;
839 fe32.lpData = lParam;
840 fe32.dwFlags = dwUnicode;
841 fe32.hdc = hDC;
842 fe32.dc = dc;
843 fe32.physDev = dc->physDev;
845 enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE;
847 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
849 ret = 0;
850 goto done;
853 if (enum_gdi_fonts)
854 ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
855 fe32.dwFlags &= ~ENUM_CALLED;
856 if (ret && dc->funcs->pEnumDeviceFonts) {
857 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, plf, FONT_EnumInstance, (LPARAM)&fe32 );
858 if(fe32.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
859 ret = ret2;
861 done:
862 if (fe32.hdc) GDI_ReleaseObj( fe32.hdc );
863 return ret;
866 /***********************************************************************
867 * EnumFontFamiliesExW (GDI32.@)
869 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
870 FONTENUMPROCW efproc,
871 LPARAM lParam, DWORD dwFlags )
873 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, ENUM_UNICODE );
876 /***********************************************************************
877 * EnumFontFamiliesExA (GDI32.@)
879 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
880 FONTENUMPROCA efproc,
881 LPARAM lParam, DWORD dwFlags)
883 LOGFONTW lfW;
884 FONT_LogFontAToW( plf, &lfW );
886 return FONT_EnumFontFamiliesEx( hDC, &lfW, (FONTENUMPROCW)efproc, lParam, 0);
889 /***********************************************************************
890 * EnumFontFamilies (GDI.330)
892 INT16 WINAPI EnumFontFamilies16( HDC16 hDC, LPCSTR lpFamily,
893 FONTENUMPROC16 efproc, LPARAM lpData )
895 LOGFONT16 lf;
897 lf.lfCharSet = DEFAULT_CHARSET;
898 if (lpFamily)
900 if (!*lpFamily) return 1;
901 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
903 else lf.lfFaceName[0] = '\0';
905 return EnumFontFamiliesEx16( hDC, &lf, efproc, lpData, 0 );
908 /***********************************************************************
909 * EnumFontFamiliesA (GDI32.@)
911 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
912 FONTENUMPROCA efproc, LPARAM lpData )
914 LOGFONTA lf;
916 lf.lfCharSet = DEFAULT_CHARSET;
917 if (lpFamily)
919 if (!*lpFamily) return 1;
920 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
922 else lf.lfFaceName[0] = lf.lfFaceName[1] = '\0';
924 return EnumFontFamiliesExA( hDC, &lf, efproc, lpData, 0 );
927 /***********************************************************************
928 * EnumFontFamiliesW (GDI32.@)
930 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
931 FONTENUMPROCW efproc, LPARAM lpData )
933 LOGFONTW lf;
935 lf.lfCharSet = DEFAULT_CHARSET;
936 if (lpFamily)
938 if (!*lpFamily) return 1;
939 lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
941 else lf.lfFaceName[0] = 0;
943 return EnumFontFamiliesExW( hDC, &lf, efproc, lpData, 0 );
946 /***********************************************************************
947 * EnumFonts (GDI.70)
949 INT16 WINAPI EnumFonts16( HDC16 hDC, LPCSTR lpName, FONTENUMPROC16 efproc,
950 LPARAM lpData )
952 return EnumFontFamilies16( hDC, lpName, efproc, lpData );
955 /***********************************************************************
956 * EnumFontsA (GDI32.@)
958 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
959 LPARAM lpData )
961 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
964 /***********************************************************************
965 * EnumFontsW (GDI32.@)
967 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
968 LPARAM lpData )
970 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
974 /***********************************************************************
975 * GetTextCharacterExtra (GDI32.@)
977 INT WINAPI GetTextCharacterExtra( HDC hdc )
979 INT ret;
980 DC *dc = DC_GetDCPtr( hdc );
981 if (!dc) return 0x80000000;
982 ret = dc->charExtra;
983 GDI_ReleaseObj( hdc );
984 return ret;
988 /***********************************************************************
989 * SetTextCharacterExtra (GDI32.@)
991 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
993 INT prev;
994 DC * dc = DC_GetDCPtr( hdc );
995 if (!dc) return 0x80000000;
996 if (dc->funcs->pSetTextCharacterExtra)
997 prev = dc->funcs->pSetTextCharacterExtra( dc->physDev, extra );
998 else
1000 prev = dc->charExtra;
1001 dc->charExtra = extra;
1003 GDI_ReleaseObj( hdc );
1004 return prev;
1008 /***********************************************************************
1009 * SetTextJustification (GDI32.@)
1011 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
1013 BOOL ret = TRUE;
1014 DC * dc = DC_GetDCPtr( hdc );
1015 if (!dc) return FALSE;
1016 if (dc->funcs->pSetTextJustification)
1017 ret = dc->funcs->pSetTextJustification( dc->physDev, extra, breaks );
1018 else
1020 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
1021 if (!extra) breaks = 0;
1022 if (breaks)
1024 dc->breakExtra = extra / breaks;
1025 dc->breakRem = extra - (breaks * dc->breakExtra);
1027 else
1029 dc->breakExtra = 0;
1030 dc->breakRem = 0;
1033 GDI_ReleaseObj( hdc );
1034 return ret;
1038 /***********************************************************************
1039 * GetTextFaceA (GDI32.@)
1041 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
1043 INT res = GetTextFaceW(hdc, 0, NULL);
1044 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
1045 GetTextFaceW( hdc, res, nameW );
1047 if (name)
1049 if (count && !WideCharToMultiByte( CP_ACP, 0, nameW, -1, name, count, NULL, NULL))
1050 name[count-1] = 0;
1051 res = strlen(name);
1053 else
1054 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
1055 HeapFree( GetProcessHeap(), 0, nameW );
1056 return res;
1059 /***********************************************************************
1060 * GetTextFaceW (GDI32.@)
1062 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
1064 FONTOBJ *font;
1065 INT ret = 0;
1067 DC * dc = DC_GetDCPtr( hdc );
1068 if (!dc) return 0;
1070 if(dc->gdiFont)
1071 ret = WineEngGetTextFace(dc->gdiFont, count, name);
1072 else if ((font = (FONTOBJ *) GDI_GetObjPtr( dc->hFont, FONT_MAGIC )))
1074 if (name)
1076 lstrcpynW( name, font->logfont.lfFaceName, count );
1077 ret = strlenW(name);
1079 else ret = strlenW(font->logfont.lfFaceName) + 1;
1080 GDI_ReleaseObj( dc->hFont );
1082 GDI_ReleaseObj( hdc );
1083 return ret;
1087 /***********************************************************************
1088 * GetTextExtentPoint32A (GDI32.@)
1090 * See GetTextExtentPoint32W.
1092 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
1093 LPSIZE size )
1095 BOOL ret = FALSE;
1096 INT wlen;
1097 LPWSTR 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 = DC_GetDCPtr( hdc );
1147 if (!dc) return FALSE;
1149 if(dc->gdiFont) {
1150 ret = WineEngGetTextExtentPointI(dc->gdiFont, indices, count, size);
1151 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1152 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1153 size->cx += count * dc->charExtra;
1155 else if(dc->funcs->pGetTextExtentExPoint) {
1156 FIXME("calling GetTextExtentExPoint\n");
1157 ret = dc->funcs->pGetTextExtentExPoint( dc->physDev, (LPCWSTR)indices,
1158 count, 0, NULL, NULL, size );
1161 GDI_ReleaseObj( hdc );
1163 TRACE("(%p %p %d %p): returning %d x %d\n",
1164 hdc, indices, count, size, size->cx, size->cy );
1165 return ret;
1169 /***********************************************************************
1170 * GetTextExtentPointA (GDI32.@)
1172 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
1173 LPSIZE size )
1175 TRACE("not bug compatible.\n");
1176 return GetTextExtentPoint32A( hdc, str, count, size );
1179 /***********************************************************************
1180 * GetTextExtentPointW (GDI32.@)
1182 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1183 LPSIZE size )
1185 TRACE("not bug compatible.\n");
1186 return GetTextExtentPoint32W( hdc, str, count, size );
1190 /***********************************************************************
1191 * GetTextExtentExPointA (GDI32.@)
1193 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1194 INT maxExt, LPINT lpnFit,
1195 LPINT alpDx, LPSIZE size )
1197 BOOL ret;
1198 INT wlen;
1199 INT *walpDx = NULL;
1200 LPWSTR p = NULL;
1202 if (alpDx &&
1203 NULL == (walpDx = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT))))
1204 return FALSE;
1206 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1207 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
1208 if (walpDx)
1210 INT n = lpnFit ? *lpnFit : wlen;
1211 INT i, j;
1212 for(i = 0, j = 0; i < n; i++, j++)
1214 alpDx[j] = walpDx[i];
1215 if (IsDBCSLeadByte(str[j])) alpDx[++j] = walpDx[i];
1218 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1219 HeapFree( GetProcessHeap(), 0, p );
1220 HeapFree( GetProcessHeap(), 0, walpDx );
1221 return ret;
1225 /***********************************************************************
1226 * GetTextExtentExPointW (GDI32.@)
1228 * Return the size of the string as it would be if it was output properly by
1229 * e.g. TextOut.
1231 * This should include
1232 * - Intercharacter spacing
1233 * - justification spacing (not yet done)
1234 * - kerning? see below
1236 * Kerning. Since kerning would be carried out by the rendering code it should
1237 * be done by the driver. However they don't support it yet. Also I am not
1238 * yet persuaded that (certainly under Win95) any kerning is actually done.
1240 * str: According to MSDN this should be null-terminated. That is not true; a
1241 * null will not terminate it early.
1242 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1243 * than count. I have seen it be either the size of the full string or
1244 * 1 less than the size of the full string. I have not seen it bear any
1245 * resemblance to the portion that would fit.
1246 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1247 * trailing intercharacter spacing and any trailing justification.
1249 * FIXME
1250 * Currently we do this by measuring each character etc. We should do it by
1251 * passing the request to the driver, perhaps by extending the
1252 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1253 * thinking about kerning issues and rounding issues in the justification.
1256 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1257 INT maxExt, LPINT lpnFit,
1258 LPINT alpDx, LPSIZE size )
1260 INT nFit = 0;
1261 LPINT dxs = NULL;
1262 DC *dc;
1263 BOOL ret = FALSE;
1264 TEXTMETRICW tm;
1266 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1268 dc = DC_GetDCPtr(hdc);
1269 if (! dc)
1270 return FALSE;
1272 GetTextMetricsW(hdc, &tm);
1274 /* If we need to calculate nFit, then we need the partial extents even if
1275 the user hasn't provided us with an array. */
1276 if (lpnFit)
1278 dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]);
1279 if (! dxs)
1281 GDI_ReleaseObj(hdc);
1282 SetLastError(ERROR_OUTOFMEMORY);
1283 return FALSE;
1286 else
1287 dxs = alpDx;
1289 if (dc->gdiFont)
1290 ret = WineEngGetTextExtentExPoint(dc->gdiFont, str, count,
1291 0, NULL, dxs, size);
1292 else if (dc->funcs->pGetTextExtentExPoint)
1293 ret = dc->funcs->pGetTextExtentExPoint(dc->physDev, str, count,
1294 0, NULL, dxs, size);
1296 /* Perform device size to world size transformations. */
1297 if (ret)
1299 INT extra = dc->charExtra,
1300 breakExtra = dc->breakExtra,
1301 breakRem = dc->breakRem,
1304 if (dxs)
1306 for (i = 0; i < count; ++i)
1308 dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
1309 dxs[i] += (i+1) * extra;
1310 if (count > 1 && (breakExtra || breakRem) && str[i] == tm.tmBreakChar)
1312 dxs[i] += breakExtra;
1313 if (breakRem > 0)
1315 breakRem--;
1316 dxs[i]++;
1319 if (dxs[i] <= maxExt)
1320 ++nFit;
1322 breakRem = dc->breakRem;
1324 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1325 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1327 if (!dxs && count > 1 && (breakExtra || breakRem))
1329 for (i = 0; i < count; i++)
1331 if (str[i] == tm.tmBreakChar)
1333 size->cx += breakExtra;
1334 if (breakRem > 0)
1336 breakRem--;
1337 (size->cx)++;
1344 if (lpnFit)
1345 *lpnFit = nFit;
1347 if (! alpDx)
1348 HeapFree(GetProcessHeap(), 0, dxs);
1350 GDI_ReleaseObj( hdc );
1352 TRACE("returning %d %d x %d\n",nFit,size->cx,size->cy);
1353 return ret;
1356 /***********************************************************************
1357 * GetTextMetricsA (GDI32.@)
1359 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1361 TEXTMETRICW tm32;
1363 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1364 FONT_TextMetricWToA( &tm32, metrics );
1365 return TRUE;
1368 /***********************************************************************
1369 * GetTextMetricsW (GDI32.@)
1371 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1373 BOOL ret = FALSE;
1374 DC * dc = DC_GetDCPtr( hdc );
1375 if (!dc) return FALSE;
1377 if (dc->gdiFont)
1378 ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1379 else if (dc->funcs->pGetTextMetrics)
1380 ret = dc->funcs->pGetTextMetrics( dc->physDev, metrics );
1382 if (ret)
1384 /* device layer returns values in device units
1385 * therefore we have to convert them to logical */
1387 metrics->tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1388 metrics->tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1390 #define WDPTOLP(x) ((x<0)? \
1391 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1392 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1393 #define HDPTOLP(y) ((y<0)? \
1394 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1395 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1397 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1398 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1399 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1400 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1401 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1402 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1403 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1404 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1405 ret = TRUE;
1406 #undef WDPTOLP
1407 #undef HDPTOLP
1408 TRACE("text metrics:\n"
1409 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1410 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1411 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1412 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1413 " PitchAndFamily = %02x\n"
1414 " --------------------\n"
1415 " InternalLeading = %i\n"
1416 " Ascent = %i\n"
1417 " Descent = %i\n"
1418 " Height = %i\n",
1419 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1420 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1421 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1422 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1423 metrics->tmPitchAndFamily,
1424 metrics->tmInternalLeading,
1425 metrics->tmAscent,
1426 metrics->tmDescent,
1427 metrics->tmHeight );
1429 GDI_ReleaseObj( hdc );
1430 return ret;
1434 /***********************************************************************
1435 * GetOutlineTextMetrics [GDI.308] Gets metrics for TrueType fonts.
1437 * NOTES
1438 * lpOTM should be LPOUTLINETEXTMETRIC
1440 * RETURNS
1441 * Success: Non-zero or size of required buffer
1442 * Failure: 0
1444 UINT16 WINAPI GetOutlineTextMetrics16(
1445 HDC16 hdc, /* [in] Handle of device context */
1446 UINT16 cbData, /* [in] Size of metric data array */
1447 LPOUTLINETEXTMETRIC16 lpOTM) /* [out] Address of metric data array */
1449 FIXME("(%04x,%04x,%p): stub\n", hdc,cbData,lpOTM);
1450 return 0;
1454 /***********************************************************************
1455 * GetOutlineTextMetricsA (GDI32.@)
1456 * Gets metrics for TrueType fonts.
1458 * NOTES
1459 * If the supplied buffer isn't big enough Windows partially fills it up to
1460 * its given length and returns that length.
1462 * RETURNS
1463 * Success: Non-zero or size of required buffer
1464 * Failure: 0
1466 UINT WINAPI GetOutlineTextMetricsA(
1467 HDC hdc, /* [in] Handle of device context */
1468 UINT cbData, /* [in] Size of metric data array */
1469 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1471 char buf[512], *ptr;
1472 UINT ret, needed;
1473 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1474 OUTLINETEXTMETRICA *output = lpOTM;
1475 INT left, len;
1477 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1478 return 0;
1479 if(ret > sizeof(buf))
1480 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1481 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1483 needed = sizeof(OUTLINETEXTMETRICA);
1484 if(lpOTMW->otmpFamilyName)
1485 needed += WideCharToMultiByte(CP_ACP, 0,
1486 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1487 NULL, 0, NULL, NULL);
1488 if(lpOTMW->otmpFaceName)
1489 needed += WideCharToMultiByte(CP_ACP, 0,
1490 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1491 NULL, 0, NULL, NULL);
1492 if(lpOTMW->otmpStyleName)
1493 needed += WideCharToMultiByte(CP_ACP, 0,
1494 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1495 NULL, 0, NULL, NULL);
1496 if(lpOTMW->otmpFullName)
1497 needed += WideCharToMultiByte(CP_ACP, 0,
1498 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1499 NULL, 0, NULL, NULL);
1501 if(!lpOTM) {
1502 ret = needed;
1503 goto end;
1506 TRACE("needed = %d\n", needed);
1507 if(needed > cbData)
1508 /* Since the supplied buffer isn't big enough, we'll alloc one
1509 that is and memcpy the first cbData bytes into the lpOTM at
1510 the end. */
1511 output = HeapAlloc(GetProcessHeap(), 0, needed);
1513 ret = output->otmSize = min(needed, cbData);
1514 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1515 output->otmFiller = 0;
1516 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1517 output->otmfsSelection = lpOTMW->otmfsSelection;
1518 output->otmfsType = lpOTMW->otmfsType;
1519 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1520 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1521 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1522 output->otmEMSquare = lpOTMW->otmEMSquare;
1523 output->otmAscent = lpOTMW->otmAscent;
1524 output->otmDescent = lpOTMW->otmDescent;
1525 output->otmLineGap = lpOTMW->otmLineGap;
1526 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1527 output->otmsXHeight = lpOTMW->otmsXHeight;
1528 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1529 output->otmMacAscent = lpOTMW->otmMacAscent;
1530 output->otmMacDescent = lpOTMW->otmMacDescent;
1531 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1532 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1533 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1534 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1535 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1536 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1537 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1538 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1539 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1540 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1543 ptr = (char*)(output + 1);
1544 left = needed - sizeof(*output);
1546 if(lpOTMW->otmpFamilyName) {
1547 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1548 len = WideCharToMultiByte(CP_ACP, 0,
1549 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1550 ptr, left, NULL, NULL);
1551 left -= len;
1552 ptr += len;
1553 } else
1554 output->otmpFamilyName = 0;
1556 if(lpOTMW->otmpFaceName) {
1557 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1558 len = WideCharToMultiByte(CP_ACP, 0,
1559 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1560 ptr, left, NULL, NULL);
1561 left -= len;
1562 ptr += len;
1563 } else
1564 output->otmpFaceName = 0;
1566 if(lpOTMW->otmpStyleName) {
1567 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1568 len = WideCharToMultiByte(CP_ACP, 0,
1569 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1570 ptr, left, NULL, NULL);
1571 left -= len;
1572 ptr += len;
1573 } else
1574 output->otmpStyleName = 0;
1576 if(lpOTMW->otmpFullName) {
1577 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1578 len = WideCharToMultiByte(CP_ACP, 0,
1579 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1580 ptr, left, NULL, NULL);
1581 left -= len;
1582 } else
1583 output->otmpFullName = 0;
1585 assert(left == 0);
1587 if(output != lpOTM) {
1588 memcpy(lpOTM, output, cbData);
1589 HeapFree(GetProcessHeap(), 0, output);
1591 /* check if the string offsets really fit into the provided size */
1592 /* FIXME: should we check string length as well? */
1593 /* make sure that we don't read/write beyond the provided buffer */
1594 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(LPSTR))
1596 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1597 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1600 /* make sure that we don't read/write beyond the provided buffer */
1601 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(LPSTR))
1603 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1604 lpOTM->otmpFaceName = 0; /* doesn't fit */
1607 /* make sure that we don't read/write beyond the provided buffer */
1608 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(LPSTR))
1610 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1611 lpOTM->otmpStyleName = 0; /* doesn't fit */
1614 /* make sure that we don't read/write beyond the provided buffer */
1615 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(LPSTR))
1617 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1618 lpOTM->otmpFullName = 0; /* doesn't fit */
1622 end:
1623 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1624 HeapFree(GetProcessHeap(), 0, lpOTMW);
1626 return ret;
1630 /***********************************************************************
1631 * GetOutlineTextMetricsW [GDI32.@]
1633 UINT WINAPI GetOutlineTextMetricsW(
1634 HDC hdc, /* [in] Handle of device context */
1635 UINT cbData, /* [in] Size of metric data array */
1636 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1638 DC *dc = DC_GetDCPtr( hdc );
1639 OUTLINETEXTMETRICW *output = lpOTM;
1640 UINT ret;
1642 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1643 if(!dc) return 0;
1645 if(dc->gdiFont) {
1646 ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, output);
1647 if(lpOTM && ret) {
1648 if(ret > cbData) {
1649 output = HeapAlloc(GetProcessHeap(), 0, ret);
1650 WineEngGetOutlineTextMetrics(dc->gdiFont, ret, output);
1653 #define WDPTOLP(x) ((x<0)? \
1654 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1655 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1656 #define HDPTOLP(y) ((y<0)? \
1657 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1658 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1660 output->otmTextMetrics.tmHeight = HDPTOLP(output->otmTextMetrics.tmHeight);
1661 output->otmTextMetrics.tmAscent = HDPTOLP(output->otmTextMetrics.tmAscent);
1662 output->otmTextMetrics.tmDescent = HDPTOLP(output->otmTextMetrics.tmDescent);
1663 output->otmTextMetrics.tmInternalLeading = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1664 output->otmTextMetrics.tmExternalLeading = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1665 output->otmTextMetrics.tmAveCharWidth = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1666 output->otmTextMetrics.tmMaxCharWidth = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1667 output->otmTextMetrics.tmOverhang = WDPTOLP(output->otmTextMetrics.tmOverhang);
1668 output->otmAscent = HDPTOLP(output->otmAscent);
1669 output->otmDescent = HDPTOLP(output->otmDescent);
1670 output->otmLineGap = HDPTOLP(output->otmLineGap);
1671 output->otmsCapEmHeight = HDPTOLP(output->otmsCapEmHeight);
1672 output->otmsXHeight = HDPTOLP(output->otmsXHeight);
1673 output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1674 output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1675 output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1676 output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1677 output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1678 output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1679 output->otmMacLineGap = HDPTOLP(output->otmMacLineGap);
1680 output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1681 output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1682 output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1683 output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1684 output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1685 output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1686 output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1687 output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1688 output->otmsStrikeoutSize = HDPTOLP(output->otmsStrikeoutSize);
1689 output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1690 output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1691 output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1692 #undef WDPTOLP
1693 #undef HDPTOLP
1694 if(output != lpOTM) {
1695 memcpy(lpOTM, output, cbData);
1696 HeapFree(GetProcessHeap(), 0, output);
1697 ret = cbData;
1702 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1703 but really this should just be a return 0. */
1705 ret = sizeof(*lpOTM);
1706 if (lpOTM) {
1707 if(cbData < ret)
1708 ret = 0;
1709 else {
1710 memset(lpOTM, 0, ret);
1711 lpOTM->otmSize = sizeof(*lpOTM);
1712 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1714 Further fill of the structure not implemented,
1715 Needs real values for the structure members
1720 GDI_ReleaseObj(hdc);
1721 return ret;
1725 /***********************************************************************
1726 * GetCharWidthW (GDI32.@)
1727 * GetCharWidth32W (GDI32.@)
1729 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1730 LPINT buffer )
1732 UINT i;
1733 BOOL ret = FALSE;
1734 DC * dc = DC_GetDCPtr( hdc );
1735 if (!dc) return FALSE;
1737 if (dc->gdiFont)
1738 ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1739 else if (dc->funcs->pGetCharWidth)
1740 ret = dc->funcs->pGetCharWidth( dc->physDev, firstChar, lastChar, buffer);
1742 if (ret)
1744 /* convert device units to logical */
1745 for( i = firstChar; i <= lastChar; i++, buffer++ )
1746 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1747 ret = TRUE;
1749 GDI_ReleaseObj( hdc );
1750 return ret;
1754 /***********************************************************************
1755 * GetCharWidthA (GDI32.@)
1756 * GetCharWidth32A (GDI32.@)
1758 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1759 LPINT buffer )
1761 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1762 LPSTR str;
1763 LPWSTR wstr;
1764 BOOL ret = TRUE;
1766 if(count <= 0) return FALSE;
1768 str = HeapAlloc(GetProcessHeap(), 0, count);
1769 for(i = 0; i < count; i++)
1770 str[i] = (BYTE)(firstChar + i);
1772 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1774 for(i = 0; i < wlen; i++)
1776 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1778 ret = FALSE;
1779 break;
1781 buffer++;
1784 HeapFree(GetProcessHeap(), 0, str);
1785 HeapFree(GetProcessHeap(), 0, wstr);
1787 return ret;
1791 /***********************************************************************
1792 * ExtTextOutA (GDI32.@)
1794 * See ExtTextOutW.
1796 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1797 const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1799 INT wlen;
1800 UINT codepage;
1801 LPWSTR p;
1802 BOOL ret;
1803 LPINT lpDxW = NULL;
1805 if (flags & ETO_GLYPH_INDEX)
1806 return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
1808 p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
1810 if (lpDx) {
1811 unsigned int i = 0, j = 0;
1813 lpDxW = HeapAlloc( GetProcessHeap(), 0, wlen*sizeof(INT));
1814 while(i < count) {
1815 if(IsDBCSLeadByteEx(codepage, str[i])) {
1816 lpDxW[j++] = lpDx[i] + lpDx[i+1];
1817 i = i + 2;
1818 } else {
1819 lpDxW[j++] = lpDx[i];
1820 i = i + 1;
1825 ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1827 HeapFree( GetProcessHeap(), 0, p );
1828 HeapFree( GetProcessHeap(), 0, lpDxW );
1829 return ret;
1833 /***********************************************************************
1834 * ExtTextOutW (GDI32.@)
1836 * Draws text using the currently selected font, background color, and text color.
1839 * PARAMS
1840 * x,y [I] coordinates of string
1841 * flags [I]
1842 * ETO_GRAYED - undocumented on MSDN
1843 * ETO_OPAQUE - use background color for fill the rectangle
1844 * ETO_CLIPPED - clipping text to the rectangle
1845 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1846 * than encoded characters. Implies ETO_IGNORELANGUAGE
1847 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1848 * Affects BiDi ordering
1849 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1850 * ETO_PDY - unimplemented
1851 * ETO_NUMERICSLATIN - unimplemented always assumed -
1852 * do not translate numbers into locale representations
1853 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1854 * lprect [I] dimensions for clipping or/and opaquing
1855 * str [I] text string
1856 * count [I] number of symbols in string
1857 * lpDx [I] optional parameter with distance between drawing characters
1859 * RETURNS
1860 * Success: TRUE
1861 * Failure: FALSE
1863 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1864 const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1866 BOOL ret = FALSE;
1867 LPWSTR reordered_str = (LPWSTR)str;
1868 WORD *glyphs = NULL;
1869 UINT align = GetTextAlign( hdc );
1870 POINT pt;
1871 TEXTMETRICW tm;
1872 LOGFONTW lf;
1873 double cosEsc, sinEsc;
1874 INT *deltas = NULL, char_extra;
1875 SIZE sz;
1876 RECT rc;
1877 BOOL done_extents = FALSE;
1878 INT width = 0, xwidth = 0, ywidth = 0;
1879 DWORD type;
1880 DC * dc = DC_GetDCUpdate( hdc );
1881 INT breakRem;
1883 if (!dc) return FALSE;
1885 breakRem = dc->breakRem;
1887 if (flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY))
1888 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY unimplemented\n");
1890 if (!dc->funcs->pExtTextOut && !PATH_IsPathOpen(dc->path))
1892 GDI_ReleaseObj( hdc );
1893 return ret;
1896 type = GetObjectType(hdc);
1897 if(type == OBJ_METADC || type == OBJ_ENHMETADC)
1899 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, flags, lprect, str, count, lpDx);
1900 GDI_ReleaseObj( hdc );
1901 return ret;
1904 if (!lprect)
1905 flags &= ~ETO_CLIPPED;
1907 if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && BidiAvail && count > 0 )
1909 reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1911 BIDI_Reorder( str, count, GCP_REORDER,
1912 ((flags&ETO_RTLREADING)!=0 || (GetTextAlign(hdc)&TA_RTLREADING)!=0)?
1913 WINE_GCPW_FORCE_RTL:WINE_GCPW_FORCE_LTR,
1914 reordered_str, count, NULL );
1916 flags |= ETO_IGNORELANGUAGE;
1919 TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc, x, y, flags,
1920 lprect, debugstr_wn(str, count), count, lpDx);
1922 if(flags & ETO_GLYPH_INDEX)
1923 glyphs = reordered_str;
1925 if(lprect)
1926 TRACE("rect: %d,%d - %d,%d\n", lprect->left, lprect->top, lprect->right,
1927 lprect->bottom);
1928 TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
1930 if(align & TA_UPDATECP)
1932 GetCurrentPositionEx( hdc, &pt );
1933 x = pt.x;
1934 y = pt.y;
1937 GetTextMetricsW(hdc, &tm);
1938 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1940 if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
1941 lf.lfEscapement = 0;
1943 if(lf.lfEscapement != 0)
1945 cosEsc = cos(lf.lfEscapement * M_PI / 1800);
1946 sinEsc = sin(lf.lfEscapement * M_PI / 1800);
1948 else
1950 cosEsc = 1;
1951 sinEsc = 0;
1954 if(flags & (ETO_CLIPPED | ETO_OPAQUE))
1956 if(!lprect)
1958 if(flags & ETO_GLYPH_INDEX)
1959 GetTextExtentPointI(hdc, glyphs, count, &sz);
1960 else
1961 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1963 done_extents = TRUE;
1964 rc.left = x;
1965 rc.top = y;
1966 rc.right = x + sz.cx;
1967 rc.bottom = y + sz.cy;
1969 else
1971 rc = *lprect;
1974 LPtoDP(hdc, (POINT*)&rc, 2);
1976 if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
1977 if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
1980 if ((flags & ETO_OPAQUE) && !PATH_IsPathOpen(dc->path))
1981 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1983 if(count == 0)
1985 ret = TRUE;
1986 goto done;
1989 pt.x = x;
1990 pt.y = y;
1991 LPtoDP(hdc, &pt, 1);
1992 x = pt.x;
1993 y = pt.y;
1995 char_extra = GetTextCharacterExtra(hdc);
1996 if(char_extra || dc->breakExtra || breakRem || lpDx || lf.lfEscapement != 0)
1998 UINT i;
1999 SIZE tmpsz;
2000 deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT));
2001 for(i = 0; i < count; i++)
2003 if(lpDx && (flags & ETO_PDY))
2004 deltas[i] = lpDx[i*2] + char_extra;
2005 else if(lpDx)
2006 deltas[i] = lpDx[i] + char_extra;
2007 else
2009 if(flags & ETO_GLYPH_INDEX)
2010 GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
2011 else
2012 GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
2014 deltas[i] = tmpsz.cx;
2017 if (!(flags & ETO_GLYPH_INDEX) && (dc->breakExtra || breakRem) && reordered_str[i] == tm.tmBreakChar)
2019 deltas[i] = deltas[i] + dc->breakExtra;
2020 if (breakRem > 0)
2022 breakRem--;
2023 deltas[i]++;
2026 deltas[i] = INTERNAL_XWSTODS(dc, deltas[i]);
2027 width += deltas[i];
2030 else
2032 if(!done_extents)
2034 if(flags & ETO_GLYPH_INDEX)
2035 GetTextExtentPointI(hdc, glyphs, count, &sz);
2036 else
2037 GetTextExtentPointW(hdc, reordered_str, count, &sz);
2038 done_extents = TRUE;
2040 width = INTERNAL_XWSTODS(dc, sz.cx);
2042 xwidth = width * cosEsc;
2043 ywidth = width * sinEsc;
2045 tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
2046 tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
2047 switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
2049 case TA_LEFT:
2050 if (align & TA_UPDATECP)
2052 pt.x = x + xwidth;
2053 pt.y = y - ywidth;
2054 DPtoLP(hdc, &pt, 1);
2055 MoveToEx(hdc, pt.x, pt.y, NULL);
2057 break;
2059 case TA_CENTER:
2060 x -= xwidth / 2;
2061 y += ywidth / 2;
2062 break;
2064 case TA_RIGHT:
2065 x -= xwidth;
2066 y += ywidth;
2067 if (align & TA_UPDATECP)
2069 pt.x = x;
2070 pt.y = y;
2071 DPtoLP(hdc, &pt, 1);
2072 MoveToEx(hdc, pt.x, pt.y, NULL);
2074 break;
2077 switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
2079 case TA_TOP:
2080 y += tm.tmAscent * cosEsc;
2081 x += tm.tmAscent * sinEsc;
2082 break;
2084 case TA_BOTTOM:
2085 y -= tm.tmDescent * cosEsc;
2086 x -= tm.tmDescent * sinEsc;
2087 break;
2089 case TA_BASELINE:
2090 break;
2093 if (GetBkMode(hdc) != TRANSPARENT && !PATH_IsPathOpen(dc->path))
2095 if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
2097 if(!(flags & ETO_OPAQUE) || x < rc.left || x + width >= rc.right ||
2098 y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
2100 RECT rc;
2101 rc.left = x;
2102 rc.right = x + width;
2103 rc.top = y - tm.tmAscent;
2104 rc.bottom = y + tm.tmDescent;
2105 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
2110 if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
2112 HFONT orig_font = dc->hFont, cur_font;
2113 UINT glyph;
2114 INT span = 0, *offsets = NULL, i;
2116 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2117 for(i = 0; i < count; i++)
2119 WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
2120 if(cur_font != dc->hFont)
2122 if(!offsets)
2124 int j;
2125 offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
2126 offsets[0] = 0;
2127 if(!deltas)
2129 SIZE tmpsz;
2130 for(j = 1; j < count; j++)
2132 GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
2133 offsets[j] = offsets[j-1] + INTERNAL_XWSTODS(dc, tmpsz.cx);
2136 else
2138 for(j = 1; j < count; j++)
2139 offsets[j] = offsets[j-1] + deltas[j];
2142 if(span)
2144 if (PATH_IsPathOpen(dc->path))
2145 ret = PATH_ExtTextOut(dc, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
2146 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2147 glyphs, span, deltas ? deltas + i - span : NULL);
2148 else
2149 dc->funcs->pExtTextOut(dc->physDev, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
2150 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2151 glyphs, span, deltas ? deltas + i - span : NULL);
2152 span = 0;
2154 SelectObject(hdc, cur_font);
2156 glyphs[span++] = glyph;
2158 if(i == count - 1)
2160 if (PATH_IsPathOpen(dc->path))
2161 ret = PATH_ExtTextOut(dc, x + (offsets ? offsets[count - span] * cosEsc : 0),
2162 y - (offsets ? offsets[count - span] * sinEsc : 0),
2163 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2164 glyphs, span, deltas ? deltas + count - span : NULL);
2165 else
2166 ret = dc->funcs->pExtTextOut(dc->physDev, x + (offsets ? offsets[count - span] * cosEsc : 0),
2167 y - (offsets ? offsets[count - span] * sinEsc : 0),
2168 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2169 glyphs, span, deltas ? deltas + count - span : NULL);
2170 SelectObject(hdc, orig_font);
2171 HeapFree(GetProcessHeap(), 0, offsets);
2175 else
2177 if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
2179 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2180 GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
2181 flags |= ETO_GLYPH_INDEX;
2184 if (PATH_IsPathOpen(dc->path))
2185 ret = PATH_ExtTextOut(dc, x, y, (flags & ~ETO_OPAQUE), &rc,
2186 glyphs ? glyphs : reordered_str, count, deltas);
2187 else
2188 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, (flags & ~ETO_OPAQUE), &rc,
2189 glyphs ? glyphs : reordered_str, count, deltas);
2192 done:
2193 HeapFree(GetProcessHeap(), 0, deltas);
2194 if(glyphs != reordered_str)
2195 HeapFree(GetProcessHeap(), 0, glyphs);
2196 if(reordered_str != str)
2197 HeapFree(GetProcessHeap(), 0, reordered_str);
2199 GDI_ReleaseObj( hdc );
2201 if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2203 int underlinePos, strikeoutPos;
2204 int underlineWidth, strikeoutWidth;
2205 UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2206 OUTLINETEXTMETRICW* otm = NULL;
2208 if(!size)
2210 underlinePos = 0;
2211 underlineWidth = tm.tmAscent / 20 + 1;
2212 strikeoutPos = tm.tmAscent / 2;
2213 strikeoutWidth = underlineWidth;
2215 else
2217 otm = HeapAlloc(GetProcessHeap(), 0, size);
2218 GetOutlineTextMetricsW(hdc, size, otm);
2219 underlinePos = otm->otmsUnderscorePosition;
2220 underlineWidth = otm->otmsUnderscoreSize;
2221 strikeoutPos = otm->otmsStrikeoutPosition;
2222 strikeoutWidth = otm->otmsStrikeoutSize;
2223 HeapFree(GetProcessHeap(), 0, otm);
2226 if (PATH_IsPathOpen(dc->path))
2228 POINT pts[5];
2229 HPEN hpen;
2230 HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2232 hbrush = SelectObject(hdc, hbrush);
2233 hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2235 if (lf.lfUnderline)
2237 pts[0].x = x - underlinePos * sinEsc;
2238 pts[0].y = y - underlinePos * cosEsc;
2239 pts[1].x = x + xwidth - underlinePos * sinEsc;
2240 pts[1].y = y - ywidth - underlinePos * cosEsc;
2241 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2242 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2243 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2244 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2245 pts[4].x = pts[0].x;
2246 pts[4].y = pts[0].y;
2247 DPtoLP(hdc, pts, 5);
2248 Polygon(hdc, pts, 5);
2251 if (lf.lfStrikeOut)
2253 pts[0].x = x - strikeoutPos * sinEsc;
2254 pts[0].y = y - strikeoutPos * cosEsc;
2255 pts[1].x = x + xwidth - strikeoutPos * sinEsc;
2256 pts[1].y = y - ywidth - strikeoutPos * cosEsc;
2257 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2258 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2259 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2260 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2261 pts[4].x = pts[0].x;
2262 pts[4].y = pts[0].y;
2263 DPtoLP(hdc, pts, 5);
2264 Polygon(hdc, pts, 5);
2267 SelectObject(hdc, hpen);
2268 hbrush = SelectObject(hdc, hbrush);
2269 DeleteObject(hbrush);
2271 else
2273 POINT pts[2], oldpt;
2274 HPEN hpen;
2276 if (lf.lfUnderline)
2278 hpen = CreatePen(PS_SOLID, underlineWidth, GetTextColor(hdc));
2279 hpen = SelectObject(hdc, hpen);
2280 pts[0].x = x;
2281 pts[0].y = y;
2282 pts[1].x = x + xwidth;
2283 pts[1].y = y - ywidth;
2284 DPtoLP(hdc, pts, 2);
2285 MoveToEx(hdc, pts[0].x - underlinePos * sinEsc, pts[0].y - underlinePos * cosEsc, &oldpt);
2286 LineTo(hdc, pts[1].x - underlinePos * sinEsc, pts[1].y - underlinePos * cosEsc);
2287 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2288 DeleteObject(SelectObject(hdc, hpen));
2291 if (lf.lfStrikeOut)
2293 hpen = CreatePen(PS_SOLID, strikeoutWidth, GetTextColor(hdc));
2294 hpen = SelectObject(hdc, hpen);
2295 pts[0].x = x;
2296 pts[0].y = y;
2297 pts[1].x = x + xwidth;
2298 pts[1].y = y - ywidth;
2299 DPtoLP(hdc, pts, 2);
2300 MoveToEx(hdc, pts[0].x - strikeoutPos * sinEsc, pts[0].y - strikeoutPos * cosEsc, &oldpt);
2301 LineTo(hdc, pts[1].x - strikeoutPos * sinEsc, pts[1].y - strikeoutPos * cosEsc);
2302 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2303 DeleteObject(SelectObject(hdc, hpen));
2308 return ret;
2312 /***********************************************************************
2313 * TextOutA (GDI32.@)
2315 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2317 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2321 /***********************************************************************
2322 * TextOutW (GDI32.@)
2324 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2326 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2330 /***********************************************************************
2331 * PolyTextOutA (GDI32.@)
2333 * See PolyTextOutW.
2335 BOOL WINAPI PolyTextOutA( HDC hdc, const POLYTEXTA *pptxt, INT cStrings )
2337 for (; cStrings>0; cStrings--, pptxt++)
2338 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2339 return FALSE;
2340 return TRUE;
2345 /***********************************************************************
2346 * PolyTextOutW (GDI32.@)
2348 * Draw several Strings
2350 * RETURNS
2351 * TRUE: Success.
2352 * FALSE: Failure.
2354 BOOL WINAPI PolyTextOutW( HDC hdc, const POLYTEXTW *pptxt, INT cStrings )
2356 for (; cStrings>0; cStrings--, pptxt++)
2357 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2358 return FALSE;
2359 return TRUE;
2363 /* FIXME: all following APIs ******************************************/
2366 /***********************************************************************
2367 * SetMapperFlags (GDI32.@)
2369 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
2371 DC *dc = DC_GetDCPtr( hDC );
2372 DWORD ret = 0;
2373 if(!dc) return 0;
2374 if(dc->funcs->pSetMapperFlags)
2376 ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
2377 /* FIXME: ret is just a success flag, we should return a proper value */
2379 else
2380 FIXME("(%p, 0x%08x): stub - harmless\n", hDC, dwFlag);
2381 GDI_ReleaseObj( hDC );
2382 return ret;
2385 /***********************************************************************
2386 * GetAspectRatioFilterEx (GDI.486)
2388 BOOL16 WINAPI GetAspectRatioFilterEx16( HDC16 hdc, LPSIZE16 pAspectRatio )
2390 FIXME("(%04x, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2391 return FALSE;
2394 /***********************************************************************
2395 * GetAspectRatioFilterEx (GDI32.@)
2397 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2399 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2400 return FALSE;
2404 /***********************************************************************
2405 * GetCharABCWidthsA (GDI32.@)
2407 * See GetCharABCWidthsW.
2409 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2410 LPABC abc )
2412 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
2413 LPSTR str;
2414 LPWSTR wstr;
2415 BOOL ret = TRUE;
2417 if(count <= 0) return FALSE;
2419 str = HeapAlloc(GetProcessHeap(), 0, count);
2420 for(i = 0; i < count; i++)
2421 str[i] = (BYTE)(firstChar + i);
2423 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
2425 for(i = 0; i < wlen; i++)
2427 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2429 ret = FALSE;
2430 break;
2432 abc++;
2435 HeapFree(GetProcessHeap(), 0, str);
2436 HeapFree(GetProcessHeap(), 0, wstr);
2438 return ret;
2442 /******************************************************************************
2443 * GetCharABCWidthsW [GDI32.@]
2445 * Retrieves widths of characters in range.
2447 * PARAMS
2448 * hdc [I] Handle of device context
2449 * firstChar [I] First character in range to query
2450 * lastChar [I] Last character in range to query
2451 * abc [O] Address of character-width structure
2453 * NOTES
2454 * Only works with TrueType fonts
2456 * RETURNS
2457 * Success: TRUE
2458 * Failure: FALSE
2460 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2461 LPABC abc )
2463 DC *dc = DC_GetDCPtr(hdc);
2464 unsigned int i;
2465 BOOL ret = FALSE;
2467 if (!dc) return FALSE;
2469 if(dc->gdiFont)
2470 ret = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
2471 else
2472 FIXME(": stub\n");
2474 if (ret)
2476 /* convert device units to logical */
2477 for( i = firstChar; i <= lastChar; i++, abc++ ) {
2478 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2479 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2480 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2482 ret = TRUE;
2485 GDI_ReleaseObj(hdc);
2486 return ret;
2490 /******************************************************************************
2491 * GetCharABCWidthsI [GDI32.@]
2493 * Retrieves widths of characters in range.
2495 * PARAMS
2496 * hdc [I] Handle of device context
2497 * firstChar [I] First glyphs in range to query
2498 * count [I] Last glyphs in range to query
2499 * pgi [i] Array of glyphs to query
2500 * abc [O] Address of character-width structure
2502 * NOTES
2503 * Only works with TrueType fonts
2505 * RETURNS
2506 * Success: TRUE
2507 * Failure: FALSE
2509 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2510 LPWORD pgi, LPABC abc)
2512 DC *dc = DC_GetDCPtr(hdc);
2513 unsigned int i;
2514 BOOL ret = FALSE;
2516 if (!dc) return FALSE;
2518 if(dc->gdiFont)
2519 ret = WineEngGetCharABCWidthsI( dc->gdiFont, firstChar, count, pgi, abc );
2520 else
2521 FIXME(": stub\n");
2523 if (ret)
2525 /* convert device units to logical */
2526 for( i = 0; i < count; i++, abc++ ) {
2527 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2528 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2529 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2531 ret = TRUE;
2534 GDI_ReleaseObj(hdc);
2535 return ret;
2539 /***********************************************************************
2540 * GetGlyphOutlineA (GDI32.@)
2542 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2543 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2544 LPVOID lpBuffer, const MAT2 *lpmat2 )
2546 LPWSTR p = NULL;
2547 DWORD ret;
2548 UINT c;
2550 if(!(fuFormat & GGO_GLYPH_INDEX)) {
2551 int len;
2552 char mbchs[2];
2553 if(uChar > 0xff) { /* but, 2 bytes character only */
2554 len = 2;
2555 mbchs[0] = (uChar & 0xff00) >> 8;
2556 mbchs[1] = (uChar & 0xff);
2557 } else {
2558 len = 1;
2559 mbchs[0] = (uChar & 0xff);
2561 p = FONT_mbtowc(hdc, mbchs, len, NULL, NULL);
2562 c = p[0];
2563 } else
2564 c = uChar;
2565 ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
2566 lpmat2);
2567 HeapFree(GetProcessHeap(), 0, p);
2568 return ret;
2571 /***********************************************************************
2572 * GetGlyphOutlineW (GDI32.@)
2574 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2575 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2576 LPVOID lpBuffer, const MAT2 *lpmat2 )
2578 DC *dc = DC_GetDCPtr(hdc);
2579 DWORD ret;
2581 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2582 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2584 if(!dc) return GDI_ERROR;
2586 if(dc->gdiFont)
2587 ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
2588 cbBuffer, lpBuffer, lpmat2);
2589 else
2590 ret = GDI_ERROR;
2592 GDI_ReleaseObj(hdc);
2593 return ret;
2597 /***********************************************************************
2598 * CreateScalableFontResourceA (GDI32.@)
2600 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2601 LPCSTR lpszResourceFile,
2602 LPCSTR lpszFontFile,
2603 LPCSTR lpszCurrentPath )
2605 HANDLE f;
2607 /* fHidden=1 - only visible for the calling app, read-only, not
2608 * enumbered with EnumFonts/EnumFontFamilies
2609 * lpszCurrentPath can be NULL
2611 FIXME("(%d,%s,%s,%s): stub\n",
2612 fHidden, debugstr_a(lpszResourceFile), debugstr_a(lpszFontFile),
2613 debugstr_a(lpszCurrentPath) );
2615 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2616 if ((f = CreateFileA(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2617 CloseHandle(f);
2618 SetLastError(ERROR_FILE_EXISTS);
2619 return FALSE;
2621 return FALSE; /* create failed */
2624 /***********************************************************************
2625 * CreateScalableFontResourceW (GDI32.@)
2627 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2628 LPCWSTR lpszResourceFile,
2629 LPCWSTR lpszFontFile,
2630 LPCWSTR lpszCurrentPath )
2632 FIXME("(%d,%p,%p,%p): stub\n",
2633 fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
2634 return FALSE; /* create failed */
2637 /*************************************************************************
2638 * GetKerningPairsA (GDI32.@)
2640 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2641 LPKERNINGPAIR kern_pairA )
2643 INT charset;
2644 CHARSETINFO csi;
2645 CPINFO cpi;
2646 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2647 KERNINGPAIR *kern_pairW;
2649 if (!cPairs && kern_pairA)
2651 SetLastError(ERROR_INVALID_PARAMETER);
2652 return 0;
2655 charset = GetTextCharset(hDC);
2656 if (!TranslateCharsetInfo(ULongToPtr(charset), &csi, TCI_SRCCHARSET))
2658 FIXME("Can't find codepage for charset %d\n", charset);
2659 return 0;
2661 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2662 * to fail on an invalid character for CP_SYMBOL.
2664 cpi.DefaultChar[0] = 0;
2665 if (csi.ciACP != CP_SYMBOL && !GetCPInfo(csi.ciACP, &cpi))
2667 FIXME("Can't find codepage %u info\n", csi.ciACP);
2668 return 0;
2670 TRACE("charset %d => codepage %u\n", charset, csi.ciACP);
2672 total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2673 if (!total_kern_pairs) return 0;
2675 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2676 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2678 for (i = 0; i < total_kern_pairs; i++)
2680 char first, second;
2682 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2683 continue;
2685 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2686 continue;
2688 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2689 continue;
2691 if (kern_pairA)
2693 if (kern_pairs_copied >= cPairs) break;
2695 kern_pairA->wFirst = (BYTE)first;
2696 kern_pairA->wSecond = (BYTE)second;
2697 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2698 kern_pairA++;
2700 kern_pairs_copied++;
2703 HeapFree(GetProcessHeap(), 0, kern_pairW);
2705 return kern_pairs_copied;
2708 /*************************************************************************
2709 * GetKerningPairsW (GDI32.@)
2711 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2712 LPKERNINGPAIR lpKerningPairs )
2714 DC *dc;
2715 DWORD ret = 0;
2717 TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2719 if (!cPairs && lpKerningPairs)
2721 SetLastError(ERROR_INVALID_PARAMETER);
2722 return 0;
2725 dc = DC_GetDCPtr(hDC);
2726 if (!dc) return 0;
2728 if (dc->gdiFont)
2729 ret = WineEngGetKerningPairs(dc->gdiFont, cPairs, lpKerningPairs);
2731 GDI_ReleaseObj(hDC);
2732 return ret;
2735 /*************************************************************************
2736 * TranslateCharsetInfo [GDI32.@]
2738 * Fills a CHARSETINFO structure for a character set, code page, or
2739 * font. This allows making the correspondance between different labelings
2740 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2741 * of the same encoding.
2743 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2744 * only one codepage should be set in *lpSrc.
2746 * RETURNS
2747 * TRUE on success, FALSE on failure.
2750 BOOL WINAPI TranslateCharsetInfo(
2751 LPDWORD lpSrc, /* [in]
2752 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2753 if flags == TCI_SRCCHARSET: a character set value
2754 if flags == TCI_SRCCODEPAGE: a code page value
2756 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2757 DWORD flags /* [in] determines interpretation of lpSrc */)
2759 int index = 0;
2760 switch (flags) {
2761 case TCI_SRCFONTSIG:
2762 while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
2763 break;
2764 case TCI_SRCCODEPAGE:
2765 while (PtrToUlong(lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
2766 break;
2767 case TCI_SRCCHARSET:
2768 while (PtrToUlong(lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
2769 break;
2770 default:
2771 return FALSE;
2773 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2774 memcpy(lpCs, &FONT_tci[index], sizeof(CHARSETINFO));
2775 return TRUE;
2778 /*************************************************************************
2779 * GetFontLanguageInfo (GDI32.@)
2781 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2783 FONTSIGNATURE fontsig;
2784 static const DWORD GCP_DBCS_MASK=0x003F0000,
2785 GCP_DIACRITIC_MASK=0x00000000,
2786 FLI_GLYPHS_MASK=0x00000000,
2787 GCP_GLYPHSHAPE_MASK=0x00000040,
2788 GCP_KASHIDA_MASK=0x00000000,
2789 GCP_LIGATE_MASK=0x00000000,
2790 GCP_USEKERNING_MASK=0x00000000,
2791 GCP_REORDER_MASK=0x00000060;
2793 DWORD result=0;
2795 GetTextCharsetInfo( hdc, &fontsig, 0 );
2796 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2798 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2799 result|=GCP_DBCS;
2801 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2802 result|=GCP_DIACRITIC;
2804 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2805 result|=FLI_GLYPHS;
2807 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2808 result|=GCP_GLYPHSHAPE;
2810 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2811 result|=GCP_KASHIDA;
2813 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2814 result|=GCP_LIGATE;
2816 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2817 result|=GCP_USEKERNING;
2819 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2820 if( GetTextAlign( hdc) & TA_RTLREADING )
2821 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2822 result|=GCP_REORDER;
2824 return result;
2828 /*************************************************************************
2829 * GetFontData [GDI32.@]
2831 * Retrieve data for TrueType font.
2833 * RETURNS
2835 * success: Number of bytes returned
2836 * failure: GDI_ERROR
2838 * NOTES
2840 * Calls SetLastError()
2843 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2844 LPVOID buffer, DWORD length)
2846 DC *dc = DC_GetDCPtr(hdc);
2847 DWORD ret = GDI_ERROR;
2849 if(!dc) return GDI_ERROR;
2851 if(dc->gdiFont)
2852 ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2854 GDI_ReleaseObj(hdc);
2855 return ret;
2858 /*************************************************************************
2859 * GetGlyphIndicesA [GDI32.@]
2861 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2862 LPWORD pgi, DWORD flags)
2864 DWORD ret;
2865 WCHAR *lpstrW;
2866 INT countW;
2868 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2869 hdc, debugstr_an(lpstr, count), count, pgi, flags);
2871 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2872 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2873 HeapFree(GetProcessHeap(), 0, lpstrW);
2875 return ret;
2878 /*************************************************************************
2879 * GetGlyphIndicesW [GDI32.@]
2881 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2882 LPWORD pgi, DWORD flags)
2884 DC *dc = DC_GetDCPtr(hdc);
2885 DWORD ret = GDI_ERROR;
2887 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2888 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2890 if(!dc) return GDI_ERROR;
2892 if(dc->gdiFont)
2893 ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2895 GDI_ReleaseObj(hdc);
2896 return ret;
2899 /*************************************************************************
2900 * GetCharacterPlacementA [GDI32.@]
2902 * See GetCharacterPlacementW.
2904 * NOTES:
2905 * the web browser control of ie4 calls this with dwFlags=0
2907 DWORD WINAPI
2908 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2909 INT nMaxExtent, GCP_RESULTSA *lpResults,
2910 DWORD dwFlags)
2912 WCHAR *lpStringW;
2913 INT uCountW;
2914 GCP_RESULTSW resultsW;
2915 DWORD ret;
2916 UINT font_cp;
2918 TRACE("%s, %d, %d, 0x%08x\n",
2919 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2921 /* both structs are equal in size */
2922 memcpy(&resultsW, lpResults, sizeof(resultsW));
2924 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2925 if(lpResults->lpOutString)
2926 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2928 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2930 lpResults->nGlyphs = resultsW.nGlyphs;
2931 lpResults->nMaxFit = resultsW.nMaxFit;
2933 if(lpResults->lpOutString) {
2934 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2935 lpResults->lpOutString, uCount, NULL, NULL );
2938 HeapFree(GetProcessHeap(), 0, lpStringW);
2939 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2941 return ret;
2944 /*************************************************************************
2945 * GetCharacterPlacementW [GDI32.@]
2947 * Retrieve information about a string. This includes the width, reordering,
2948 * Glyphing and so on.
2950 * RETURNS
2952 * The width and height of the string if successful, 0 if failed.
2954 * BUGS
2956 * All flags except GCP_REORDER are not yet implemented.
2957 * Reordering is not 100% complient to the Windows BiDi method.
2958 * Caret positioning is not yet implemented for BiDi.
2959 * Classes are not yet implemented.
2962 DWORD WINAPI
2963 GetCharacterPlacementW(
2964 HDC hdc, /* [in] Device context for which the rendering is to be done */
2965 LPCWSTR lpString, /* [in] The string for which information is to be returned */
2966 INT uCount, /* [in] Number of WORDS in string. */
2967 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
2968 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2969 DWORD dwFlags /* [in] Flags specifying how to process the string */
2972 DWORD ret=0;
2973 SIZE size;
2974 UINT i, nSet;
2976 TRACE("%s, %d, %d, 0x%08x\n",
2977 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2979 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2980 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2981 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2982 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2983 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2985 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08x ignored\n", dwFlags);
2986 if(lpResults->lpClass) FIXME("classes not implemented\n");
2987 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2988 FIXME("Caret positions for complex scripts not implemented\n");
2990 nSet = (UINT)uCount;
2991 if(nSet > lpResults->nGlyphs)
2992 nSet = lpResults->nGlyphs;
2994 /* return number of initialized fields */
2995 lpResults->nGlyphs = nSet;
2997 if((dwFlags&GCP_REORDER)==0 || !BidiAvail)
2999 /* Treat the case where no special handling was requested in a fastpath way */
3000 /* copy will do if the GCP_REORDER flag is not set */
3001 if(lpResults->lpOutString)
3002 memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
3004 if(lpResults->lpOrder)
3006 for(i = 0; i < nSet; i++)
3007 lpResults->lpOrder[i] = i;
3009 } else
3011 BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
3012 nSet, lpResults->lpOrder );
3015 /* FIXME: Will use the placement chars */
3016 if (lpResults->lpDx)
3018 int c;
3019 for (i = 0; i < nSet; i++)
3021 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
3022 lpResults->lpDx[i]= c;
3026 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
3028 int pos = 0;
3030 lpResults->lpCaretPos[0] = 0;
3031 for (i = 1; i < nSet; i++)
3032 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
3033 lpResults->lpCaretPos[i] = (pos += size.cx);
3036 if(lpResults->lpGlyphs)
3037 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
3039 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
3040 ret = MAKELONG(size.cx, size.cy);
3042 return ret;
3045 /*************************************************************************
3046 * GetCharABCWidthsFloatA [GDI32.@]
3048 * See GetCharABCWidthsFloatW.
3050 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3052 INT i, wlen, count = (INT)(last - first + 1);
3053 LPSTR str;
3054 LPWSTR wstr;
3055 BOOL ret = TRUE;
3057 if (count <= 0) return FALSE;
3059 str = HeapAlloc(GetProcessHeap(), 0, count);
3061 for(i = 0; i < count; i++)
3062 str[i] = (BYTE)(first + i);
3064 wstr = FONT_mbtowc( hdc, str, count, &wlen, NULL );
3066 for (i = 0; i < wlen; i++)
3068 if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
3070 ret = FALSE;
3071 break;
3073 abcf++;
3076 HeapFree( GetProcessHeap(), 0, str );
3077 HeapFree( GetProcessHeap(), 0, wstr );
3079 return ret;
3082 /*************************************************************************
3083 * GetCharABCWidthsFloatW [GDI32.@]
3085 * Retrieves widths of a range of characters.
3087 * PARAMS
3088 * hdc [I] Handle to device context.
3089 * first [I] First character in range to query.
3090 * last [I] Last character in range to query.
3091 * abcf [O] Array of LPABCFLOAT structures.
3093 * RETURNS
3094 * Success: TRUE
3095 * Failure: FALSE
3097 * BUGS
3098 * Only works with TrueType fonts. It also doesn't return real
3099 * floats but converted integers because it's implemented on
3100 * top of GetCharABCWidthsW.
3102 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3104 ABC *abc;
3105 unsigned int i, size = sizeof(ABC) * (last - first + 1);
3106 BOOL ret;
3108 TRACE("%p, %d, %d, %p - partial stub\n", hdc, first, last, abcf);
3110 abc = HeapAlloc( GetProcessHeap(), 0, size );
3111 if (!abc) return FALSE;
3113 ret = GetCharABCWidthsW( hdc, first, last, abc );
3114 if (ret)
3116 for (i = first; i <= last; i++, abc++, abcf++)
3118 abcf->abcfA = abc->abcA;
3119 abcf->abcfB = abc->abcB;
3120 abcf->abcfC = abc->abcC;
3123 HeapFree( GetProcessHeap(), 0, abc );
3124 return ret;
3127 /*************************************************************************
3128 * GetCharWidthFloatA [GDI32.@]
3130 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
3131 UINT iLastChar, PFLOAT pxBuffer)
3133 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3134 return 0;
3137 /*************************************************************************
3138 * GetCharWidthFloatW [GDI32.@]
3140 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
3141 UINT iLastChar, PFLOAT pxBuffer)
3143 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3144 return 0;
3148 /***********************************************************************
3150 * Font Resource API *
3152 ***********************************************************************/
3154 /***********************************************************************
3155 * AddFontResourceA (GDI32.@)
3157 INT WINAPI AddFontResourceA( LPCSTR str )
3159 return AddFontResourceExA( str, 0, NULL);
3162 /***********************************************************************
3163 * AddFontResourceW (GDI32.@)
3165 INT WINAPI AddFontResourceW( LPCWSTR str )
3167 return AddFontResourceExW(str, 0, NULL);
3171 /***********************************************************************
3172 * AddFontResourceExA (GDI32.@)
3174 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3176 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3177 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3178 INT ret;
3180 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3181 ret = AddFontResourceExW(strW, fl, pdv);
3182 HeapFree(GetProcessHeap(), 0, strW);
3183 return ret;
3186 /***********************************************************************
3187 * AddFontResourceExW (GDI32.@)
3189 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3191 return WineEngAddFontResourceEx(str, fl, pdv);
3194 /***********************************************************************
3195 * RemoveFontResourceA (GDI32.@)
3197 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3199 return RemoveFontResourceExA(str, 0, 0);
3202 /***********************************************************************
3203 * RemoveFontResourceW (GDI32.@)
3205 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3207 return RemoveFontResourceExW(str, 0, 0);
3210 /***********************************************************************
3211 * AddFontMemResourceEx (GDI32.@)
3213 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3215 FIXME("(%p,%08x,%p,%p): stub\n", pbFont, cbFont, pdv, pcFonts);
3216 return NULL;
3219 /***********************************************************************
3220 * RemoveFontResourceExA (GDI32.@)
3222 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3224 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3225 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3226 INT ret;
3228 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3229 ret = RemoveFontResourceExW(strW, fl, pdv);
3230 HeapFree(GetProcessHeap(), 0, strW);
3231 return ret;
3234 /***********************************************************************
3235 * RemoveFontResourceExW (GDI32.@)
3237 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3239 return WineEngRemoveFontResourceEx(str, fl, pdv);
3242 /***********************************************************************
3243 * GetTextCharset (GDI32.@)
3245 UINT WINAPI GetTextCharset(HDC hdc)
3247 /* MSDN docs say this is equivalent */
3248 return GetTextCharsetInfo(hdc, NULL, 0);
3251 /***********************************************************************
3252 * GetTextCharsetInfo (GDI32.@)
3254 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3256 UINT ret = DEFAULT_CHARSET;
3257 DC *dc = DC_GetDCPtr(hdc);
3259 if (dc)
3261 if (dc->gdiFont)
3262 ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
3264 GDI_ReleaseObj(hdc);
3267 if (ret == DEFAULT_CHARSET && fs)
3268 memset(fs, 0, sizeof(FONTSIGNATURE));
3269 return ret;
3272 /***********************************************************************
3273 * GdiGetCharDimensions (GDI32.@)
3275 * Gets the average width of the characters in the English alphabet.
3277 * PARAMS
3278 * hdc [I] Handle to the device context to measure on.
3279 * lptm [O] Pointer to memory to store the text metrics into.
3280 * height [O] On exit, the maximum height of characters in the English alphabet.
3282 * RETURNS
3283 * The average width of characters in the English alphabet.
3285 * NOTES
3286 * This function is used by the dialog manager to get the size of a dialog
3287 * unit. It should also be used by other pieces of code that need to know
3288 * the size of a dialog unit in logical units without having access to the
3289 * window handle of the dialog.
3290 * Windows caches the font metrics from this function, but we don't and
3291 * there doesn't appear to be an immediate advantage to do so.
3293 * SEE ALSO
3294 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3296 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3298 SIZE sz;
3299 static const WCHAR alphabet[] = {
3300 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3301 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3302 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3304 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3306 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3308 if (height) *height = sz.cy;
3309 return (sz.cx / 26 + 1) / 2;
3312 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3314 FIXME("(%d): stub\n", fEnableEUDC);
3315 return FALSE;
3318 /***********************************************************************
3319 * GetCharWidthI (GDI32.@)
3321 * Retrieve widths of characters.
3323 * PARAMS
3324 * hdc [I] Handle to a device context.
3325 * first [I] First glyph in range to query.
3326 * count [I] Number of glyph indices to query.
3327 * glyphs [I] Array of glyphs to query.
3328 * buffer [O] Buffer to receive character widths.
3330 * NOTES
3331 * Only works with TrueType fonts.
3333 * RETURNS
3334 * Success: TRUE
3335 * Failure: FALSE
3337 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3339 ABC *abc;
3340 unsigned int i;
3342 TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3344 if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3345 return FALSE;
3347 if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3349 HeapFree(GetProcessHeap(), 0, abc);
3350 return FALSE;
3353 for (i = 0; i < count; i++)
3354 buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3356 HeapFree(GetProcessHeap(), 0, abc);
3357 return TRUE;
3360 /***********************************************************************
3361 * GetFontUnicodeRanges (GDI32.@)
3363 * Retrieve a list of supported Unicode characters in a font.
3365 * PARAMS
3366 * hdc [I] Handle to a device context.
3367 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3369 * RETURNS
3370 * Success: Number of bytes written to the buffer pointed to by lpgs.
3371 * Failure: 0
3374 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3376 return WineEngGetFontUnicodeRanges(hdc, lpgs);