wintrust: Don't prefer native version.
[wine/multimedia.git] / dlls / gdi32 / font.c
blobc5167363b5adeeb7aaa31a509fc8b2436f62397c
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 DC_ReleaseDCPtr( dc );
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 DC_ReleaseDCPtr( pfe->dc ); /* 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) DC_ReleaseDCPtr( dc );
715 pfe->hdc = 0; /* make sure we don't try to release it later on */
716 pfe->dc = NULL;
717 ret = 0;
720 return ret;
723 /***********************************************************************
724 * FONT_EnumInstance
726 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
727 * We have to use other types because of the FONTENUMPROCW definition.
729 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
730 DWORD fType, LPARAM lp )
732 fontEnum32 *pfe = (fontEnum32*)lp;
733 INT ret = 1;
734 DC *dc;
736 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
737 if((pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
738 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
739 (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
741 /* convert font metrics */
742 ENUMLOGFONTEXA logfont;
743 NEWTEXTMETRICEXA tmA;
745 pfe->dwFlags |= ENUM_CALLED;
746 if (!(pfe->dwFlags & ENUM_UNICODE))
748 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
749 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
750 plf = (LOGFONTW *)&logfont.elfLogFont;
751 ptm = (TEXTMETRICW *)&tmA;
753 DC_ReleaseDCPtr( pfe->dc ); /* release the GDI lock */
755 ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
757 /* get the lock again and make sure the DC is still valid */
758 dc = DC_GetDCPtr( pfe->hdc );
759 if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
761 if (dc) DC_ReleaseDCPtr( dc );
762 pfe->hdc = 0; /* make sure we don't try to release it later on */
763 pfe->dc = NULL;
764 ret = 0;
767 return ret;
770 /***********************************************************************
771 * EnumFontFamiliesEx (GDI.613)
773 INT16 WINAPI EnumFontFamiliesEx16( HDC16 hDC, LPLOGFONT16 plf,
774 FONTENUMPROC16 efproc, LPARAM lParam,
775 DWORD dwFlags)
777 fontEnum16 fe16;
778 INT16 ret = 1, ret2;
779 DC* dc = DC_GetDCPtr( HDC_32(hDC) );
780 NEWTEXTMETRICEX16 tm16;
781 ENUMLOGFONTEX16 lf16;
782 LOGFONTW lfW;
783 BOOL enum_gdi_fonts;
785 if (!dc) return 0;
786 FONT_LogFont16ToW(plf, &lfW);
788 fe16.hdc = HDC_32(hDC);
789 fe16.dc = dc;
790 fe16.physDev = dc->physDev;
791 fe16.lpLogFontParam = plf;
792 fe16.lpEnumFunc = efproc;
793 fe16.lpData = lParam;
794 fe16.lpTextMetric = &tm16;
795 fe16.lpLogFont = &lf16;
796 fe16.segTextMetric = MapLS( &tm16 );
797 fe16.segLogFont = MapLS( &lf16 );
798 fe16.dwFlags = 0;
800 enum_gdi_fonts = GetDeviceCaps(fe16.hdc, TEXTCAPS) & TC_VA_ABLE;
802 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
804 ret = 0;
805 goto done;
808 if (enum_gdi_fonts)
809 ret = WineEngEnumFonts( &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
810 fe16.dwFlags &= ~ENUM_CALLED;
811 if (ret && dc->funcs->pEnumDeviceFonts) {
812 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
813 if(fe16.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
814 ret = ret2;
816 done:
817 UnMapLS( fe16.segTextMetric );
818 UnMapLS( fe16.segLogFont );
819 if (fe16.dc) DC_ReleaseDCPtr( fe16.dc );
820 return ret;
823 /***********************************************************************
824 * FONT_EnumFontFamiliesEx
826 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf,
827 FONTENUMPROCW efproc,
828 LPARAM lParam, DWORD dwUnicode)
830 INT ret = 1, ret2;
831 DC *dc = DC_GetDCPtr( hDC );
832 fontEnum32 fe32;
833 BOOL enum_gdi_fonts;
835 if (!dc) return 0;
837 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName),
838 plf->lfCharSet);
839 fe32.lpLogFontParam = plf;
840 fe32.lpEnumFunc = efproc;
841 fe32.lpData = lParam;
842 fe32.dwFlags = dwUnicode;
843 fe32.hdc = hDC;
844 fe32.dc = dc;
845 fe32.physDev = dc->physDev;
847 enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE;
849 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
851 ret = 0;
852 goto done;
855 if (enum_gdi_fonts)
856 ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
857 fe32.dwFlags &= ~ENUM_CALLED;
858 if (ret && dc->funcs->pEnumDeviceFonts) {
859 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, plf, FONT_EnumInstance, (LPARAM)&fe32 );
860 if(fe32.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
861 ret = ret2;
863 done:
864 if (fe32.dc) DC_ReleaseDCPtr( fe32.dc );
865 return ret;
868 /***********************************************************************
869 * EnumFontFamiliesExW (GDI32.@)
871 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
872 FONTENUMPROCW efproc,
873 LPARAM lParam, DWORD dwFlags )
875 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, ENUM_UNICODE );
878 /***********************************************************************
879 * EnumFontFamiliesExA (GDI32.@)
881 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
882 FONTENUMPROCA efproc,
883 LPARAM lParam, DWORD dwFlags)
885 LOGFONTW lfW;
886 FONT_LogFontAToW( plf, &lfW );
888 return FONT_EnumFontFamiliesEx( hDC, &lfW, (FONTENUMPROCW)efproc, lParam, 0);
891 /***********************************************************************
892 * EnumFontFamilies (GDI.330)
894 INT16 WINAPI EnumFontFamilies16( HDC16 hDC, LPCSTR lpFamily,
895 FONTENUMPROC16 efproc, LPARAM lpData )
897 LOGFONT16 lf;
899 lf.lfCharSet = DEFAULT_CHARSET;
900 if (lpFamily)
902 if (!*lpFamily) return 1;
903 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
905 else lf.lfFaceName[0] = '\0';
907 return EnumFontFamiliesEx16( hDC, &lf, efproc, lpData, 0 );
910 /***********************************************************************
911 * EnumFontFamiliesA (GDI32.@)
913 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
914 FONTENUMPROCA efproc, LPARAM lpData )
916 LOGFONTA lf;
918 lf.lfCharSet = DEFAULT_CHARSET;
919 if (lpFamily)
921 if (!*lpFamily) return 1;
922 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
924 else lf.lfFaceName[0] = lf.lfFaceName[1] = '\0';
926 return EnumFontFamiliesExA( hDC, &lf, efproc, lpData, 0 );
929 /***********************************************************************
930 * EnumFontFamiliesW (GDI32.@)
932 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
933 FONTENUMPROCW efproc, LPARAM lpData )
935 LOGFONTW lf;
937 lf.lfCharSet = DEFAULT_CHARSET;
938 if (lpFamily)
940 if (!*lpFamily) return 1;
941 lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
943 else lf.lfFaceName[0] = 0;
945 return EnumFontFamiliesExW( hDC, &lf, efproc, lpData, 0 );
948 /***********************************************************************
949 * EnumFonts (GDI.70)
951 INT16 WINAPI EnumFonts16( HDC16 hDC, LPCSTR lpName, FONTENUMPROC16 efproc,
952 LPARAM lpData )
954 return EnumFontFamilies16( hDC, lpName, efproc, lpData );
957 /***********************************************************************
958 * EnumFontsA (GDI32.@)
960 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
961 LPARAM lpData )
963 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
966 /***********************************************************************
967 * EnumFontsW (GDI32.@)
969 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
970 LPARAM lpData )
972 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
976 /***********************************************************************
977 * GetTextCharacterExtra (GDI32.@)
979 INT WINAPI GetTextCharacterExtra( HDC hdc )
981 INT ret;
982 DC *dc = DC_GetDCPtr( hdc );
983 if (!dc) return 0x80000000;
984 ret = dc->charExtra;
985 DC_ReleaseDCPtr( dc );
986 return ret;
990 /***********************************************************************
991 * SetTextCharacterExtra (GDI32.@)
993 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
995 INT prev;
996 DC * dc = DC_GetDCPtr( hdc );
997 if (!dc) return 0x80000000;
998 if (dc->funcs->pSetTextCharacterExtra)
999 prev = dc->funcs->pSetTextCharacterExtra( dc->physDev, extra );
1000 else
1002 prev = dc->charExtra;
1003 dc->charExtra = extra;
1005 DC_ReleaseDCPtr( dc );
1006 return prev;
1010 /***********************************************************************
1011 * SetTextJustification (GDI32.@)
1013 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
1015 BOOL ret = TRUE;
1016 DC * dc = DC_GetDCPtr( hdc );
1017 if (!dc) return FALSE;
1018 if (dc->funcs->pSetTextJustification)
1019 ret = dc->funcs->pSetTextJustification( dc->physDev, extra, breaks );
1020 else
1022 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
1023 if (!extra) breaks = 0;
1024 if (breaks)
1026 dc->breakExtra = extra / breaks;
1027 dc->breakRem = extra - (breaks * dc->breakExtra);
1029 else
1031 dc->breakExtra = 0;
1032 dc->breakRem = 0;
1035 DC_ReleaseDCPtr( dc );
1036 return ret;
1040 /***********************************************************************
1041 * GetTextFaceA (GDI32.@)
1043 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
1045 INT res = GetTextFaceW(hdc, 0, NULL);
1046 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
1047 GetTextFaceW( hdc, res, nameW );
1049 if (name)
1051 if (count && !WideCharToMultiByte( CP_ACP, 0, nameW, -1, name, count, NULL, NULL))
1052 name[count-1] = 0;
1053 res = strlen(name);
1055 else
1056 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
1057 HeapFree( GetProcessHeap(), 0, nameW );
1058 return res;
1061 /***********************************************************************
1062 * GetTextFaceW (GDI32.@)
1064 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
1066 FONTOBJ *font;
1067 INT ret = 0;
1069 DC * dc = DC_GetDCPtr( hdc );
1070 if (!dc) return 0;
1072 if(dc->gdiFont)
1073 ret = WineEngGetTextFace(dc->gdiFont, count, name);
1074 else if ((font = (FONTOBJ *) GDI_GetObjPtr( dc->hFont, FONT_MAGIC )))
1076 if (name)
1078 lstrcpynW( name, font->logfont.lfFaceName, count );
1079 ret = strlenW(name);
1081 else ret = strlenW(font->logfont.lfFaceName) + 1;
1082 GDI_ReleaseObj( dc->hFont );
1084 DC_ReleaseDCPtr( dc );
1085 return ret;
1089 /***********************************************************************
1090 * GetTextExtentPoint32A (GDI32.@)
1092 * See GetTextExtentPoint32W.
1094 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
1095 LPSIZE size )
1097 BOOL ret = FALSE;
1098 INT wlen;
1099 LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1101 if (p) {
1102 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
1103 HeapFree( GetProcessHeap(), 0, p );
1106 TRACE("(%p %s %d %p): returning %d x %d\n",
1107 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
1108 return ret;
1112 /***********************************************************************
1113 * GetTextExtentPoint32W [GDI32.@]
1115 * Computes width/height for a string.
1117 * Computes width and height of the specified string.
1119 * RETURNS
1120 * Success: TRUE
1121 * Failure: FALSE
1123 BOOL WINAPI GetTextExtentPoint32W(
1124 HDC hdc, /* [in] Handle of device context */
1125 LPCWSTR str, /* [in] Address of text string */
1126 INT count, /* [in] Number of characters in string */
1127 LPSIZE size) /* [out] Address of structure for string size */
1129 return GetTextExtentExPointW(hdc, str, count, 0, NULL, NULL, size);
1132 /***********************************************************************
1133 * GetTextExtentPointI [GDI32.@]
1135 * Computes width and height of the array of glyph indices.
1137 * RETURNS
1138 * Success: TRUE
1139 * Failure: FALSE
1141 BOOL WINAPI GetTextExtentPointI(
1142 HDC hdc, /* [in] Handle of device context */
1143 const WORD *indices, /* [in] Address of glyph index array */
1144 INT count, /* [in] Number of glyphs in array */
1145 LPSIZE size) /* [out] Address of structure for string size */
1147 BOOL ret = FALSE;
1148 DC * dc = DC_GetDCPtr( hdc );
1149 if (!dc) return FALSE;
1151 if(dc->gdiFont) {
1152 ret = WineEngGetTextExtentPointI(dc->gdiFont, indices, count, size);
1153 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1154 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1155 size->cx += count * dc->charExtra;
1157 else if(dc->funcs->pGetTextExtentExPoint) {
1158 FIXME("calling GetTextExtentExPoint\n");
1159 ret = dc->funcs->pGetTextExtentExPoint( dc->physDev, (LPCWSTR)indices,
1160 count, 0, NULL, NULL, size );
1163 DC_ReleaseDCPtr( dc );
1165 TRACE("(%p %p %d %p): returning %d x %d\n",
1166 hdc, indices, count, size, size->cx, size->cy );
1167 return ret;
1171 /***********************************************************************
1172 * GetTextExtentPointA (GDI32.@)
1174 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
1175 LPSIZE size )
1177 TRACE("not bug compatible.\n");
1178 return GetTextExtentPoint32A( hdc, str, count, size );
1181 /***********************************************************************
1182 * GetTextExtentPointW (GDI32.@)
1184 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1185 LPSIZE size )
1187 TRACE("not bug compatible.\n");
1188 return GetTextExtentPoint32W( hdc, str, count, size );
1192 /***********************************************************************
1193 * GetTextExtentExPointA (GDI32.@)
1195 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1196 INT maxExt, LPINT lpnFit,
1197 LPINT alpDx, LPSIZE size )
1199 BOOL ret;
1200 INT wlen;
1201 INT *walpDx = NULL;
1202 LPWSTR p = NULL;
1204 if (alpDx &&
1205 NULL == (walpDx = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT))))
1206 return FALSE;
1208 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1209 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
1210 if (walpDx)
1212 INT n = lpnFit ? *lpnFit : wlen;
1213 INT i, j;
1214 for(i = 0, j = 0; i < n; i++, j++)
1216 alpDx[j] = walpDx[i];
1217 if (IsDBCSLeadByte(str[j])) alpDx[++j] = walpDx[i];
1220 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1221 HeapFree( GetProcessHeap(), 0, p );
1222 HeapFree( GetProcessHeap(), 0, walpDx );
1223 return ret;
1227 /***********************************************************************
1228 * GetTextExtentExPointW (GDI32.@)
1230 * Return the size of the string as it would be if it was output properly by
1231 * e.g. TextOut.
1233 * This should include
1234 * - Intercharacter spacing
1235 * - justification spacing (not yet done)
1236 * - kerning? see below
1238 * Kerning. Since kerning would be carried out by the rendering code it should
1239 * be done by the driver. However they don't support it yet. Also I am not
1240 * yet persuaded that (certainly under Win95) any kerning is actually done.
1242 * str: According to MSDN this should be null-terminated. That is not true; a
1243 * null will not terminate it early.
1244 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1245 * than count. I have seen it be either the size of the full string or
1246 * 1 less than the size of the full string. I have not seen it bear any
1247 * resemblance to the portion that would fit.
1248 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1249 * trailing intercharacter spacing and any trailing justification.
1251 * FIXME
1252 * Currently we do this by measuring each character etc. We should do it by
1253 * passing the request to the driver, perhaps by extending the
1254 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1255 * thinking about kerning issues and rounding issues in the justification.
1258 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1259 INT maxExt, LPINT lpnFit,
1260 LPINT alpDx, LPSIZE size )
1262 INT nFit = 0;
1263 LPINT dxs = NULL;
1264 DC *dc;
1265 BOOL ret = FALSE;
1266 TEXTMETRICW tm;
1268 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1270 dc = DC_GetDCPtr(hdc);
1271 if (! dc)
1272 return FALSE;
1274 GetTextMetricsW(hdc, &tm);
1276 /* If we need to calculate nFit, then we need the partial extents even if
1277 the user hasn't provided us with an array. */
1278 if (lpnFit)
1280 dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]);
1281 if (! dxs)
1283 DC_ReleaseDCPtr(dc);
1284 SetLastError(ERROR_OUTOFMEMORY);
1285 return FALSE;
1288 else
1289 dxs = alpDx;
1291 if (dc->gdiFont)
1292 ret = WineEngGetTextExtentExPoint(dc->gdiFont, str, count,
1293 0, NULL, dxs, size);
1294 else if (dc->funcs->pGetTextExtentExPoint)
1295 ret = dc->funcs->pGetTextExtentExPoint(dc->physDev, str, count,
1296 0, NULL, dxs, size);
1298 /* Perform device size to world size transformations. */
1299 if (ret)
1301 INT extra = dc->charExtra,
1302 breakExtra = dc->breakExtra,
1303 breakRem = dc->breakRem,
1306 if (dxs)
1308 for (i = 0; i < count; ++i)
1310 dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
1311 dxs[i] += (i+1) * extra;
1312 if (count > 1 && (breakExtra || breakRem) && str[i] == tm.tmBreakChar)
1314 dxs[i] += breakExtra;
1315 if (breakRem > 0)
1317 breakRem--;
1318 dxs[i]++;
1321 if (dxs[i] <= maxExt)
1322 ++nFit;
1324 breakRem = dc->breakRem;
1326 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1327 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1329 if (!dxs && count > 1 && (breakExtra || breakRem))
1331 for (i = 0; i < count; i++)
1333 if (str[i] == tm.tmBreakChar)
1335 size->cx += breakExtra;
1336 if (breakRem > 0)
1338 breakRem--;
1339 (size->cx)++;
1346 if (lpnFit)
1347 *lpnFit = nFit;
1349 if (! alpDx)
1350 HeapFree(GetProcessHeap(), 0, dxs);
1352 DC_ReleaseDCPtr( dc );
1354 TRACE("returning %d %d x %d\n",nFit,size->cx,size->cy);
1355 return ret;
1358 /***********************************************************************
1359 * GetTextMetricsA (GDI32.@)
1361 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1363 TEXTMETRICW tm32;
1365 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1366 FONT_TextMetricWToA( &tm32, metrics );
1367 return TRUE;
1370 /***********************************************************************
1371 * GetTextMetricsW (GDI32.@)
1373 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1375 BOOL ret = FALSE;
1376 DC * dc = DC_GetDCPtr( hdc );
1377 if (!dc) return FALSE;
1379 if (dc->gdiFont)
1380 ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1381 else if (dc->funcs->pGetTextMetrics)
1382 ret = dc->funcs->pGetTextMetrics( dc->physDev, metrics );
1384 if (ret)
1386 /* device layer returns values in device units
1387 * therefore we have to convert them to logical */
1389 metrics->tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1390 metrics->tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1392 #define WDPTOLP(x) ((x<0)? \
1393 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1394 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1395 #define HDPTOLP(y) ((y<0)? \
1396 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1397 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1399 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1400 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1401 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1402 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1403 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1404 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1405 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1406 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1407 ret = TRUE;
1408 #undef WDPTOLP
1409 #undef HDPTOLP
1410 TRACE("text metrics:\n"
1411 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1412 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1413 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1414 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1415 " PitchAndFamily = %02x\n"
1416 " --------------------\n"
1417 " InternalLeading = %i\n"
1418 " Ascent = %i\n"
1419 " Descent = %i\n"
1420 " Height = %i\n",
1421 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1422 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1423 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1424 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1425 metrics->tmPitchAndFamily,
1426 metrics->tmInternalLeading,
1427 metrics->tmAscent,
1428 metrics->tmDescent,
1429 metrics->tmHeight );
1431 DC_ReleaseDCPtr( dc );
1432 return ret;
1436 /***********************************************************************
1437 * GetOutlineTextMetrics [GDI.308] Gets metrics for TrueType fonts.
1439 * NOTES
1440 * lpOTM should be LPOUTLINETEXTMETRIC
1442 * RETURNS
1443 * Success: Non-zero or size of required buffer
1444 * Failure: 0
1446 UINT16 WINAPI GetOutlineTextMetrics16(
1447 HDC16 hdc, /* [in] Handle of device context */
1448 UINT16 cbData, /* [in] Size of metric data array */
1449 LPOUTLINETEXTMETRIC16 lpOTM) /* [out] Address of metric data array */
1451 FIXME("(%04x,%04x,%p): stub\n", hdc,cbData,lpOTM);
1452 return 0;
1456 /***********************************************************************
1457 * GetOutlineTextMetricsA (GDI32.@)
1458 * Gets metrics for TrueType fonts.
1460 * NOTES
1461 * If the supplied buffer isn't big enough Windows partially fills it up to
1462 * its given length and returns that length.
1464 * RETURNS
1465 * Success: Non-zero or size of required buffer
1466 * Failure: 0
1468 UINT WINAPI GetOutlineTextMetricsA(
1469 HDC hdc, /* [in] Handle of device context */
1470 UINT cbData, /* [in] Size of metric data array */
1471 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1473 char buf[512], *ptr;
1474 UINT ret, needed;
1475 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1476 OUTLINETEXTMETRICA *output = lpOTM;
1477 INT left, len;
1479 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1480 return 0;
1481 if(ret > sizeof(buf))
1482 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1483 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1485 needed = sizeof(OUTLINETEXTMETRICA);
1486 if(lpOTMW->otmpFamilyName)
1487 needed += WideCharToMultiByte(CP_ACP, 0,
1488 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1489 NULL, 0, NULL, NULL);
1490 if(lpOTMW->otmpFaceName)
1491 needed += WideCharToMultiByte(CP_ACP, 0,
1492 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1493 NULL, 0, NULL, NULL);
1494 if(lpOTMW->otmpStyleName)
1495 needed += WideCharToMultiByte(CP_ACP, 0,
1496 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1497 NULL, 0, NULL, NULL);
1498 if(lpOTMW->otmpFullName)
1499 needed += WideCharToMultiByte(CP_ACP, 0,
1500 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1501 NULL, 0, NULL, NULL);
1503 if(!lpOTM) {
1504 ret = needed;
1505 goto end;
1508 TRACE("needed = %d\n", needed);
1509 if(needed > cbData)
1510 /* Since the supplied buffer isn't big enough, we'll alloc one
1511 that is and memcpy the first cbData bytes into the lpOTM at
1512 the end. */
1513 output = HeapAlloc(GetProcessHeap(), 0, needed);
1515 ret = output->otmSize = min(needed, cbData);
1516 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1517 output->otmFiller = 0;
1518 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1519 output->otmfsSelection = lpOTMW->otmfsSelection;
1520 output->otmfsType = lpOTMW->otmfsType;
1521 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1522 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1523 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1524 output->otmEMSquare = lpOTMW->otmEMSquare;
1525 output->otmAscent = lpOTMW->otmAscent;
1526 output->otmDescent = lpOTMW->otmDescent;
1527 output->otmLineGap = lpOTMW->otmLineGap;
1528 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1529 output->otmsXHeight = lpOTMW->otmsXHeight;
1530 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1531 output->otmMacAscent = lpOTMW->otmMacAscent;
1532 output->otmMacDescent = lpOTMW->otmMacDescent;
1533 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1534 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1535 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1536 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1537 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1538 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1539 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1540 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1541 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1542 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1545 ptr = (char*)(output + 1);
1546 left = needed - sizeof(*output);
1548 if(lpOTMW->otmpFamilyName) {
1549 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1550 len = WideCharToMultiByte(CP_ACP, 0,
1551 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1552 ptr, left, NULL, NULL);
1553 left -= len;
1554 ptr += len;
1555 } else
1556 output->otmpFamilyName = 0;
1558 if(lpOTMW->otmpFaceName) {
1559 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1560 len = WideCharToMultiByte(CP_ACP, 0,
1561 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1562 ptr, left, NULL, NULL);
1563 left -= len;
1564 ptr += len;
1565 } else
1566 output->otmpFaceName = 0;
1568 if(lpOTMW->otmpStyleName) {
1569 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1570 len = WideCharToMultiByte(CP_ACP, 0,
1571 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1572 ptr, left, NULL, NULL);
1573 left -= len;
1574 ptr += len;
1575 } else
1576 output->otmpStyleName = 0;
1578 if(lpOTMW->otmpFullName) {
1579 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1580 len = WideCharToMultiByte(CP_ACP, 0,
1581 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1582 ptr, left, NULL, NULL);
1583 left -= len;
1584 } else
1585 output->otmpFullName = 0;
1587 assert(left == 0);
1589 if(output != lpOTM) {
1590 memcpy(lpOTM, output, cbData);
1591 HeapFree(GetProcessHeap(), 0, output);
1593 /* check if the string offsets really fit into the provided size */
1594 /* FIXME: should we check string length as well? */
1595 /* make sure that we don't read/write beyond the provided buffer */
1596 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(LPSTR))
1598 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1599 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1602 /* make sure that we don't read/write beyond the provided buffer */
1603 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(LPSTR))
1605 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1606 lpOTM->otmpFaceName = 0; /* doesn't fit */
1609 /* make sure that we don't read/write beyond the provided buffer */
1610 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(LPSTR))
1612 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1613 lpOTM->otmpStyleName = 0; /* doesn't fit */
1616 /* make sure that we don't read/write beyond the provided buffer */
1617 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(LPSTR))
1619 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1620 lpOTM->otmpFullName = 0; /* doesn't fit */
1624 end:
1625 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1626 HeapFree(GetProcessHeap(), 0, lpOTMW);
1628 return ret;
1632 /***********************************************************************
1633 * GetOutlineTextMetricsW [GDI32.@]
1635 UINT WINAPI GetOutlineTextMetricsW(
1636 HDC hdc, /* [in] Handle of device context */
1637 UINT cbData, /* [in] Size of metric data array */
1638 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1640 DC *dc = DC_GetDCPtr( hdc );
1641 OUTLINETEXTMETRICW *output = lpOTM;
1642 UINT ret;
1644 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1645 if(!dc) return 0;
1647 if(dc->gdiFont) {
1648 ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, output);
1649 if(lpOTM && ret) {
1650 if(ret > cbData) {
1651 output = HeapAlloc(GetProcessHeap(), 0, ret);
1652 WineEngGetOutlineTextMetrics(dc->gdiFont, ret, output);
1655 #define WDPTOLP(x) ((x<0)? \
1656 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1657 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1658 #define HDPTOLP(y) ((y<0)? \
1659 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1660 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1662 output->otmTextMetrics.tmHeight = HDPTOLP(output->otmTextMetrics.tmHeight);
1663 output->otmTextMetrics.tmAscent = HDPTOLP(output->otmTextMetrics.tmAscent);
1664 output->otmTextMetrics.tmDescent = HDPTOLP(output->otmTextMetrics.tmDescent);
1665 output->otmTextMetrics.tmInternalLeading = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1666 output->otmTextMetrics.tmExternalLeading = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1667 output->otmTextMetrics.tmAveCharWidth = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1668 output->otmTextMetrics.tmMaxCharWidth = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1669 output->otmTextMetrics.tmOverhang = WDPTOLP(output->otmTextMetrics.tmOverhang);
1670 output->otmAscent = HDPTOLP(output->otmAscent);
1671 output->otmDescent = HDPTOLP(output->otmDescent);
1672 output->otmLineGap = HDPTOLP(output->otmLineGap);
1673 output->otmsCapEmHeight = HDPTOLP(output->otmsCapEmHeight);
1674 output->otmsXHeight = HDPTOLP(output->otmsXHeight);
1675 output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1676 output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1677 output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1678 output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1679 output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1680 output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1681 output->otmMacLineGap = HDPTOLP(output->otmMacLineGap);
1682 output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1683 output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1684 output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1685 output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1686 output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1687 output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1688 output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1689 output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1690 output->otmsStrikeoutSize = HDPTOLP(output->otmsStrikeoutSize);
1691 output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1692 output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1693 output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1694 #undef WDPTOLP
1695 #undef HDPTOLP
1696 if(output != lpOTM) {
1697 memcpy(lpOTM, output, cbData);
1698 HeapFree(GetProcessHeap(), 0, output);
1699 ret = cbData;
1704 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1705 but really this should just be a return 0. */
1707 ret = sizeof(*lpOTM);
1708 if (lpOTM) {
1709 if(cbData < ret)
1710 ret = 0;
1711 else {
1712 memset(lpOTM, 0, ret);
1713 lpOTM->otmSize = sizeof(*lpOTM);
1714 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1716 Further fill of the structure not implemented,
1717 Needs real values for the structure members
1722 DC_ReleaseDCPtr(dc);
1723 return ret;
1727 /***********************************************************************
1728 * GetCharWidthW (GDI32.@)
1729 * GetCharWidth32W (GDI32.@)
1731 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1732 LPINT buffer )
1734 UINT i;
1735 BOOL ret = FALSE;
1736 DC * dc = DC_GetDCPtr( hdc );
1737 if (!dc) return FALSE;
1739 if (dc->gdiFont)
1740 ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1741 else if (dc->funcs->pGetCharWidth)
1742 ret = dc->funcs->pGetCharWidth( dc->physDev, firstChar, lastChar, buffer);
1744 if (ret)
1746 /* convert device units to logical */
1747 for( i = firstChar; i <= lastChar; i++, buffer++ )
1748 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1749 ret = TRUE;
1751 DC_ReleaseDCPtr( dc );
1752 return ret;
1756 /***********************************************************************
1757 * GetCharWidthA (GDI32.@)
1758 * GetCharWidth32A (GDI32.@)
1760 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1761 LPINT buffer )
1763 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1764 LPSTR str;
1765 LPWSTR wstr;
1766 BOOL ret = TRUE;
1768 if(count <= 0) return FALSE;
1770 str = HeapAlloc(GetProcessHeap(), 0, count);
1771 for(i = 0; i < count; i++)
1772 str[i] = (BYTE)(firstChar + i);
1774 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1776 for(i = 0; i < wlen; i++)
1778 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1780 ret = FALSE;
1781 break;
1783 buffer++;
1786 HeapFree(GetProcessHeap(), 0, str);
1787 HeapFree(GetProcessHeap(), 0, wstr);
1789 return ret;
1793 /***********************************************************************
1794 * ExtTextOutA (GDI32.@)
1796 * See ExtTextOutW.
1798 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1799 const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1801 INT wlen;
1802 UINT codepage;
1803 LPWSTR p;
1804 BOOL ret;
1805 LPINT lpDxW = NULL;
1807 if (flags & ETO_GLYPH_INDEX)
1808 return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
1810 p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
1812 if (lpDx) {
1813 unsigned int i = 0, j = 0;
1815 lpDxW = HeapAlloc( GetProcessHeap(), 0, wlen*sizeof(INT));
1816 while(i < count) {
1817 if(IsDBCSLeadByteEx(codepage, str[i])) {
1818 lpDxW[j++] = lpDx[i] + lpDx[i+1];
1819 i = i + 2;
1820 } else {
1821 lpDxW[j++] = lpDx[i];
1822 i = i + 1;
1827 ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1829 HeapFree( GetProcessHeap(), 0, p );
1830 HeapFree( GetProcessHeap(), 0, lpDxW );
1831 return ret;
1835 /***********************************************************************
1836 * ExtTextOutW (GDI32.@)
1838 * Draws text using the currently selected font, background color, and text color.
1841 * PARAMS
1842 * x,y [I] coordinates of string
1843 * flags [I]
1844 * ETO_GRAYED - undocumented on MSDN
1845 * ETO_OPAQUE - use background color for fill the rectangle
1846 * ETO_CLIPPED - clipping text to the rectangle
1847 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1848 * than encoded characters. Implies ETO_IGNORELANGUAGE
1849 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1850 * Affects BiDi ordering
1851 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1852 * ETO_PDY - unimplemented
1853 * ETO_NUMERICSLATIN - unimplemented always assumed -
1854 * do not translate numbers into locale representations
1855 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1856 * lprect [I] dimensions for clipping or/and opaquing
1857 * str [I] text string
1858 * count [I] number of symbols in string
1859 * lpDx [I] optional parameter with distance between drawing characters
1861 * RETURNS
1862 * Success: TRUE
1863 * Failure: FALSE
1865 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1866 const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1868 BOOL ret = FALSE;
1869 LPWSTR reordered_str = (LPWSTR)str;
1870 WORD *glyphs = NULL;
1871 UINT align = GetTextAlign( hdc );
1872 POINT pt;
1873 TEXTMETRICW tm;
1874 LOGFONTW lf;
1875 double cosEsc, sinEsc;
1876 INT *deltas = NULL, char_extra;
1877 SIZE sz;
1878 RECT rc;
1879 BOOL done_extents = FALSE;
1880 INT width = 0, xwidth = 0, ywidth = 0;
1881 DWORD type;
1882 DC * dc = DC_GetDCUpdate( hdc );
1883 INT breakRem;
1885 if (!dc) return FALSE;
1887 breakRem = dc->breakRem;
1889 if (flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY))
1890 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY unimplemented\n");
1892 if (!dc->funcs->pExtTextOut && !PATH_IsPathOpen(dc->path))
1894 DC_ReleaseDCPtr( dc );
1895 return ret;
1898 type = GetObjectType(hdc);
1899 if(type == OBJ_METADC || type == OBJ_ENHMETADC)
1901 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, flags, lprect, str, count, lpDx);
1902 DC_ReleaseDCPtr( dc );
1903 return ret;
1906 if (!lprect)
1907 flags &= ~ETO_CLIPPED;
1909 if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && BidiAvail && count > 0 )
1911 reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1913 BIDI_Reorder( str, count, GCP_REORDER,
1914 ((flags&ETO_RTLREADING)!=0 || (GetTextAlign(hdc)&TA_RTLREADING)!=0)?
1915 WINE_GCPW_FORCE_RTL:WINE_GCPW_FORCE_LTR,
1916 reordered_str, count, NULL );
1918 flags |= ETO_IGNORELANGUAGE;
1921 TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc, x, y, flags,
1922 lprect, debugstr_wn(str, count), count, lpDx);
1924 if(flags & ETO_GLYPH_INDEX)
1925 glyphs = reordered_str;
1927 if(lprect)
1928 TRACE("rect: %d,%d - %d,%d\n", lprect->left, lprect->top, lprect->right,
1929 lprect->bottom);
1930 TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
1932 if(align & TA_UPDATECP)
1934 GetCurrentPositionEx( hdc, &pt );
1935 x = pt.x;
1936 y = pt.y;
1939 GetTextMetricsW(hdc, &tm);
1940 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1942 if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
1943 lf.lfEscapement = 0;
1945 if(lf.lfEscapement != 0)
1947 cosEsc = cos(lf.lfEscapement * M_PI / 1800);
1948 sinEsc = sin(lf.lfEscapement * M_PI / 1800);
1950 else
1952 cosEsc = 1;
1953 sinEsc = 0;
1956 if(flags & (ETO_CLIPPED | ETO_OPAQUE))
1958 if(!lprect)
1960 if(flags & ETO_GLYPH_INDEX)
1961 GetTextExtentPointI(hdc, glyphs, count, &sz);
1962 else
1963 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1965 done_extents = TRUE;
1966 rc.left = x;
1967 rc.top = y;
1968 rc.right = x + sz.cx;
1969 rc.bottom = y + sz.cy;
1971 else
1973 rc = *lprect;
1976 LPtoDP(hdc, (POINT*)&rc, 2);
1978 if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
1979 if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
1982 if ((flags & ETO_OPAQUE) && !PATH_IsPathOpen(dc->path))
1983 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1985 if(count == 0)
1987 ret = TRUE;
1988 goto done;
1991 pt.x = x;
1992 pt.y = y;
1993 LPtoDP(hdc, &pt, 1);
1994 x = pt.x;
1995 y = pt.y;
1997 char_extra = GetTextCharacterExtra(hdc);
1998 if(char_extra || dc->breakExtra || breakRem || lpDx || lf.lfEscapement != 0)
2000 UINT i;
2001 SIZE tmpsz;
2002 deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT));
2003 for(i = 0; i < count; i++)
2005 if(lpDx && (flags & ETO_PDY))
2006 deltas[i] = lpDx[i*2] + char_extra;
2007 else if(lpDx)
2008 deltas[i] = lpDx[i] + char_extra;
2009 else
2011 if(flags & ETO_GLYPH_INDEX)
2012 GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
2013 else
2014 GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
2016 deltas[i] = tmpsz.cx;
2019 if (!(flags & ETO_GLYPH_INDEX) && (dc->breakExtra || breakRem) && reordered_str[i] == tm.tmBreakChar)
2021 deltas[i] = deltas[i] + dc->breakExtra;
2022 if (breakRem > 0)
2024 breakRem--;
2025 deltas[i]++;
2028 deltas[i] = INTERNAL_XWSTODS(dc, deltas[i]);
2029 width += deltas[i];
2032 else
2034 if(!done_extents)
2036 if(flags & ETO_GLYPH_INDEX)
2037 GetTextExtentPointI(hdc, glyphs, count, &sz);
2038 else
2039 GetTextExtentPointW(hdc, reordered_str, count, &sz);
2040 done_extents = TRUE;
2042 width = INTERNAL_XWSTODS(dc, sz.cx);
2044 xwidth = width * cosEsc;
2045 ywidth = width * sinEsc;
2047 tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
2048 tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
2049 switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
2051 case TA_LEFT:
2052 if (align & TA_UPDATECP)
2054 pt.x = x + xwidth;
2055 pt.y = y - ywidth;
2056 DPtoLP(hdc, &pt, 1);
2057 MoveToEx(hdc, pt.x, pt.y, NULL);
2059 break;
2061 case TA_CENTER:
2062 x -= xwidth / 2;
2063 y += ywidth / 2;
2064 break;
2066 case TA_RIGHT:
2067 x -= xwidth;
2068 y += ywidth;
2069 if (align & TA_UPDATECP)
2071 pt.x = x;
2072 pt.y = y;
2073 DPtoLP(hdc, &pt, 1);
2074 MoveToEx(hdc, pt.x, pt.y, NULL);
2076 break;
2079 switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
2081 case TA_TOP:
2082 y += tm.tmAscent * cosEsc;
2083 x += tm.tmAscent * sinEsc;
2084 break;
2086 case TA_BOTTOM:
2087 y -= tm.tmDescent * cosEsc;
2088 x -= tm.tmDescent * sinEsc;
2089 break;
2091 case TA_BASELINE:
2092 break;
2095 if (GetBkMode(hdc) != TRANSPARENT && !PATH_IsPathOpen(dc->path))
2097 if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
2099 if(!(flags & ETO_OPAQUE) || x < rc.left || x + width >= rc.right ||
2100 y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
2102 RECT rc;
2103 rc.left = x;
2104 rc.right = x + width;
2105 rc.top = y - tm.tmAscent;
2106 rc.bottom = y + tm.tmDescent;
2107 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
2112 if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
2114 HFONT orig_font = dc->hFont, cur_font;
2115 UINT glyph;
2116 INT span = 0, *offsets = NULL, i;
2118 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2119 for(i = 0; i < count; i++)
2121 WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
2122 if(cur_font != dc->hFont)
2124 if(!offsets)
2126 int j;
2127 offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
2128 offsets[0] = 0;
2129 if(!deltas)
2131 SIZE tmpsz;
2132 for(j = 1; j < count; j++)
2134 GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
2135 offsets[j] = offsets[j-1] + INTERNAL_XWSTODS(dc, tmpsz.cx);
2138 else
2140 for(j = 1; j < count; j++)
2141 offsets[j] = offsets[j-1] + deltas[j];
2144 if(span)
2146 if (PATH_IsPathOpen(dc->path))
2147 ret = PATH_ExtTextOut(dc, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
2148 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2149 glyphs, span, deltas ? deltas + i - span : NULL);
2150 else
2151 dc->funcs->pExtTextOut(dc->physDev, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
2152 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2153 glyphs, span, deltas ? deltas + i - span : NULL);
2154 span = 0;
2156 SelectObject(hdc, cur_font);
2158 glyphs[span++] = glyph;
2160 if(i == count - 1)
2162 if (PATH_IsPathOpen(dc->path))
2163 ret = PATH_ExtTextOut(dc, x + (offsets ? offsets[count - span] * cosEsc : 0),
2164 y - (offsets ? offsets[count - span] * sinEsc : 0),
2165 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2166 glyphs, span, deltas ? deltas + count - span : NULL);
2167 else
2168 ret = dc->funcs->pExtTextOut(dc->physDev, x + (offsets ? offsets[count - span] * cosEsc : 0),
2169 y - (offsets ? offsets[count - span] * sinEsc : 0),
2170 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2171 glyphs, span, deltas ? deltas + count - span : NULL);
2172 SelectObject(hdc, orig_font);
2173 HeapFree(GetProcessHeap(), 0, offsets);
2177 else
2179 if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
2181 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2182 GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
2183 flags |= ETO_GLYPH_INDEX;
2186 if (PATH_IsPathOpen(dc->path))
2187 ret = PATH_ExtTextOut(dc, x, y, (flags & ~ETO_OPAQUE), &rc,
2188 glyphs ? glyphs : reordered_str, count, deltas);
2189 else
2190 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, (flags & ~ETO_OPAQUE), &rc,
2191 glyphs ? glyphs : reordered_str, count, deltas);
2194 done:
2195 HeapFree(GetProcessHeap(), 0, deltas);
2196 if(glyphs != reordered_str)
2197 HeapFree(GetProcessHeap(), 0, glyphs);
2198 if(reordered_str != str)
2199 HeapFree(GetProcessHeap(), 0, reordered_str);
2201 DC_ReleaseDCPtr( dc );
2203 if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2205 int underlinePos, strikeoutPos;
2206 int underlineWidth, strikeoutWidth;
2207 UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2208 OUTLINETEXTMETRICW* otm = NULL;
2210 if(!size)
2212 underlinePos = 0;
2213 underlineWidth = tm.tmAscent / 20 + 1;
2214 strikeoutPos = tm.tmAscent / 2;
2215 strikeoutWidth = underlineWidth;
2217 else
2219 otm = HeapAlloc(GetProcessHeap(), 0, size);
2220 GetOutlineTextMetricsW(hdc, size, otm);
2221 underlinePos = otm->otmsUnderscorePosition;
2222 underlineWidth = otm->otmsUnderscoreSize;
2223 strikeoutPos = otm->otmsStrikeoutPosition;
2224 strikeoutWidth = otm->otmsStrikeoutSize;
2225 HeapFree(GetProcessHeap(), 0, otm);
2228 if (PATH_IsPathOpen(dc->path))
2230 POINT pts[5];
2231 HPEN hpen;
2232 HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2234 hbrush = SelectObject(hdc, hbrush);
2235 hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2237 if (lf.lfUnderline)
2239 pts[0].x = x - underlinePos * sinEsc;
2240 pts[0].y = y - underlinePos * cosEsc;
2241 pts[1].x = x + xwidth - underlinePos * sinEsc;
2242 pts[1].y = y - ywidth - underlinePos * cosEsc;
2243 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2244 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2245 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2246 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2247 pts[4].x = pts[0].x;
2248 pts[4].y = pts[0].y;
2249 DPtoLP(hdc, pts, 5);
2250 Polygon(hdc, pts, 5);
2253 if (lf.lfStrikeOut)
2255 pts[0].x = x - strikeoutPos * sinEsc;
2256 pts[0].y = y - strikeoutPos * cosEsc;
2257 pts[1].x = x + xwidth - strikeoutPos * sinEsc;
2258 pts[1].y = y - ywidth - strikeoutPos * cosEsc;
2259 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2260 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2261 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2262 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2263 pts[4].x = pts[0].x;
2264 pts[4].y = pts[0].y;
2265 DPtoLP(hdc, pts, 5);
2266 Polygon(hdc, pts, 5);
2269 SelectObject(hdc, hpen);
2270 hbrush = SelectObject(hdc, hbrush);
2271 DeleteObject(hbrush);
2273 else
2275 POINT pts[2], oldpt;
2276 HPEN hpen;
2278 if (lf.lfUnderline)
2280 hpen = CreatePen(PS_SOLID, underlineWidth, GetTextColor(hdc));
2281 hpen = SelectObject(hdc, hpen);
2282 pts[0].x = x;
2283 pts[0].y = y;
2284 pts[1].x = x + xwidth;
2285 pts[1].y = y - ywidth;
2286 DPtoLP(hdc, pts, 2);
2287 MoveToEx(hdc, pts[0].x - underlinePos * sinEsc, pts[0].y - underlinePos * cosEsc, &oldpt);
2288 LineTo(hdc, pts[1].x - underlinePos * sinEsc, pts[1].y - underlinePos * cosEsc);
2289 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2290 DeleteObject(SelectObject(hdc, hpen));
2293 if (lf.lfStrikeOut)
2295 hpen = CreatePen(PS_SOLID, strikeoutWidth, GetTextColor(hdc));
2296 hpen = SelectObject(hdc, hpen);
2297 pts[0].x = x;
2298 pts[0].y = y;
2299 pts[1].x = x + xwidth;
2300 pts[1].y = y - ywidth;
2301 DPtoLP(hdc, pts, 2);
2302 MoveToEx(hdc, pts[0].x - strikeoutPos * sinEsc, pts[0].y - strikeoutPos * cosEsc, &oldpt);
2303 LineTo(hdc, pts[1].x - strikeoutPos * sinEsc, pts[1].y - strikeoutPos * cosEsc);
2304 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2305 DeleteObject(SelectObject(hdc, hpen));
2310 return ret;
2314 /***********************************************************************
2315 * TextOutA (GDI32.@)
2317 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2319 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2323 /***********************************************************************
2324 * TextOutW (GDI32.@)
2326 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2328 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2332 /***********************************************************************
2333 * PolyTextOutA (GDI32.@)
2335 * See PolyTextOutW.
2337 BOOL WINAPI PolyTextOutA( HDC hdc, const POLYTEXTA *pptxt, INT cStrings )
2339 for (; cStrings>0; cStrings--, pptxt++)
2340 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2341 return FALSE;
2342 return TRUE;
2347 /***********************************************************************
2348 * PolyTextOutW (GDI32.@)
2350 * Draw several Strings
2352 * RETURNS
2353 * TRUE: Success.
2354 * FALSE: Failure.
2356 BOOL WINAPI PolyTextOutW( HDC hdc, const POLYTEXTW *pptxt, INT cStrings )
2358 for (; cStrings>0; cStrings--, pptxt++)
2359 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2360 return FALSE;
2361 return TRUE;
2365 /* FIXME: all following APIs ******************************************/
2368 /***********************************************************************
2369 * SetMapperFlags (GDI32.@)
2371 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
2373 DC *dc = DC_GetDCPtr( hDC );
2374 DWORD ret = 0;
2375 if(!dc) return 0;
2376 if(dc->funcs->pSetMapperFlags)
2378 ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
2379 /* FIXME: ret is just a success flag, we should return a proper value */
2381 else
2382 FIXME("(%p, 0x%08x): stub - harmless\n", hDC, dwFlag);
2383 DC_ReleaseDCPtr( dc );
2384 return ret;
2387 /***********************************************************************
2388 * GetAspectRatioFilterEx (GDI.486)
2390 BOOL16 WINAPI GetAspectRatioFilterEx16( HDC16 hdc, LPSIZE16 pAspectRatio )
2392 FIXME("(%04x, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2393 return FALSE;
2396 /***********************************************************************
2397 * GetAspectRatioFilterEx (GDI32.@)
2399 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2401 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2402 return FALSE;
2406 /***********************************************************************
2407 * GetCharABCWidthsA (GDI32.@)
2409 * See GetCharABCWidthsW.
2411 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2412 LPABC abc )
2414 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
2415 LPSTR str;
2416 LPWSTR wstr;
2417 BOOL ret = TRUE;
2419 if(count <= 0) return FALSE;
2421 str = HeapAlloc(GetProcessHeap(), 0, count);
2422 for(i = 0; i < count; i++)
2423 str[i] = (BYTE)(firstChar + i);
2425 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
2427 for(i = 0; i < wlen; i++)
2429 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2431 ret = FALSE;
2432 break;
2434 abc++;
2437 HeapFree(GetProcessHeap(), 0, str);
2438 HeapFree(GetProcessHeap(), 0, wstr);
2440 return ret;
2444 /******************************************************************************
2445 * GetCharABCWidthsW [GDI32.@]
2447 * Retrieves widths of characters in range.
2449 * PARAMS
2450 * hdc [I] Handle of device context
2451 * firstChar [I] First character in range to query
2452 * lastChar [I] Last character in range to query
2453 * abc [O] Address of character-width structure
2455 * NOTES
2456 * Only works with TrueType fonts
2458 * RETURNS
2459 * Success: TRUE
2460 * Failure: FALSE
2462 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2463 LPABC abc )
2465 DC *dc = DC_GetDCPtr(hdc);
2466 unsigned int i;
2467 BOOL ret = FALSE;
2469 if (!dc) return FALSE;
2471 if(dc->gdiFont)
2472 ret = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
2473 else
2474 FIXME(": stub\n");
2476 if (ret)
2478 /* convert device units to logical */
2479 for( i = firstChar; i <= lastChar; i++, abc++ ) {
2480 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2481 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2482 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2484 ret = TRUE;
2487 DC_ReleaseDCPtr( dc );
2488 return ret;
2492 /******************************************************************************
2493 * GetCharABCWidthsI [GDI32.@]
2495 * Retrieves widths of characters in range.
2497 * PARAMS
2498 * hdc [I] Handle of device context
2499 * firstChar [I] First glyphs in range to query
2500 * count [I] Last glyphs in range to query
2501 * pgi [i] Array of glyphs to query
2502 * abc [O] Address of character-width structure
2504 * NOTES
2505 * Only works with TrueType fonts
2507 * RETURNS
2508 * Success: TRUE
2509 * Failure: FALSE
2511 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2512 LPWORD pgi, LPABC abc)
2514 DC *dc = DC_GetDCPtr(hdc);
2515 unsigned int i;
2516 BOOL ret = FALSE;
2518 if (!dc) return FALSE;
2520 if(dc->gdiFont)
2521 ret = WineEngGetCharABCWidthsI( dc->gdiFont, firstChar, count, pgi, abc );
2522 else
2523 FIXME(": stub\n");
2525 if (ret)
2527 /* convert device units to logical */
2528 for( i = 0; i < count; i++, abc++ ) {
2529 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2530 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2531 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2533 ret = TRUE;
2536 DC_ReleaseDCPtr( dc );
2537 return ret;
2541 /***********************************************************************
2542 * GetGlyphOutlineA (GDI32.@)
2544 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2545 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2546 LPVOID lpBuffer, const MAT2 *lpmat2 )
2548 LPWSTR p = NULL;
2549 DWORD ret;
2550 UINT c;
2552 if(!(fuFormat & GGO_GLYPH_INDEX)) {
2553 int len;
2554 char mbchs[2];
2555 if(uChar > 0xff) { /* but, 2 bytes character only */
2556 len = 2;
2557 mbchs[0] = (uChar & 0xff00) >> 8;
2558 mbchs[1] = (uChar & 0xff);
2559 } else {
2560 len = 1;
2561 mbchs[0] = (uChar & 0xff);
2563 p = FONT_mbtowc(hdc, mbchs, len, NULL, NULL);
2564 c = p[0];
2565 } else
2566 c = uChar;
2567 ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
2568 lpmat2);
2569 HeapFree(GetProcessHeap(), 0, p);
2570 return ret;
2573 /***********************************************************************
2574 * GetGlyphOutlineW (GDI32.@)
2576 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2577 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2578 LPVOID lpBuffer, const MAT2 *lpmat2 )
2580 DC *dc = DC_GetDCPtr(hdc);
2581 DWORD ret;
2583 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2584 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2586 if(!dc) return GDI_ERROR;
2588 if(dc->gdiFont)
2589 ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
2590 cbBuffer, lpBuffer, lpmat2);
2591 else
2592 ret = GDI_ERROR;
2594 DC_ReleaseDCPtr( dc );
2595 return ret;
2599 /***********************************************************************
2600 * CreateScalableFontResourceA (GDI32.@)
2602 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2603 LPCSTR lpszResourceFile,
2604 LPCSTR lpszFontFile,
2605 LPCSTR lpszCurrentPath )
2607 HANDLE f;
2609 /* fHidden=1 - only visible for the calling app, read-only, not
2610 * enumbered with EnumFonts/EnumFontFamilies
2611 * lpszCurrentPath can be NULL
2613 FIXME("(%d,%s,%s,%s): stub\n",
2614 fHidden, debugstr_a(lpszResourceFile), debugstr_a(lpszFontFile),
2615 debugstr_a(lpszCurrentPath) );
2617 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2618 if ((f = CreateFileA(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2619 CloseHandle(f);
2620 SetLastError(ERROR_FILE_EXISTS);
2621 return FALSE;
2623 return FALSE; /* create failed */
2626 /***********************************************************************
2627 * CreateScalableFontResourceW (GDI32.@)
2629 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2630 LPCWSTR lpszResourceFile,
2631 LPCWSTR lpszFontFile,
2632 LPCWSTR lpszCurrentPath )
2634 FIXME("(%d,%p,%p,%p): stub\n",
2635 fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
2636 return FALSE; /* create failed */
2639 /*************************************************************************
2640 * GetKerningPairsA (GDI32.@)
2642 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2643 LPKERNINGPAIR kern_pairA )
2645 INT charset;
2646 CHARSETINFO csi;
2647 CPINFO cpi;
2648 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2649 KERNINGPAIR *kern_pairW;
2651 if (!cPairs && kern_pairA)
2653 SetLastError(ERROR_INVALID_PARAMETER);
2654 return 0;
2657 charset = GetTextCharset(hDC);
2658 if (!TranslateCharsetInfo(ULongToPtr(charset), &csi, TCI_SRCCHARSET))
2660 FIXME("Can't find codepage for charset %d\n", charset);
2661 return 0;
2663 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2664 * to fail on an invalid character for CP_SYMBOL.
2666 cpi.DefaultChar[0] = 0;
2667 if (csi.ciACP != CP_SYMBOL && !GetCPInfo(csi.ciACP, &cpi))
2669 FIXME("Can't find codepage %u info\n", csi.ciACP);
2670 return 0;
2672 TRACE("charset %d => codepage %u\n", charset, csi.ciACP);
2674 total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2675 if (!total_kern_pairs) return 0;
2677 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2678 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2680 for (i = 0; i < total_kern_pairs; i++)
2682 char first, second;
2684 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2685 continue;
2687 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2688 continue;
2690 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2691 continue;
2693 if (kern_pairA)
2695 if (kern_pairs_copied >= cPairs) break;
2697 kern_pairA->wFirst = (BYTE)first;
2698 kern_pairA->wSecond = (BYTE)second;
2699 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2700 kern_pairA++;
2702 kern_pairs_copied++;
2705 HeapFree(GetProcessHeap(), 0, kern_pairW);
2707 return kern_pairs_copied;
2710 /*************************************************************************
2711 * GetKerningPairsW (GDI32.@)
2713 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2714 LPKERNINGPAIR lpKerningPairs )
2716 DC *dc;
2717 DWORD ret = 0;
2719 TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2721 if (!cPairs && lpKerningPairs)
2723 SetLastError(ERROR_INVALID_PARAMETER);
2724 return 0;
2727 dc = DC_GetDCPtr(hDC);
2728 if (!dc) return 0;
2730 if (dc->gdiFont)
2731 ret = WineEngGetKerningPairs(dc->gdiFont, cPairs, lpKerningPairs);
2733 DC_ReleaseDCPtr( dc );
2734 return ret;
2737 /*************************************************************************
2738 * TranslateCharsetInfo [GDI32.@]
2740 * Fills a CHARSETINFO structure for a character set, code page, or
2741 * font. This allows making the correspondance between different labelings
2742 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2743 * of the same encoding.
2745 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2746 * only one codepage should be set in *lpSrc.
2748 * RETURNS
2749 * TRUE on success, FALSE on failure.
2752 BOOL WINAPI TranslateCharsetInfo(
2753 LPDWORD lpSrc, /* [in]
2754 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2755 if flags == TCI_SRCCHARSET: a character set value
2756 if flags == TCI_SRCCODEPAGE: a code page value
2758 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2759 DWORD flags /* [in] determines interpretation of lpSrc */)
2761 int index = 0;
2762 switch (flags) {
2763 case TCI_SRCFONTSIG:
2764 while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
2765 break;
2766 case TCI_SRCCODEPAGE:
2767 while (PtrToUlong(lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
2768 break;
2769 case TCI_SRCCHARSET:
2770 while (PtrToUlong(lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
2771 break;
2772 default:
2773 return FALSE;
2775 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2776 memcpy(lpCs, &FONT_tci[index], sizeof(CHARSETINFO));
2777 return TRUE;
2780 /*************************************************************************
2781 * GetFontLanguageInfo (GDI32.@)
2783 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2785 FONTSIGNATURE fontsig;
2786 static const DWORD GCP_DBCS_MASK=0x003F0000,
2787 GCP_DIACRITIC_MASK=0x00000000,
2788 FLI_GLYPHS_MASK=0x00000000,
2789 GCP_GLYPHSHAPE_MASK=0x00000040,
2790 GCP_KASHIDA_MASK=0x00000000,
2791 GCP_LIGATE_MASK=0x00000000,
2792 GCP_USEKERNING_MASK=0x00000000,
2793 GCP_REORDER_MASK=0x00000060;
2795 DWORD result=0;
2797 GetTextCharsetInfo( hdc, &fontsig, 0 );
2798 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2800 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2801 result|=GCP_DBCS;
2803 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2804 result|=GCP_DIACRITIC;
2806 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2807 result|=FLI_GLYPHS;
2809 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2810 result|=GCP_GLYPHSHAPE;
2812 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2813 result|=GCP_KASHIDA;
2815 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2816 result|=GCP_LIGATE;
2818 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2819 result|=GCP_USEKERNING;
2821 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2822 if( GetTextAlign( hdc) & TA_RTLREADING )
2823 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2824 result|=GCP_REORDER;
2826 return result;
2830 /*************************************************************************
2831 * GetFontData [GDI32.@]
2833 * Retrieve data for TrueType font.
2835 * RETURNS
2837 * success: Number of bytes returned
2838 * failure: GDI_ERROR
2840 * NOTES
2842 * Calls SetLastError()
2845 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2846 LPVOID buffer, DWORD length)
2848 DC *dc = DC_GetDCPtr(hdc);
2849 DWORD ret = GDI_ERROR;
2851 if(!dc) return GDI_ERROR;
2853 if(dc->gdiFont)
2854 ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2856 DC_ReleaseDCPtr( dc );
2857 return ret;
2860 /*************************************************************************
2861 * GetGlyphIndicesA [GDI32.@]
2863 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2864 LPWORD pgi, DWORD flags)
2866 DWORD ret;
2867 WCHAR *lpstrW;
2868 INT countW;
2870 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2871 hdc, debugstr_an(lpstr, count), count, pgi, flags);
2873 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2874 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2875 HeapFree(GetProcessHeap(), 0, lpstrW);
2877 return ret;
2880 /*************************************************************************
2881 * GetGlyphIndicesW [GDI32.@]
2883 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2884 LPWORD pgi, DWORD flags)
2886 DC *dc = DC_GetDCPtr(hdc);
2887 DWORD ret = GDI_ERROR;
2889 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2890 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2892 if(!dc) return GDI_ERROR;
2894 if(dc->gdiFont)
2895 ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2897 DC_ReleaseDCPtr( dc );
2898 return ret;
2901 /*************************************************************************
2902 * GetCharacterPlacementA [GDI32.@]
2904 * See GetCharacterPlacementW.
2906 * NOTES:
2907 * the web browser control of ie4 calls this with dwFlags=0
2909 DWORD WINAPI
2910 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2911 INT nMaxExtent, GCP_RESULTSA *lpResults,
2912 DWORD dwFlags)
2914 WCHAR *lpStringW;
2915 INT uCountW;
2916 GCP_RESULTSW resultsW;
2917 DWORD ret;
2918 UINT font_cp;
2920 TRACE("%s, %d, %d, 0x%08x\n",
2921 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2923 /* both structs are equal in size */
2924 memcpy(&resultsW, lpResults, sizeof(resultsW));
2926 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2927 if(lpResults->lpOutString)
2928 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2930 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2932 lpResults->nGlyphs = resultsW.nGlyphs;
2933 lpResults->nMaxFit = resultsW.nMaxFit;
2935 if(lpResults->lpOutString) {
2936 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2937 lpResults->lpOutString, uCount, NULL, NULL );
2940 HeapFree(GetProcessHeap(), 0, lpStringW);
2941 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2943 return ret;
2946 /*************************************************************************
2947 * GetCharacterPlacementW [GDI32.@]
2949 * Retrieve information about a string. This includes the width, reordering,
2950 * Glyphing and so on.
2952 * RETURNS
2954 * The width and height of the string if successful, 0 if failed.
2956 * BUGS
2958 * All flags except GCP_REORDER are not yet implemented.
2959 * Reordering is not 100% complient to the Windows BiDi method.
2960 * Caret positioning is not yet implemented for BiDi.
2961 * Classes are not yet implemented.
2964 DWORD WINAPI
2965 GetCharacterPlacementW(
2966 HDC hdc, /* [in] Device context for which the rendering is to be done */
2967 LPCWSTR lpString, /* [in] The string for which information is to be returned */
2968 INT uCount, /* [in] Number of WORDS in string. */
2969 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
2970 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2971 DWORD dwFlags /* [in] Flags specifying how to process the string */
2974 DWORD ret=0;
2975 SIZE size;
2976 UINT i, nSet;
2978 TRACE("%s, %d, %d, 0x%08x\n",
2979 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2981 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2982 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2983 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2984 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2985 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2987 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08x ignored\n", dwFlags);
2988 if(lpResults->lpClass) FIXME("classes not implemented\n");
2989 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2990 FIXME("Caret positions for complex scripts not implemented\n");
2992 nSet = (UINT)uCount;
2993 if(nSet > lpResults->nGlyphs)
2994 nSet = lpResults->nGlyphs;
2996 /* return number of initialized fields */
2997 lpResults->nGlyphs = nSet;
2999 if((dwFlags&GCP_REORDER)==0 || !BidiAvail)
3001 /* Treat the case where no special handling was requested in a fastpath way */
3002 /* copy will do if the GCP_REORDER flag is not set */
3003 if(lpResults->lpOutString)
3004 memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
3006 if(lpResults->lpOrder)
3008 for(i = 0; i < nSet; i++)
3009 lpResults->lpOrder[i] = i;
3011 } else
3013 BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
3014 nSet, lpResults->lpOrder );
3017 /* FIXME: Will use the placement chars */
3018 if (lpResults->lpDx)
3020 int c;
3021 for (i = 0; i < nSet; i++)
3023 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
3024 lpResults->lpDx[i]= c;
3028 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
3030 int pos = 0;
3032 lpResults->lpCaretPos[0] = 0;
3033 for (i = 1; i < nSet; i++)
3034 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
3035 lpResults->lpCaretPos[i] = (pos += size.cx);
3038 if(lpResults->lpGlyphs)
3039 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
3041 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
3042 ret = MAKELONG(size.cx, size.cy);
3044 return ret;
3047 /*************************************************************************
3048 * GetCharABCWidthsFloatA [GDI32.@]
3050 * See GetCharABCWidthsFloatW.
3052 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3054 INT i, wlen, count = (INT)(last - first + 1);
3055 LPSTR str;
3056 LPWSTR wstr;
3057 BOOL ret = TRUE;
3059 if (count <= 0) return FALSE;
3061 str = HeapAlloc(GetProcessHeap(), 0, count);
3063 for(i = 0; i < count; i++)
3064 str[i] = (BYTE)(first + i);
3066 wstr = FONT_mbtowc( hdc, str, count, &wlen, NULL );
3068 for (i = 0; i < wlen; i++)
3070 if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
3072 ret = FALSE;
3073 break;
3075 abcf++;
3078 HeapFree( GetProcessHeap(), 0, str );
3079 HeapFree( GetProcessHeap(), 0, wstr );
3081 return ret;
3084 /*************************************************************************
3085 * GetCharABCWidthsFloatW [GDI32.@]
3087 * Retrieves widths of a range of characters.
3089 * PARAMS
3090 * hdc [I] Handle to device context.
3091 * first [I] First character in range to query.
3092 * last [I] Last character in range to query.
3093 * abcf [O] Array of LPABCFLOAT structures.
3095 * RETURNS
3096 * Success: TRUE
3097 * Failure: FALSE
3099 * BUGS
3100 * Only works with TrueType fonts. It also doesn't return real
3101 * floats but converted integers because it's implemented on
3102 * top of GetCharABCWidthsW.
3104 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3106 ABC *abc;
3107 unsigned int i, size = sizeof(ABC) * (last - first + 1);
3108 BOOL ret;
3110 TRACE("%p, %d, %d, %p - partial stub\n", hdc, first, last, abcf);
3112 abc = HeapAlloc( GetProcessHeap(), 0, size );
3113 if (!abc) return FALSE;
3115 ret = GetCharABCWidthsW( hdc, first, last, abc );
3116 if (ret)
3118 for (i = first; i <= last; i++, abc++, abcf++)
3120 abcf->abcfA = abc->abcA;
3121 abcf->abcfB = abc->abcB;
3122 abcf->abcfC = abc->abcC;
3125 HeapFree( GetProcessHeap(), 0, abc );
3126 return ret;
3129 /*************************************************************************
3130 * GetCharWidthFloatA [GDI32.@]
3132 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
3133 UINT iLastChar, PFLOAT pxBuffer)
3135 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3136 return 0;
3139 /*************************************************************************
3140 * GetCharWidthFloatW [GDI32.@]
3142 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
3143 UINT iLastChar, PFLOAT pxBuffer)
3145 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3146 return 0;
3150 /***********************************************************************
3152 * Font Resource API *
3154 ***********************************************************************/
3156 /***********************************************************************
3157 * AddFontResourceA (GDI32.@)
3159 INT WINAPI AddFontResourceA( LPCSTR str )
3161 return AddFontResourceExA( str, 0, NULL);
3164 /***********************************************************************
3165 * AddFontResourceW (GDI32.@)
3167 INT WINAPI AddFontResourceW( LPCWSTR str )
3169 return AddFontResourceExW(str, 0, NULL);
3173 /***********************************************************************
3174 * AddFontResourceExA (GDI32.@)
3176 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3178 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3179 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3180 INT ret;
3182 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3183 ret = AddFontResourceExW(strW, fl, pdv);
3184 HeapFree(GetProcessHeap(), 0, strW);
3185 return ret;
3188 /***********************************************************************
3189 * AddFontResourceExW (GDI32.@)
3191 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3193 return WineEngAddFontResourceEx(str, fl, pdv);
3196 /***********************************************************************
3197 * RemoveFontResourceA (GDI32.@)
3199 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3201 return RemoveFontResourceExA(str, 0, 0);
3204 /***********************************************************************
3205 * RemoveFontResourceW (GDI32.@)
3207 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3209 return RemoveFontResourceExW(str, 0, 0);
3212 /***********************************************************************
3213 * AddFontMemResourceEx (GDI32.@)
3215 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3217 FIXME("(%p,%08x,%p,%p): stub\n", pbFont, cbFont, pdv, pcFonts);
3218 return NULL;
3221 /***********************************************************************
3222 * RemoveFontResourceExA (GDI32.@)
3224 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3226 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3227 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3228 INT ret;
3230 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3231 ret = RemoveFontResourceExW(strW, fl, pdv);
3232 HeapFree(GetProcessHeap(), 0, strW);
3233 return ret;
3236 /***********************************************************************
3237 * RemoveFontResourceExW (GDI32.@)
3239 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3241 return WineEngRemoveFontResourceEx(str, fl, pdv);
3244 /***********************************************************************
3245 * GetTextCharset (GDI32.@)
3247 UINT WINAPI GetTextCharset(HDC hdc)
3249 /* MSDN docs say this is equivalent */
3250 return GetTextCharsetInfo(hdc, NULL, 0);
3253 /***********************************************************************
3254 * GetTextCharsetInfo (GDI32.@)
3256 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3258 UINT ret = DEFAULT_CHARSET;
3259 DC *dc = DC_GetDCPtr(hdc);
3261 if (dc)
3263 if (dc->gdiFont)
3264 ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
3266 DC_ReleaseDCPtr( dc );
3269 if (ret == DEFAULT_CHARSET && fs)
3270 memset(fs, 0, sizeof(FONTSIGNATURE));
3271 return ret;
3274 /***********************************************************************
3275 * GdiGetCharDimensions (GDI32.@)
3277 * Gets the average width of the characters in the English alphabet.
3279 * PARAMS
3280 * hdc [I] Handle to the device context to measure on.
3281 * lptm [O] Pointer to memory to store the text metrics into.
3282 * height [O] On exit, the maximum height of characters in the English alphabet.
3284 * RETURNS
3285 * The average width of characters in the English alphabet.
3287 * NOTES
3288 * This function is used by the dialog manager to get the size of a dialog
3289 * unit. It should also be used by other pieces of code that need to know
3290 * the size of a dialog unit in logical units without having access to the
3291 * window handle of the dialog.
3292 * Windows caches the font metrics from this function, but we don't and
3293 * there doesn't appear to be an immediate advantage to do so.
3295 * SEE ALSO
3296 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3298 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3300 SIZE sz;
3301 static const WCHAR alphabet[] = {
3302 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3303 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3304 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3306 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3308 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3310 if (height) *height = sz.cy;
3311 return (sz.cx / 26 + 1) / 2;
3314 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3316 FIXME("(%d): stub\n", fEnableEUDC);
3317 return FALSE;
3320 /***********************************************************************
3321 * GetCharWidthI (GDI32.@)
3323 * Retrieve widths of characters.
3325 * PARAMS
3326 * hdc [I] Handle to a device context.
3327 * first [I] First glyph in range to query.
3328 * count [I] Number of glyph indices to query.
3329 * glyphs [I] Array of glyphs to query.
3330 * buffer [O] Buffer to receive character widths.
3332 * NOTES
3333 * Only works with TrueType fonts.
3335 * RETURNS
3336 * Success: TRUE
3337 * Failure: FALSE
3339 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3341 ABC *abc;
3342 unsigned int i;
3344 TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3346 if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3347 return FALSE;
3349 if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3351 HeapFree(GetProcessHeap(), 0, abc);
3352 return FALSE;
3355 for (i = 0; i < count; i++)
3356 buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3358 HeapFree(GetProcessHeap(), 0, abc);
3359 return TRUE;
3362 /***********************************************************************
3363 * GetFontUnicodeRanges (GDI32.@)
3365 * Retrieve a list of supported Unicode characters in a font.
3367 * PARAMS
3368 * hdc [I] Handle to a device context.
3369 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3371 * RETURNS
3372 * Success: Number of bytes written to the buffer pointed to by lpgs.
3373 * Failure: 0
3376 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3378 return WineEngGetFontUnicodeRanges(hdc, lpgs);