push b59ba84f7e04af9ef068bd4c6e96701941f0256e
[wine/hacks.git] / dlls / gdi32 / font.c
blob5cec471011b798ac380b06c1010a34ea7e7d64ef
1 /*
2 * GDI font objects
4 * Copyright 1993 Alexandre Julliard
5 * 1997 Alex Korobka
6 * Copyright 2002,2003 Shachar Shemesh
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "config.h"
24 #include "wine/port.h"
26 #include <stdarg.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <assert.h>
30 #include "winerror.h"
31 #include "windef.h"
32 #include "winbase.h"
33 #include "winnls.h"
34 #include "wownt32.h"
35 #include "gdi_private.h"
36 #include "wine/unicode.h"
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(font);
41 /* Device -> World size conversion */
43 /* Performs a device to world transformation on the specified width (which
44 * is in integer format).
46 static inline INT INTERNAL_XDSTOWS(DC *dc, INT width)
48 FLOAT floatWidth;
50 /* Perform operation with floating point */
51 floatWidth = (FLOAT)width * dc->xformVport2World.eM11;
52 /* Round to integers */
53 return GDI_ROUND(floatWidth);
56 /* Performs a device to world transformation on the specified size (which
57 * is in integer format).
59 static inline INT INTERNAL_YDSTOWS(DC *dc, INT height)
61 FLOAT floatHeight;
63 /* Perform operation with floating point */
64 floatHeight = (FLOAT)height * dc->xformVport2World.eM22;
65 /* Round to integers */
66 return GDI_ROUND(floatHeight);
69 static inline INT INTERNAL_XWSTODS(DC *dc, INT width)
71 POINT pt[2];
72 pt[0].x = pt[0].y = 0;
73 pt[1].x = width;
74 pt[1].y = 0;
75 LPtoDP(dc->hSelf, pt, 2);
76 return pt[1].x - pt[0].x;
79 static inline INT INTERNAL_YWSTODS(DC *dc, INT height)
81 POINT pt[2];
82 pt[0].x = pt[0].y = 0;
83 pt[1].x = 0;
84 pt[1].y = height;
85 LPtoDP(dc->hSelf, pt, 2);
86 return pt[1].y - pt[0].y;
89 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc );
90 static INT FONT_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
91 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
92 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
93 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj );
95 static const struct gdi_obj_funcs font_funcs =
97 FONT_SelectObject, /* pSelectObject */
98 FONT_GetObject16, /* pGetObject16 */
99 FONT_GetObjectA, /* pGetObjectA */
100 FONT_GetObjectW, /* pGetObjectW */
101 NULL, /* pUnrealizeObject */
102 FONT_DeleteObject /* pDeleteObject */
105 #define ENUM_UNICODE 0x00000001
106 #define ENUM_CALLED 0x00000002
108 typedef struct
110 GDIOBJHDR header;
111 LOGFONTW logfont;
112 } FONTOBJ;
114 typedef struct
116 LPLOGFONT16 lpLogFontParam;
117 FONTENUMPROC16 lpEnumFunc;
118 LPARAM lpData;
120 LPNEWTEXTMETRICEX16 lpTextMetric;
121 LPENUMLOGFONTEX16 lpLogFont;
122 SEGPTR segTextMetric;
123 SEGPTR segLogFont;
124 DWORD dwFlags;
125 HDC hdc;
126 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 MAXTCIINDEX 32
145 static const CHARSETINFO FONT_tci[MAXTCIINDEX] = {
146 /* ANSI */
147 { ANSI_CHARSET, 1252, {{0,0,0,0},{FS_LATIN1,0}} },
148 { EASTEUROPE_CHARSET, 1250, {{0,0,0,0},{FS_LATIN2,0}} },
149 { RUSSIAN_CHARSET, 1251, {{0,0,0,0},{FS_CYRILLIC,0}} },
150 { GREEK_CHARSET, 1253, {{0,0,0,0},{FS_GREEK,0}} },
151 { TURKISH_CHARSET, 1254, {{0,0,0,0},{FS_TURKISH,0}} },
152 { HEBREW_CHARSET, 1255, {{0,0,0,0},{FS_HEBREW,0}} },
153 { ARABIC_CHARSET, 1256, {{0,0,0,0},{FS_ARABIC,0}} },
154 { BALTIC_CHARSET, 1257, {{0,0,0,0},{FS_BALTIC,0}} },
155 { VIETNAMESE_CHARSET, 1258, {{0,0,0,0},{FS_VIETNAMESE,0}} },
156 /* reserved by ANSI */
157 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
158 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
159 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
160 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
161 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
162 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
163 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
164 /* ANSI and OEM */
165 { THAI_CHARSET, 874, {{0,0,0,0},{FS_THAI,0}} },
166 { SHIFTJIS_CHARSET, 932, {{0,0,0,0},{FS_JISJAPAN,0}} },
167 { GB2312_CHARSET, 936, {{0,0,0,0},{FS_CHINESESIMP,0}} },
168 { HANGEUL_CHARSET, 949, {{0,0,0,0},{FS_WANSUNG,0}} },
169 { CHINESEBIG5_CHARSET, 950, {{0,0,0,0},{FS_CHINESETRAD,0}} },
170 { JOHAB_CHARSET, 1361, {{0,0,0,0},{FS_JOHAB,0}} },
171 /* reserved for alternate ANSI and OEM */
172 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
173 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
174 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
175 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
176 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
177 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
178 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
179 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
180 /* reserved for system */
181 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
182 { SYMBOL_CHARSET, CP_SYMBOL, {{0,0,0,0},{FS_SYMBOL,0}} }
185 /***********************************************************************
186 * LOGFONT conversion functions.
188 static void FONT_LogFontWTo16( const LOGFONTW* font32, LPLOGFONT16 font16 )
190 font16->lfHeight = font32->lfHeight;
191 font16->lfWidth = font32->lfWidth;
192 font16->lfEscapement = font32->lfEscapement;
193 font16->lfOrientation = font32->lfOrientation;
194 font16->lfWeight = font32->lfWeight;
195 font16->lfItalic = font32->lfItalic;
196 font16->lfUnderline = font32->lfUnderline;
197 font16->lfStrikeOut = font32->lfStrikeOut;
198 font16->lfCharSet = font32->lfCharSet;
199 font16->lfOutPrecision = font32->lfOutPrecision;
200 font16->lfClipPrecision = font32->lfClipPrecision;
201 font16->lfQuality = font32->lfQuality;
202 font16->lfPitchAndFamily = font32->lfPitchAndFamily;
203 WideCharToMultiByte( CP_ACP, 0, font32->lfFaceName, -1,
204 font16->lfFaceName, LF_FACESIZE, NULL, NULL );
205 font16->lfFaceName[LF_FACESIZE-1] = 0;
208 static void FONT_LogFont16ToW( const LOGFONT16 *font16, LPLOGFONTW font32 )
210 font32->lfHeight = font16->lfHeight;
211 font32->lfWidth = font16->lfWidth;
212 font32->lfEscapement = font16->lfEscapement;
213 font32->lfOrientation = font16->lfOrientation;
214 font32->lfWeight = font16->lfWeight;
215 font32->lfItalic = font16->lfItalic;
216 font32->lfUnderline = font16->lfUnderline;
217 font32->lfStrikeOut = font16->lfStrikeOut;
218 font32->lfCharSet = font16->lfCharSet;
219 font32->lfOutPrecision = font16->lfOutPrecision;
220 font32->lfClipPrecision = font16->lfClipPrecision;
221 font32->lfQuality = font16->lfQuality;
222 font32->lfPitchAndFamily = font16->lfPitchAndFamily;
223 MultiByteToWideChar( CP_ACP, 0, font16->lfFaceName, -1, font32->lfFaceName, LF_FACESIZE );
224 font32->lfFaceName[LF_FACESIZE-1] = 0;
227 static void FONT_LogFontAToW( const LOGFONTA *fontA, LPLOGFONTW fontW )
229 memcpy(fontW, fontA, sizeof(LOGFONTA) - LF_FACESIZE);
230 MultiByteToWideChar(CP_ACP, 0, fontA->lfFaceName, -1, fontW->lfFaceName,
231 LF_FACESIZE);
232 fontW->lfFaceName[LF_FACESIZE-1] = 0;
235 static void FONT_LogFontWToA( const LOGFONTW *fontW, LPLOGFONTA fontA )
237 memcpy(fontA, fontW, sizeof(LOGFONTA) - LF_FACESIZE);
238 WideCharToMultiByte(CP_ACP, 0, fontW->lfFaceName, -1, fontA->lfFaceName,
239 LF_FACESIZE, NULL, NULL);
240 fontA->lfFaceName[LF_FACESIZE-1] = 0;
243 static void FONT_EnumLogFontExWTo16( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEX16 font16 )
245 FONT_LogFontWTo16( (const LOGFONTW *)fontW, (LPLOGFONT16)font16);
247 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
248 (LPSTR) font16->elfFullName, LF_FULLFACESIZE, NULL, NULL );
249 font16->elfFullName[LF_FULLFACESIZE-1] = '\0';
250 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
251 (LPSTR) font16->elfStyle, LF_FACESIZE, NULL, NULL );
252 font16->elfStyle[LF_FACESIZE-1] = '\0';
253 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
254 (LPSTR) font16->elfScript, LF_FACESIZE, NULL, NULL );
255 font16->elfScript[LF_FACESIZE-1] = '\0';
258 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEXA fontA )
260 FONT_LogFontWToA( (const LOGFONTW *)fontW, (LPLOGFONTA)fontA);
262 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
263 (LPSTR) fontA->elfFullName, LF_FULLFACESIZE, NULL, NULL );
264 fontA->elfFullName[LF_FULLFACESIZE-1] = '\0';
265 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
266 (LPSTR) fontA->elfStyle, LF_FACESIZE, NULL, NULL );
267 fontA->elfStyle[LF_FACESIZE-1] = '\0';
268 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
269 (LPSTR) fontA->elfScript, LF_FACESIZE, NULL, NULL );
270 fontA->elfScript[LF_FACESIZE-1] = '\0';
273 /***********************************************************************
274 * TEXTMETRIC conversion functions.
276 static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
278 ptmA->tmHeight = ptmW->tmHeight;
279 ptmA->tmAscent = ptmW->tmAscent;
280 ptmA->tmDescent = ptmW->tmDescent;
281 ptmA->tmInternalLeading = ptmW->tmInternalLeading;
282 ptmA->tmExternalLeading = ptmW->tmExternalLeading;
283 ptmA->tmAveCharWidth = ptmW->tmAveCharWidth;
284 ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth;
285 ptmA->tmWeight = ptmW->tmWeight;
286 ptmA->tmOverhang = ptmW->tmOverhang;
287 ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX;
288 ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
289 ptmA->tmFirstChar = min(ptmW->tmFirstChar, 255);
290 if (ptmW->tmCharSet == SYMBOL_CHARSET)
292 UINT last_char = ptmW->tmLastChar;
293 if (last_char > 0xf000) last_char -= 0xf000;
294 ptmA->tmLastChar = min(last_char, 255);
296 else
297 ptmA->tmLastChar = min(ptmW->tmLastChar, 255);
298 ptmA->tmDefaultChar = min(ptmW->tmDefaultChar, 255);
299 ptmA->tmBreakChar = min(ptmW->tmBreakChar, 255);
300 ptmA->tmItalic = ptmW->tmItalic;
301 ptmA->tmUnderlined = ptmW->tmUnderlined;
302 ptmA->tmStruckOut = ptmW->tmStruckOut;
303 ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
304 ptmA->tmCharSet = ptmW->tmCharSet;
308 static void FONT_NewTextMetricExWTo16(const NEWTEXTMETRICEXW *ptmW, LPNEWTEXTMETRICEX16 ptm16 )
310 ptm16->ntmTm.tmHeight = ptmW->ntmTm.tmHeight;
311 ptm16->ntmTm.tmAscent = ptmW->ntmTm.tmAscent;
312 ptm16->ntmTm.tmDescent = ptmW->ntmTm.tmDescent;
313 ptm16->ntmTm.tmInternalLeading = ptmW->ntmTm.tmInternalLeading;
314 ptm16->ntmTm.tmExternalLeading = ptmW->ntmTm.tmExternalLeading;
315 ptm16->ntmTm.tmAveCharWidth = ptmW->ntmTm.tmAveCharWidth;
316 ptm16->ntmTm.tmMaxCharWidth = ptmW->ntmTm.tmMaxCharWidth;
317 ptm16->ntmTm.tmWeight = ptmW->ntmTm.tmWeight;
318 ptm16->ntmTm.tmOverhang = ptmW->ntmTm.tmOverhang;
319 ptm16->ntmTm.tmDigitizedAspectX = ptmW->ntmTm.tmDigitizedAspectX;
320 ptm16->ntmTm.tmDigitizedAspectY = ptmW->ntmTm.tmDigitizedAspectY;
321 ptm16->ntmTm.tmFirstChar = ptmW->ntmTm.tmFirstChar > 255 ? 255 : ptmW->ntmTm.tmFirstChar;
322 ptm16->ntmTm.tmLastChar = ptmW->ntmTm.tmLastChar > 255 ? 255 : ptmW->ntmTm.tmLastChar;
323 ptm16->ntmTm.tmDefaultChar = ptmW->ntmTm.tmDefaultChar > 255 ? 255 : ptmW->ntmTm.tmDefaultChar;
324 ptm16->ntmTm.tmBreakChar = ptmW->ntmTm.tmBreakChar > 255 ? 255 : ptmW->ntmTm.tmBreakChar;
325 ptm16->ntmTm.tmItalic = ptmW->ntmTm.tmItalic;
326 ptm16->ntmTm.tmUnderlined = ptmW->ntmTm.tmUnderlined;
327 ptm16->ntmTm.tmStruckOut = ptmW->ntmTm.tmStruckOut;
328 ptm16->ntmTm.tmPitchAndFamily = ptmW->ntmTm.tmPitchAndFamily;
329 ptm16->ntmTm.tmCharSet = ptmW->ntmTm.tmCharSet;
330 ptm16->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
331 ptm16->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
332 ptm16->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
333 ptm16->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
334 memcpy(&ptm16->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
337 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW *ptmW, NEWTEXTMETRICEXA *ptmA )
339 FONT_TextMetricWToA((const TEXTMETRICW *)ptmW, (LPTEXTMETRICA)ptmA);
340 ptmA->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
341 ptmA->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
342 ptmA->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
343 ptmA->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
344 memcpy(&ptmA->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
348 /***********************************************************************
349 * GdiGetCodePage (GDI32.@)
351 DWORD WINAPI GdiGetCodePage( HDC hdc )
353 UINT cp = CP_ACP;
354 CHARSETINFO csi;
355 int charset = GetTextCharset(hdc);
357 /* Hmm, nicely designed api this one! */
358 if(TranslateCharsetInfo(ULongToPtr(charset), &csi, TCI_SRCCHARSET))
359 cp = csi.ciACP;
360 else {
361 switch(charset) {
362 case OEM_CHARSET:
363 cp = GetOEMCP();
364 break;
365 case DEFAULT_CHARSET:
366 cp = GetACP();
367 break;
369 case VISCII_CHARSET:
370 case TCVN_CHARSET:
371 case KOI8_CHARSET:
372 case ISO3_CHARSET:
373 case ISO4_CHARSET:
374 case ISO10_CHARSET:
375 case CELTIC_CHARSET:
376 /* FIXME: These have no place here, but because x11drv
377 enumerates fonts with these (made up) charsets some apps
378 might use them and then the FIXME below would become
379 annoying. Now we could pick the intended codepage for
380 each of these, but since it's broken anyway we'll just
381 use CP_ACP and hope it'll go away...
383 cp = CP_ACP;
384 break;
386 default:
387 FIXME("Can't find codepage for charset %d\n", charset);
388 break;
392 TRACE("charset %d => cp %d\n", charset, cp);
393 return cp;
396 /***********************************************************************
397 * FONT_mbtowc
399 * Returns a Unicode translation of str using the charset of the
400 * currently selected font in hdc. If count is -1 then str is assumed
401 * to be '\0' terminated, otherwise it contains the number of bytes to
402 * convert. If plenW is non-NULL, on return it will point to the
403 * number of WCHARs that have been written. If pCP is non-NULL, on
404 * return it will point to the codepage used in the conversion. The
405 * caller should free the returned LPWSTR from the process heap
406 * itself.
408 static LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
410 UINT cp;
411 INT lenW;
412 LPWSTR strW;
414 cp = GdiGetCodePage( hdc );
416 if(count == -1) count = strlen(str);
417 lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
418 strW = HeapAlloc(GetProcessHeap(), 0, lenW*sizeof(WCHAR));
419 MultiByteToWideChar(cp, 0, str, count, strW, lenW);
420 TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW));
421 if(plenW) *plenW = lenW;
422 if(pCP) *pCP = cp;
423 return strW;
427 /***********************************************************************
428 * CreateFontIndirectA (GDI32.@)
430 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *plfA )
432 LOGFONTW lfW;
434 if (!plfA) return 0;
436 FONT_LogFontAToW( plfA, &lfW );
437 return CreateFontIndirectW( &lfW );
440 /***********************************************************************
441 * CreateFontIndirectW (GDI32.@)
443 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
445 static const WCHAR ItalicW[] = {' ','I','t','a','l','i','c','\0'};
446 static const WCHAR BoldW[] = {' ','B','o','l','d','\0'};
447 WCHAR *pFaceNameItalicSuffix, *pFaceNameBoldSuffix;
448 WCHAR *pFaceNameSuffix = NULL;
449 HFONT hFont;
450 FONTOBJ *fontPtr;
452 if (!plf) return 0;
454 if (!(fontPtr = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC, (HGDIOBJ *)&hFont,
455 &font_funcs ))) return 0;
457 memcpy( &fontPtr->logfont, plf, sizeof(LOGFONTW) );
459 TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
460 plf->lfHeight, plf->lfWidth,
461 plf->lfEscapement, plf->lfOrientation,
462 plf->lfPitchAndFamily,
463 plf->lfOutPrecision, plf->lfClipPrecision,
464 plf->lfQuality, plf->lfCharSet,
465 debugstr_w(plf->lfFaceName),
466 plf->lfWeight > 400 ? "Bold" : "",
467 plf->lfItalic ? "Italic" : "",
468 plf->lfUnderline ? "Underline" : "", hFont);
470 if (plf->lfEscapement != plf->lfOrientation)
472 /* this should really depend on whether GM_ADVANCED is set */
473 fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
474 WARN("orientation angle %f set to "
475 "escapement angle %f for new font %p\n",
476 plf->lfOrientation/10., plf->lfEscapement/10., hFont);
479 pFaceNameItalicSuffix = strstrW(fontPtr->logfont.lfFaceName, ItalicW);
480 if (pFaceNameItalicSuffix)
482 fontPtr->logfont.lfItalic = TRUE;
483 pFaceNameSuffix = pFaceNameItalicSuffix;
486 pFaceNameBoldSuffix = strstrW(fontPtr->logfont.lfFaceName, BoldW);
487 if (pFaceNameBoldSuffix)
489 if (fontPtr->logfont.lfWeight < FW_BOLD)
490 fontPtr->logfont.lfWeight = FW_BOLD;
491 if (!pFaceNameSuffix || (pFaceNameBoldSuffix < pFaceNameSuffix))
492 pFaceNameSuffix = pFaceNameBoldSuffix;
495 if (pFaceNameSuffix) *pFaceNameSuffix = 0;
497 GDI_ReleaseObj( hFont );
498 return hFont;
501 /*************************************************************************
502 * CreateFontA (GDI32.@)
504 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
505 INT orient, INT weight, DWORD italic,
506 DWORD underline, DWORD strikeout, DWORD charset,
507 DWORD outpres, DWORD clippres, DWORD quality,
508 DWORD pitch, LPCSTR name )
510 LOGFONTA logfont;
512 logfont.lfHeight = height;
513 logfont.lfWidth = width;
514 logfont.lfEscapement = esc;
515 logfont.lfOrientation = orient;
516 logfont.lfWeight = weight;
517 logfont.lfItalic = italic;
518 logfont.lfUnderline = underline;
519 logfont.lfStrikeOut = strikeout;
520 logfont.lfCharSet = charset;
521 logfont.lfOutPrecision = outpres;
522 logfont.lfClipPrecision = clippres;
523 logfont.lfQuality = quality;
524 logfont.lfPitchAndFamily = pitch;
526 if (name)
527 lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
528 else
529 logfont.lfFaceName[0] = '\0';
531 return CreateFontIndirectA( &logfont );
534 /*************************************************************************
535 * CreateFontW (GDI32.@)
537 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
538 INT orient, INT weight, DWORD italic,
539 DWORD underline, DWORD strikeout, DWORD charset,
540 DWORD outpres, DWORD clippres, DWORD quality,
541 DWORD pitch, LPCWSTR name )
543 LOGFONTW logfont;
545 logfont.lfHeight = height;
546 logfont.lfWidth = width;
547 logfont.lfEscapement = esc;
548 logfont.lfOrientation = orient;
549 logfont.lfWeight = weight;
550 logfont.lfItalic = italic;
551 logfont.lfUnderline = underline;
552 logfont.lfStrikeOut = strikeout;
553 logfont.lfCharSet = charset;
554 logfont.lfOutPrecision = outpres;
555 logfont.lfClipPrecision = clippres;
556 logfont.lfQuality = quality;
557 logfont.lfPitchAndFamily = pitch;
559 if (name)
560 lstrcpynW(logfont.lfFaceName, name,
561 sizeof(logfont.lfFaceName) / sizeof(WCHAR));
562 else
563 logfont.lfFaceName[0] = '\0';
565 return CreateFontIndirectW( &logfont );
569 /***********************************************************************
570 * FONT_SelectObject
572 * If the driver supports vector fonts we create a gdi font first and
573 * then call the driver to give it a chance to supply its own device
574 * font. If the driver wants to do this it returns TRUE and we can
575 * delete the gdi font, if the driver wants to use the gdi font it
576 * should return FALSE, to signal an error return GDI_ERROR. For
577 * drivers that don't support vector fonts they must supply their own
578 * font.
580 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc )
582 HGDIOBJ ret = 0;
583 DC *dc = get_dc_ptr( hdc );
585 if (!dc) return 0;
587 if (!GDI_inc_ref_count( handle ))
589 release_dc_ptr( dc );
590 return 0;
593 if (dc->hFont != handle || dc->gdiFont == NULL)
595 if(GetDeviceCaps(dc->hSelf, TEXTCAPS) & TC_VA_ABLE)
597 FONTOBJ *font = GDI_GetObjPtr( handle, FONT_MAGIC ); /* to grab the GDI lock (FIXME) */
598 dc->gdiFont = WineEngCreateFontInstance(dc, handle);
599 if (font) GDI_ReleaseObj( handle );
603 if (dc->funcs->pSelectFont) ret = dc->funcs->pSelectFont( dc->physDev, handle, dc->gdiFont );
605 if (ret && dc->gdiFont) dc->gdiFont = 0;
607 if (ret == HGDI_ERROR)
609 GDI_dec_ref_count( handle );
610 ret = 0; /* SelectObject returns 0 on error */
612 else
614 ret = dc->hFont;
615 dc->hFont = handle;
616 GDI_dec_ref_count( ret );
618 release_dc_ptr( dc );
619 return ret;
623 /***********************************************************************
624 * FONT_GetObject16
626 static INT FONT_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
628 FONTOBJ *font = obj;
629 LOGFONT16 lf16;
631 FONT_LogFontWTo16( &font->logfont, &lf16 );
633 if (count > sizeof(LOGFONT16)) count = sizeof(LOGFONT16);
634 memcpy( buffer, &lf16, count );
635 return count;
638 /***********************************************************************
639 * FONT_GetObjectA
641 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
643 FONTOBJ *font = obj;
644 LOGFONTA lfA;
646 if(!buffer)
647 return sizeof(lfA);
648 FONT_LogFontWToA( &font->logfont, &lfA );
650 if (count > sizeof(lfA)) count = sizeof(lfA);
651 memcpy( buffer, &lfA, count );
652 return count;
655 /***********************************************************************
656 * FONT_GetObjectW
658 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
660 FONTOBJ *font = obj;
661 if(!buffer)
662 return sizeof(LOGFONTW);
663 if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
664 memcpy( buffer, &font->logfont, count );
665 return count;
669 /***********************************************************************
670 * FONT_DeleteObject
672 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj )
674 WineEngDestroyFontInstance( handle );
675 return GDI_FreeObject( handle, obj );
679 /***********************************************************************
680 * FONT_EnumInstance16
682 * Called by the device driver layer to pass font info
683 * down to the application.
685 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
686 * We have to use other types because of the FONTENUMPROCW definition.
688 static INT CALLBACK FONT_EnumInstance16( const LOGFONTW *plf, const TEXTMETRICW *ptm,
689 DWORD fType, LPARAM lp )
691 fontEnum16 *pfe = (fontEnum16*)lp;
692 INT ret = 1;
693 DC *dc;
695 if (!pfe->lpLogFontParam ||
696 pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
697 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet )
699 WORD args[7];
700 DWORD result;
702 FONT_EnumLogFontExWTo16((const ENUMLOGFONTEXW *)plf, pfe->lpLogFont);
703 FONT_NewTextMetricExWTo16((const NEWTEXTMETRICEXW *)ptm, pfe->lpTextMetric);
704 pfe->dwFlags |= ENUM_CALLED;
705 DC_ReleaseDCPtr( pfe->dc ); /* release the GDI lock */
707 args[6] = SELECTOROF(pfe->segLogFont);
708 args[5] = OFFSETOF(pfe->segLogFont);
709 args[4] = SELECTOROF(pfe->segTextMetric);
710 args[3] = OFFSETOF(pfe->segTextMetric);
711 args[2] = fType;
712 args[1] = HIWORD(pfe->lpData);
713 args[0] = LOWORD(pfe->lpData);
714 WOWCallback16Ex( (DWORD)pfe->lpEnumFunc, WCB16_PASCAL, sizeof(args), args, &result );
715 ret = LOWORD(result);
717 /* get the lock again and make sure the DC is still valid */
718 dc = DC_GetDCPtr( pfe->hdc );
719 if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
721 if (dc) DC_ReleaseDCPtr( dc );
722 pfe->hdc = 0; /* make sure we don't try to release it later on */
723 pfe->dc = NULL;
724 ret = 0;
727 return ret;
730 /***********************************************************************
731 * FONT_EnumInstance
733 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
734 * We have to use other types because of the FONTENUMPROCW definition.
736 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
737 DWORD fType, LPARAM lp )
739 fontEnum32 *pfe = (fontEnum32*)lp;
740 INT ret = 1;
741 DC *dc;
743 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
744 if ((!pfe->lpLogFontParam ||
745 pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
746 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
747 (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
749 /* convert font metrics */
750 ENUMLOGFONTEXA logfont;
751 NEWTEXTMETRICEXA tmA;
753 pfe->dwFlags |= ENUM_CALLED;
754 if (!(pfe->dwFlags & ENUM_UNICODE))
756 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
757 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
758 plf = (LOGFONTW *)&logfont.elfLogFont;
759 ptm = (TEXTMETRICW *)&tmA;
761 DC_ReleaseDCPtr( pfe->dc ); /* release the GDI lock */
763 ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
765 /* get the lock again and make sure the DC is still valid */
766 dc = DC_GetDCPtr( pfe->hdc );
767 if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
769 if (dc) DC_ReleaseDCPtr( dc );
770 pfe->hdc = 0; /* make sure we don't try to release it later on */
771 pfe->dc = NULL;
772 ret = 0;
775 return ret;
778 /***********************************************************************
779 * EnumFontFamiliesEx (GDI.613)
781 INT16 WINAPI EnumFontFamiliesEx16( HDC16 hDC, LPLOGFONT16 plf,
782 FONTENUMPROC16 efproc, LPARAM lParam,
783 DWORD dwFlags)
785 fontEnum16 fe16;
786 INT16 ret = 1, ret2;
787 DC* dc = DC_GetDCPtr( HDC_32(hDC) );
788 NEWTEXTMETRICEX16 tm16;
789 ENUMLOGFONTEX16 lf16;
790 LOGFONTW lfW, *plfW;
791 BOOL enum_gdi_fonts;
793 if (!dc) return 0;
795 if (plf)
797 FONT_LogFont16ToW(plf, &lfW);
798 plfW = &lfW;
800 else plfW = NULL;
802 fe16.hdc = HDC_32(hDC);
803 fe16.dc = dc;
804 fe16.physDev = dc->physDev;
805 fe16.lpLogFontParam = plf;
806 fe16.lpEnumFunc = efproc;
807 fe16.lpData = lParam;
808 fe16.lpTextMetric = &tm16;
809 fe16.lpLogFont = &lf16;
810 fe16.segTextMetric = MapLS( &tm16 );
811 fe16.segLogFont = MapLS( &lf16 );
812 fe16.dwFlags = 0;
814 enum_gdi_fonts = GetDeviceCaps(fe16.hdc, TEXTCAPS) & TC_VA_ABLE;
816 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
818 ret = 0;
819 goto done;
822 if (enum_gdi_fonts)
823 ret = WineEngEnumFonts( plfW, FONT_EnumInstance16, (LPARAM)&fe16 );
824 fe16.dwFlags &= ~ENUM_CALLED;
825 if (ret && dc->funcs->pEnumDeviceFonts) {
826 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, plfW, FONT_EnumInstance16, (LPARAM)&fe16 );
827 if(fe16.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
828 ret = ret2;
830 done:
831 UnMapLS( fe16.segTextMetric );
832 UnMapLS( fe16.segLogFont );
833 if (fe16.dc) DC_ReleaseDCPtr( fe16.dc );
834 return ret;
837 /***********************************************************************
838 * FONT_EnumFontFamiliesEx
840 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf,
841 FONTENUMPROCW efproc,
842 LPARAM lParam, DWORD dwUnicode)
844 INT ret = 1, ret2;
845 DC *dc = DC_GetDCPtr( hDC );
846 fontEnum32 fe32;
847 BOOL enum_gdi_fonts;
849 if (!dc) return 0;
851 if (plf)
852 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName),
853 plf->lfCharSet);
854 fe32.lpLogFontParam = plf;
855 fe32.lpEnumFunc = efproc;
856 fe32.lpData = lParam;
857 fe32.dwFlags = dwUnicode;
858 fe32.hdc = hDC;
859 fe32.dc = dc;
860 fe32.physDev = dc->physDev;
862 enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE;
864 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
866 ret = 0;
867 goto done;
870 if (enum_gdi_fonts)
871 ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
872 fe32.dwFlags &= ~ENUM_CALLED;
873 if (ret && dc->funcs->pEnumDeviceFonts) {
874 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, plf, FONT_EnumInstance, (LPARAM)&fe32 );
875 if(fe32.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
876 ret = ret2;
878 done:
879 if (fe32.dc) DC_ReleaseDCPtr( fe32.dc );
880 return ret;
883 /***********************************************************************
884 * EnumFontFamiliesExW (GDI32.@)
886 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
887 FONTENUMPROCW efproc,
888 LPARAM lParam, DWORD dwFlags )
890 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, ENUM_UNICODE );
893 /***********************************************************************
894 * EnumFontFamiliesExA (GDI32.@)
896 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
897 FONTENUMPROCA efproc,
898 LPARAM lParam, DWORD dwFlags)
900 LOGFONTW lfW, *plfW;
902 if (plf)
904 FONT_LogFontAToW( plf, &lfW );
905 plfW = &lfW;
907 else plfW = NULL;
909 return FONT_EnumFontFamiliesEx( hDC, plfW, (FONTENUMPROCW)efproc, lParam, 0);
912 /***********************************************************************
913 * EnumFontFamilies (GDI.330)
915 INT16 WINAPI EnumFontFamilies16( HDC16 hDC, LPCSTR lpFamily,
916 FONTENUMPROC16 efproc, LPARAM lpData )
918 LOGFONT16 lf, *plf;
920 if (lpFamily)
922 if (!*lpFamily) return 1;
923 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
924 lf.lfCharSet = DEFAULT_CHARSET;
925 lf.lfPitchAndFamily = 0;
926 plf = &lf;
928 else plf = NULL;
930 return EnumFontFamiliesEx16( hDC, plf, efproc, lpData, 0 );
933 /***********************************************************************
934 * EnumFontFamiliesA (GDI32.@)
936 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
937 FONTENUMPROCA efproc, LPARAM lpData )
939 LOGFONTA lf, *plf;
941 if (lpFamily)
943 if (!*lpFamily) return 1;
944 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
945 lf.lfCharSet = DEFAULT_CHARSET;
946 lf.lfPitchAndFamily = 0;
947 plf = &lf;
949 else plf = NULL;
951 return EnumFontFamiliesExA( hDC, plf, efproc, lpData, 0 );
954 /***********************************************************************
955 * EnumFontFamiliesW (GDI32.@)
957 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
958 FONTENUMPROCW efproc, LPARAM lpData )
960 LOGFONTW lf, *plf;
962 if (lpFamily)
964 if (!*lpFamily) return 1;
965 lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
966 lf.lfCharSet = DEFAULT_CHARSET;
967 lf.lfPitchAndFamily = 0;
968 plf = &lf;
970 else plf = NULL;
972 return EnumFontFamiliesExW( hDC, plf, efproc, lpData, 0 );
975 /***********************************************************************
976 * EnumFonts (GDI.70)
978 INT16 WINAPI EnumFonts16( HDC16 hDC, LPCSTR lpName, FONTENUMPROC16 efproc,
979 LPARAM lpData )
981 return EnumFontFamilies16( hDC, lpName, efproc, lpData );
984 /***********************************************************************
985 * EnumFontsA (GDI32.@)
987 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
988 LPARAM lpData )
990 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
993 /***********************************************************************
994 * EnumFontsW (GDI32.@)
996 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
997 LPARAM lpData )
999 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
1003 /***********************************************************************
1004 * GetTextCharacterExtra (GDI32.@)
1006 INT WINAPI GetTextCharacterExtra( HDC hdc )
1008 INT ret;
1009 DC *dc = DC_GetDCPtr( hdc );
1010 if (!dc) return 0x80000000;
1011 ret = dc->charExtra;
1012 DC_ReleaseDCPtr( dc );
1013 return ret;
1017 /***********************************************************************
1018 * SetTextCharacterExtra (GDI32.@)
1020 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
1022 INT prev;
1023 DC * dc = DC_GetDCPtr( hdc );
1024 if (!dc) return 0x80000000;
1025 if (dc->funcs->pSetTextCharacterExtra)
1026 prev = dc->funcs->pSetTextCharacterExtra( dc->physDev, extra );
1027 else
1029 prev = dc->charExtra;
1030 dc->charExtra = extra;
1032 DC_ReleaseDCPtr( dc );
1033 return prev;
1037 /***********************************************************************
1038 * SetTextJustification (GDI32.@)
1040 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
1042 BOOL ret = TRUE;
1043 DC * dc = DC_GetDCPtr( hdc );
1044 if (!dc) return FALSE;
1045 if (dc->funcs->pSetTextJustification)
1046 ret = dc->funcs->pSetTextJustification( dc->physDev, extra, breaks );
1047 else
1049 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
1050 if (!extra) breaks = 0;
1051 if (breaks)
1053 dc->breakExtra = extra / breaks;
1054 dc->breakRem = extra - (breaks * dc->breakExtra);
1056 else
1058 dc->breakExtra = 0;
1059 dc->breakRem = 0;
1062 DC_ReleaseDCPtr( dc );
1063 return ret;
1067 /***********************************************************************
1068 * GetTextFaceA (GDI32.@)
1070 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
1072 INT res = GetTextFaceW(hdc, 0, NULL);
1073 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
1074 GetTextFaceW( hdc, res, nameW );
1076 if (name)
1078 if (count && !WideCharToMultiByte( CP_ACP, 0, nameW, -1, name, count, NULL, NULL))
1079 name[count-1] = 0;
1080 res = strlen(name);
1082 else
1083 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
1084 HeapFree( GetProcessHeap(), 0, nameW );
1085 return res;
1088 /***********************************************************************
1089 * GetTextFaceW (GDI32.@)
1091 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
1093 FONTOBJ *font;
1094 INT ret = 0;
1096 DC * dc = DC_GetDCPtr( hdc );
1097 if (!dc) return 0;
1099 if(dc->gdiFont)
1100 ret = WineEngGetTextFace(dc->gdiFont, count, name);
1101 else if ((font = (FONTOBJ *) GDI_GetObjPtr( dc->hFont, FONT_MAGIC )))
1103 if (name)
1105 lstrcpynW( name, font->logfont.lfFaceName, count );
1106 ret = strlenW(name);
1108 else ret = strlenW(font->logfont.lfFaceName) + 1;
1109 GDI_ReleaseObj( dc->hFont );
1111 DC_ReleaseDCPtr( dc );
1112 return ret;
1116 /***********************************************************************
1117 * GetTextExtentPoint32A (GDI32.@)
1119 * See GetTextExtentPoint32W.
1121 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
1122 LPSIZE size )
1124 BOOL ret = FALSE;
1125 INT wlen;
1126 LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1128 if (p) {
1129 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
1130 HeapFree( GetProcessHeap(), 0, p );
1133 TRACE("(%p %s %d %p): returning %d x %d\n",
1134 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
1135 return ret;
1139 /***********************************************************************
1140 * GetTextExtentPoint32W [GDI32.@]
1142 * Computes width/height for a string.
1144 * Computes width and height of the specified string.
1146 * RETURNS
1147 * Success: TRUE
1148 * Failure: FALSE
1150 BOOL WINAPI GetTextExtentPoint32W(
1151 HDC hdc, /* [in] Handle of device context */
1152 LPCWSTR str, /* [in] Address of text string */
1153 INT count, /* [in] Number of characters in string */
1154 LPSIZE size) /* [out] Address of structure for string size */
1156 return GetTextExtentExPointW(hdc, str, count, 0, NULL, NULL, size);
1159 /***********************************************************************
1160 * GetTextExtentExPointI [GDI32.@]
1162 * Computes width and height of the array of glyph indices.
1164 * PARAMS
1165 * hdc [I] Handle of device context.
1166 * indices [I] Glyph index array.
1167 * count [I] Number of glyphs in array.
1168 * max_ext [I] Maximum width in glyphs.
1169 * nfit [O] Maximum number of characters.
1170 * dxs [O] Partial string widths.
1171 * size [O] Returned string size.
1173 * RETURNS
1174 * Success: TRUE
1175 * Failure: FALSE
1177 BOOL WINAPI GetTextExtentExPointI( HDC hdc, const WORD *indices, INT count, INT max_ext,
1178 LPINT nfit, LPINT dxs, LPSIZE size )
1180 BOOL ret = FALSE;
1181 DC * dc = DC_GetDCPtr( hdc );
1182 if (!dc) return FALSE;
1184 if(dc->gdiFont) {
1185 ret = WineEngGetTextExtentExPointI(dc->gdiFont, indices, count, max_ext, nfit, dxs, size);
1186 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1187 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1188 size->cx += count * dc->charExtra;
1190 else if(dc->funcs->pGetTextExtentExPoint) {
1191 FIXME("calling GetTextExtentExPoint\n");
1192 ret = dc->funcs->pGetTextExtentExPoint( dc->physDev, (LPCWSTR)indices,
1193 count, max_ext, nfit, dxs, size );
1196 DC_ReleaseDCPtr( dc );
1198 TRACE("(%p %p %d %p): returning %d x %d\n",
1199 hdc, indices, count, size, size->cx, size->cy );
1200 return ret;
1203 /***********************************************************************
1204 * GetTextExtentPointI [GDI32.@]
1206 * Computes width and height of the array of glyph indices.
1208 * PARAMS
1209 * hdc [I] Handle of device context.
1210 * indices [I] Glyph index array.
1211 * count [I] Number of glyphs in array.
1212 * size [O] Returned string size.
1214 * RETURNS
1215 * Success: TRUE
1216 * Failure: FALSE
1218 BOOL WINAPI GetTextExtentPointI( HDC hdc, const WORD *indices, INT count, LPSIZE size )
1220 return GetTextExtentExPointI( hdc, indices, count, 0, NULL, NULL, size );
1224 /***********************************************************************
1225 * GetTextExtentPointA (GDI32.@)
1227 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
1228 LPSIZE size )
1230 TRACE("not bug compatible.\n");
1231 return GetTextExtentPoint32A( hdc, str, count, size );
1234 /***********************************************************************
1235 * GetTextExtentPointW (GDI32.@)
1237 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1238 LPSIZE size )
1240 TRACE("not bug compatible.\n");
1241 return GetTextExtentPoint32W( hdc, str, count, size );
1245 /***********************************************************************
1246 * GetTextExtentExPointA (GDI32.@)
1248 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1249 INT maxExt, LPINT lpnFit,
1250 LPINT alpDx, LPSIZE size )
1252 BOOL ret;
1253 INT wlen;
1254 INT *walpDx = NULL;
1255 LPWSTR p = NULL;
1257 if (alpDx &&
1258 NULL == (walpDx = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT))))
1259 return FALSE;
1261 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1262 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
1263 if (walpDx)
1265 INT n = lpnFit ? *lpnFit : wlen;
1266 INT i, j;
1267 for(i = 0, j = 0; i < n; i++, j++)
1269 alpDx[j] = walpDx[i];
1270 if (IsDBCSLeadByte(str[j])) alpDx[++j] = walpDx[i];
1273 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1274 HeapFree( GetProcessHeap(), 0, p );
1275 HeapFree( GetProcessHeap(), 0, walpDx );
1276 return ret;
1280 /***********************************************************************
1281 * GetTextExtentExPointW (GDI32.@)
1283 * Return the size of the string as it would be if it was output properly by
1284 * e.g. TextOut.
1286 * This should include
1287 * - Intercharacter spacing
1288 * - justification spacing (not yet done)
1289 * - kerning? see below
1291 * Kerning. Since kerning would be carried out by the rendering code it should
1292 * be done by the driver. However they don't support it yet. Also I am not
1293 * yet persuaded that (certainly under Win95) any kerning is actually done.
1295 * str: According to MSDN this should be null-terminated. That is not true; a
1296 * null will not terminate it early.
1297 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1298 * than count. I have seen it be either the size of the full string or
1299 * 1 less than the size of the full string. I have not seen it bear any
1300 * resemblance to the portion that would fit.
1301 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1302 * trailing intercharacter spacing and any trailing justification.
1304 * FIXME
1305 * Currently we do this by measuring each character etc. We should do it by
1306 * passing the request to the driver, perhaps by extending the
1307 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1308 * thinking about kerning issues and rounding issues in the justification.
1311 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1312 INT maxExt, LPINT lpnFit,
1313 LPINT alpDx, LPSIZE size )
1315 INT nFit = 0;
1316 LPINT dxs = NULL;
1317 DC *dc;
1318 BOOL ret = FALSE;
1319 TEXTMETRICW tm;
1321 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1323 dc = DC_GetDCPtr(hdc);
1324 if (! dc)
1325 return FALSE;
1327 GetTextMetricsW(hdc, &tm);
1329 /* If we need to calculate nFit, then we need the partial extents even if
1330 the user hasn't provided us with an array. */
1331 if (lpnFit)
1333 dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]);
1334 if (! dxs)
1336 DC_ReleaseDCPtr(dc);
1337 SetLastError(ERROR_OUTOFMEMORY);
1338 return FALSE;
1341 else
1342 dxs = alpDx;
1344 if (dc->gdiFont)
1345 ret = WineEngGetTextExtentExPoint(dc->gdiFont, str, count,
1346 0, NULL, dxs, size);
1347 else if (dc->funcs->pGetTextExtentExPoint)
1348 ret = dc->funcs->pGetTextExtentExPoint(dc->physDev, str, count,
1349 0, NULL, dxs, size);
1351 /* Perform device size to world size transformations. */
1352 if (ret)
1354 INT extra = dc->charExtra,
1355 breakExtra = dc->breakExtra,
1356 breakRem = dc->breakRem,
1359 if (dxs)
1361 for (i = 0; i < count; ++i)
1363 dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
1364 dxs[i] += (i+1) * extra;
1365 if (count > 1 && (breakExtra || breakRem) && str[i] == tm.tmBreakChar)
1367 dxs[i] += breakExtra;
1368 if (breakRem > 0)
1370 breakRem--;
1371 dxs[i]++;
1374 if (dxs[i] <= maxExt)
1375 ++nFit;
1377 breakRem = dc->breakRem;
1379 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1380 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1382 if (!dxs && count > 1 && (breakExtra || breakRem))
1384 for (i = 0; i < count; i++)
1386 if (str[i] == tm.tmBreakChar)
1388 size->cx += breakExtra;
1389 if (breakRem > 0)
1391 breakRem--;
1392 (size->cx)++;
1399 if (lpnFit)
1400 *lpnFit = nFit;
1402 if (! alpDx)
1403 HeapFree(GetProcessHeap(), 0, dxs);
1405 DC_ReleaseDCPtr( dc );
1407 TRACE("returning %d %d x %d\n",nFit,size->cx,size->cy);
1408 return ret;
1411 /***********************************************************************
1412 * GetTextMetricsA (GDI32.@)
1414 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1416 TEXTMETRICW tm32;
1418 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1419 FONT_TextMetricWToA( &tm32, metrics );
1420 return TRUE;
1423 /***********************************************************************
1424 * GetTextMetricsW (GDI32.@)
1426 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1428 BOOL ret = FALSE;
1429 DC * dc = DC_GetDCPtr( hdc );
1430 if (!dc) return FALSE;
1432 if (dc->gdiFont)
1433 ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1434 else if (dc->funcs->pGetTextMetrics)
1435 ret = dc->funcs->pGetTextMetrics( dc->physDev, metrics );
1437 if (ret)
1439 /* device layer returns values in device units
1440 * therefore we have to convert them to logical */
1442 metrics->tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1443 metrics->tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1445 #define WDPTOLP(x) ((x<0)? \
1446 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1447 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1448 #define HDPTOLP(y) ((y<0)? \
1449 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1450 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1452 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1453 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1454 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1455 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1456 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1457 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1458 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1459 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1460 ret = TRUE;
1461 #undef WDPTOLP
1462 #undef HDPTOLP
1463 TRACE("text metrics:\n"
1464 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1465 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1466 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1467 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1468 " PitchAndFamily = %02x\n"
1469 " --------------------\n"
1470 " InternalLeading = %i\n"
1471 " Ascent = %i\n"
1472 " Descent = %i\n"
1473 " Height = %i\n",
1474 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1475 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1476 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1477 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1478 metrics->tmPitchAndFamily,
1479 metrics->tmInternalLeading,
1480 metrics->tmAscent,
1481 metrics->tmDescent,
1482 metrics->tmHeight );
1484 DC_ReleaseDCPtr( dc );
1485 return ret;
1489 /***********************************************************************
1490 * GetOutlineTextMetrics [GDI.308] Gets metrics for TrueType fonts.
1492 * NOTES
1493 * lpOTM should be LPOUTLINETEXTMETRIC
1495 * RETURNS
1496 * Success: Non-zero or size of required buffer
1497 * Failure: 0
1499 UINT16 WINAPI GetOutlineTextMetrics16(
1500 HDC16 hdc, /* [in] Handle of device context */
1501 UINT16 cbData, /* [in] Size of metric data array */
1502 LPOUTLINETEXTMETRIC16 lpOTM) /* [out] Address of metric data array */
1504 FIXME("(%04x,%04x,%p): stub\n", hdc,cbData,lpOTM);
1505 return 0;
1509 /***********************************************************************
1510 * GetOutlineTextMetricsA (GDI32.@)
1511 * Gets metrics for TrueType fonts.
1513 * NOTES
1514 * If the supplied buffer isn't big enough Windows partially fills it up to
1515 * its given length and returns that length.
1517 * RETURNS
1518 * Success: Non-zero or size of required buffer
1519 * Failure: 0
1521 UINT WINAPI GetOutlineTextMetricsA(
1522 HDC hdc, /* [in] Handle of device context */
1523 UINT cbData, /* [in] Size of metric data array */
1524 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1526 char buf[512], *ptr;
1527 UINT ret, needed;
1528 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1529 OUTLINETEXTMETRICA *output = lpOTM;
1530 INT left, len;
1532 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1533 return 0;
1534 if(ret > sizeof(buf))
1535 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1536 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1538 needed = sizeof(OUTLINETEXTMETRICA);
1539 if(lpOTMW->otmpFamilyName)
1540 needed += WideCharToMultiByte(CP_ACP, 0,
1541 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1542 NULL, 0, NULL, NULL);
1543 if(lpOTMW->otmpFaceName)
1544 needed += WideCharToMultiByte(CP_ACP, 0,
1545 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1546 NULL, 0, NULL, NULL);
1547 if(lpOTMW->otmpStyleName)
1548 needed += WideCharToMultiByte(CP_ACP, 0,
1549 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1550 NULL, 0, NULL, NULL);
1551 if(lpOTMW->otmpFullName)
1552 needed += WideCharToMultiByte(CP_ACP, 0,
1553 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1554 NULL, 0, NULL, NULL);
1556 if(!lpOTM) {
1557 ret = needed;
1558 goto end;
1561 TRACE("needed = %d\n", needed);
1562 if(needed > cbData)
1563 /* Since the supplied buffer isn't big enough, we'll alloc one
1564 that is and memcpy the first cbData bytes into the lpOTM at
1565 the end. */
1566 output = HeapAlloc(GetProcessHeap(), 0, needed);
1568 ret = output->otmSize = min(needed, cbData);
1569 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1570 output->otmFiller = 0;
1571 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1572 output->otmfsSelection = lpOTMW->otmfsSelection;
1573 output->otmfsType = lpOTMW->otmfsType;
1574 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1575 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1576 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1577 output->otmEMSquare = lpOTMW->otmEMSquare;
1578 output->otmAscent = lpOTMW->otmAscent;
1579 output->otmDescent = lpOTMW->otmDescent;
1580 output->otmLineGap = lpOTMW->otmLineGap;
1581 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1582 output->otmsXHeight = lpOTMW->otmsXHeight;
1583 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1584 output->otmMacAscent = lpOTMW->otmMacAscent;
1585 output->otmMacDescent = lpOTMW->otmMacDescent;
1586 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1587 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1588 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1589 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1590 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1591 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1592 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1593 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1594 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1595 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1598 ptr = (char*)(output + 1);
1599 left = needed - sizeof(*output);
1601 if(lpOTMW->otmpFamilyName) {
1602 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1603 len = WideCharToMultiByte(CP_ACP, 0,
1604 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1605 ptr, left, NULL, NULL);
1606 left -= len;
1607 ptr += len;
1608 } else
1609 output->otmpFamilyName = 0;
1611 if(lpOTMW->otmpFaceName) {
1612 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1613 len = WideCharToMultiByte(CP_ACP, 0,
1614 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1615 ptr, left, NULL, NULL);
1616 left -= len;
1617 ptr += len;
1618 } else
1619 output->otmpFaceName = 0;
1621 if(lpOTMW->otmpStyleName) {
1622 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1623 len = WideCharToMultiByte(CP_ACP, 0,
1624 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1625 ptr, left, NULL, NULL);
1626 left -= len;
1627 ptr += len;
1628 } else
1629 output->otmpStyleName = 0;
1631 if(lpOTMW->otmpFullName) {
1632 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1633 len = WideCharToMultiByte(CP_ACP, 0,
1634 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1635 ptr, left, NULL, NULL);
1636 left -= len;
1637 } else
1638 output->otmpFullName = 0;
1640 assert(left == 0);
1642 if(output != lpOTM) {
1643 memcpy(lpOTM, output, cbData);
1644 HeapFree(GetProcessHeap(), 0, output);
1646 /* check if the string offsets really fit into the provided size */
1647 /* FIXME: should we check string length as well? */
1648 /* make sure that we don't read/write beyond the provided buffer */
1649 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(LPSTR))
1651 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1652 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1655 /* make sure that we don't read/write beyond the provided buffer */
1656 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(LPSTR))
1658 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1659 lpOTM->otmpFaceName = 0; /* doesn't fit */
1662 /* make sure that we don't read/write beyond the provided buffer */
1663 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(LPSTR))
1665 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1666 lpOTM->otmpStyleName = 0; /* doesn't fit */
1669 /* make sure that we don't read/write beyond the provided buffer */
1670 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(LPSTR))
1672 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1673 lpOTM->otmpFullName = 0; /* doesn't fit */
1677 end:
1678 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1679 HeapFree(GetProcessHeap(), 0, lpOTMW);
1681 return ret;
1685 /***********************************************************************
1686 * GetOutlineTextMetricsW [GDI32.@]
1688 UINT WINAPI GetOutlineTextMetricsW(
1689 HDC hdc, /* [in] Handle of device context */
1690 UINT cbData, /* [in] Size of metric data array */
1691 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1693 DC *dc = DC_GetDCPtr( hdc );
1694 OUTLINETEXTMETRICW *output = lpOTM;
1695 UINT ret;
1697 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1698 if(!dc) return 0;
1700 if(dc->gdiFont) {
1701 ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, output);
1702 if(lpOTM && ret) {
1703 if(ret > cbData) {
1704 output = HeapAlloc(GetProcessHeap(), 0, ret);
1705 WineEngGetOutlineTextMetrics(dc->gdiFont, ret, output);
1708 #define WDPTOLP(x) ((x<0)? \
1709 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1710 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1711 #define HDPTOLP(y) ((y<0)? \
1712 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1713 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1715 output->otmTextMetrics.tmHeight = HDPTOLP(output->otmTextMetrics.tmHeight);
1716 output->otmTextMetrics.tmAscent = HDPTOLP(output->otmTextMetrics.tmAscent);
1717 output->otmTextMetrics.tmDescent = HDPTOLP(output->otmTextMetrics.tmDescent);
1718 output->otmTextMetrics.tmInternalLeading = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1719 output->otmTextMetrics.tmExternalLeading = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1720 output->otmTextMetrics.tmAveCharWidth = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1721 output->otmTextMetrics.tmMaxCharWidth = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1722 output->otmTextMetrics.tmOverhang = WDPTOLP(output->otmTextMetrics.tmOverhang);
1723 output->otmAscent = HDPTOLP(output->otmAscent);
1724 output->otmDescent = HDPTOLP(output->otmDescent);
1725 output->otmLineGap = HDPTOLP(output->otmLineGap);
1726 output->otmsCapEmHeight = HDPTOLP(output->otmsCapEmHeight);
1727 output->otmsXHeight = HDPTOLP(output->otmsXHeight);
1728 output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1729 output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1730 output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1731 output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1732 output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1733 output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1734 output->otmMacLineGap = HDPTOLP(output->otmMacLineGap);
1735 output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1736 output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1737 output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1738 output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1739 output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1740 output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1741 output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1742 output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1743 output->otmsStrikeoutSize = HDPTOLP(output->otmsStrikeoutSize);
1744 output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1745 output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1746 output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1747 #undef WDPTOLP
1748 #undef HDPTOLP
1749 if(output != lpOTM) {
1750 memcpy(lpOTM, output, cbData);
1751 HeapFree(GetProcessHeap(), 0, output);
1752 ret = cbData;
1757 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1758 but really this should just be a return 0. */
1760 ret = sizeof(*lpOTM);
1761 if (lpOTM) {
1762 if(cbData < ret)
1763 ret = 0;
1764 else {
1765 memset(lpOTM, 0, ret);
1766 lpOTM->otmSize = sizeof(*lpOTM);
1767 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1769 Further fill of the structure not implemented,
1770 Needs real values for the structure members
1775 DC_ReleaseDCPtr(dc);
1776 return ret;
1780 /***********************************************************************
1781 * GetCharWidthW (GDI32.@)
1782 * GetCharWidth32W (GDI32.@)
1784 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1785 LPINT buffer )
1787 UINT i;
1788 BOOL ret = FALSE;
1789 DC * dc = DC_GetDCPtr( hdc );
1790 if (!dc) return FALSE;
1792 if (dc->gdiFont)
1793 ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1794 else if (dc->funcs->pGetCharWidth)
1795 ret = dc->funcs->pGetCharWidth( dc->physDev, firstChar, lastChar, buffer);
1797 if (ret)
1799 /* convert device units to logical */
1800 for( i = firstChar; i <= lastChar; i++, buffer++ )
1801 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1802 ret = TRUE;
1804 DC_ReleaseDCPtr( dc );
1805 return ret;
1809 /***********************************************************************
1810 * GetCharWidthA (GDI32.@)
1811 * GetCharWidth32A (GDI32.@)
1813 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1814 LPINT buffer )
1816 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1817 LPSTR str;
1818 LPWSTR wstr;
1819 BOOL ret = TRUE;
1821 if(count <= 0) return FALSE;
1823 str = HeapAlloc(GetProcessHeap(), 0, count);
1824 for(i = 0; i < count; i++)
1825 str[i] = (BYTE)(firstChar + i);
1827 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1829 for(i = 0; i < wlen; i++)
1831 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1833 ret = FALSE;
1834 break;
1836 buffer++;
1839 HeapFree(GetProcessHeap(), 0, str);
1840 HeapFree(GetProcessHeap(), 0, wstr);
1842 return ret;
1846 /***********************************************************************
1847 * ExtTextOutA (GDI32.@)
1849 * See ExtTextOutW.
1851 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1852 const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1854 INT wlen;
1855 UINT codepage;
1856 LPWSTR p;
1857 BOOL ret;
1858 LPINT lpDxW = NULL;
1860 if (flags & ETO_GLYPH_INDEX)
1861 return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
1863 p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
1865 if (lpDx) {
1866 unsigned int i = 0, j = 0;
1868 lpDxW = HeapAlloc( GetProcessHeap(), 0, wlen*sizeof(INT));
1869 while(i < count) {
1870 if(IsDBCSLeadByteEx(codepage, str[i])) {
1871 lpDxW[j++] = lpDx[i] + lpDx[i+1];
1872 i = i + 2;
1873 } else {
1874 lpDxW[j++] = lpDx[i];
1875 i = i + 1;
1880 ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1882 HeapFree( GetProcessHeap(), 0, p );
1883 HeapFree( GetProcessHeap(), 0, lpDxW );
1884 return ret;
1888 /***********************************************************************
1889 * ExtTextOutW (GDI32.@)
1891 * Draws text using the currently selected font, background color, and text color.
1894 * PARAMS
1895 * x,y [I] coordinates of string
1896 * flags [I]
1897 * ETO_GRAYED - undocumented on MSDN
1898 * ETO_OPAQUE - use background color for fill the rectangle
1899 * ETO_CLIPPED - clipping text to the rectangle
1900 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1901 * than encoded characters. Implies ETO_IGNORELANGUAGE
1902 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1903 * Affects BiDi ordering
1904 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1905 * ETO_PDY - unimplemented
1906 * ETO_NUMERICSLATIN - unimplemented always assumed -
1907 * do not translate numbers into locale representations
1908 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1909 * lprect [I] dimensions for clipping or/and opaquing
1910 * str [I] text string
1911 * count [I] number of symbols in string
1912 * lpDx [I] optional parameter with distance between drawing characters
1914 * RETURNS
1915 * Success: TRUE
1916 * Failure: FALSE
1918 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1919 const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1921 BOOL ret = FALSE;
1922 LPWSTR reordered_str = (LPWSTR)str;
1923 WORD *glyphs = NULL;
1924 UINT align = GetTextAlign( hdc );
1925 POINT pt;
1926 TEXTMETRICW tm;
1927 LOGFONTW lf;
1928 double cosEsc, sinEsc;
1929 INT *deltas = NULL, char_extra;
1930 SIZE sz;
1931 RECT rc;
1932 BOOL done_extents = FALSE;
1933 INT width = 0, xwidth = 0, ywidth = 0;
1934 DWORD type;
1935 DC * dc = get_dc_ptr( hdc );
1936 INT breakRem;
1938 if (!dc) return FALSE;
1940 breakRem = dc->breakRem;
1942 if (flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY))
1943 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY unimplemented\n");
1945 if (!dc->funcs->pExtTextOut && !PATH_IsPathOpen(dc->path))
1947 release_dc_ptr( dc );
1948 return ret;
1951 update_dc( dc );
1952 type = GetObjectType(hdc);
1953 if(type == OBJ_METADC || type == OBJ_ENHMETADC)
1955 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, flags, lprect, str, count, lpDx);
1956 release_dc_ptr( dc );
1957 return ret;
1960 if (!lprect)
1961 flags &= ~ETO_CLIPPED;
1963 if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && count > 0 )
1965 reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1967 BIDI_Reorder( str, count, GCP_REORDER,
1968 ((flags&ETO_RTLREADING)!=0 || (GetTextAlign(hdc)&TA_RTLREADING)!=0)?
1969 WINE_GCPW_FORCE_RTL:WINE_GCPW_FORCE_LTR,
1970 reordered_str, count, NULL );
1972 flags |= ETO_IGNORELANGUAGE;
1975 TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc, x, y, flags,
1976 lprect, debugstr_wn(str, count), count, lpDx);
1978 if(flags & ETO_GLYPH_INDEX)
1979 glyphs = reordered_str;
1981 if(lprect)
1982 TRACE("rect: %d,%d - %d,%d\n", lprect->left, lprect->top, lprect->right,
1983 lprect->bottom);
1984 TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
1986 if(align & TA_UPDATECP)
1988 GetCurrentPositionEx( hdc, &pt );
1989 x = pt.x;
1990 y = pt.y;
1993 GetTextMetricsW(hdc, &tm);
1994 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1996 if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
1997 lf.lfEscapement = 0;
1999 if(lf.lfEscapement != 0)
2001 cosEsc = cos(lf.lfEscapement * M_PI / 1800);
2002 sinEsc = sin(lf.lfEscapement * M_PI / 1800);
2004 else
2006 cosEsc = 1;
2007 sinEsc = 0;
2010 if(flags & (ETO_CLIPPED | ETO_OPAQUE))
2012 if(!lprect)
2014 if(flags & ETO_GLYPH_INDEX)
2015 GetTextExtentPointI(hdc, glyphs, count, &sz);
2016 else
2017 GetTextExtentPointW(hdc, reordered_str, count, &sz);
2019 done_extents = TRUE;
2020 rc.left = x;
2021 rc.top = y;
2022 rc.right = x + sz.cx;
2023 rc.bottom = y + sz.cy;
2025 else
2027 rc = *lprect;
2030 LPtoDP(hdc, (POINT*)&rc, 2);
2032 if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
2033 if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
2036 if ((flags & ETO_OPAQUE) && !PATH_IsPathOpen(dc->path))
2037 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
2039 if(count == 0)
2041 ret = TRUE;
2042 goto done;
2045 pt.x = x;
2046 pt.y = y;
2047 LPtoDP(hdc, &pt, 1);
2048 x = pt.x;
2049 y = pt.y;
2051 char_extra = GetTextCharacterExtra(hdc);
2052 if(char_extra || dc->breakExtra || breakRem || lpDx || lf.lfEscapement != 0)
2054 UINT i;
2055 SIZE tmpsz;
2056 deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT));
2057 for(i = 0; i < count; i++)
2059 if(lpDx && (flags & ETO_PDY))
2060 deltas[i] = lpDx[i*2] + char_extra;
2061 else if(lpDx)
2062 deltas[i] = lpDx[i] + char_extra;
2063 else
2065 if(flags & ETO_GLYPH_INDEX)
2066 GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
2067 else
2068 GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
2070 deltas[i] = tmpsz.cx;
2073 if (!(flags & ETO_GLYPH_INDEX) && (dc->breakExtra || breakRem) && reordered_str[i] == tm.tmBreakChar)
2075 deltas[i] = deltas[i] + dc->breakExtra;
2076 if (breakRem > 0)
2078 breakRem--;
2079 deltas[i]++;
2082 deltas[i] = INTERNAL_XWSTODS(dc, deltas[i]);
2083 width += deltas[i];
2086 else
2088 if(!done_extents)
2090 if(flags & ETO_GLYPH_INDEX)
2091 GetTextExtentPointI(hdc, glyphs, count, &sz);
2092 else
2093 GetTextExtentPointW(hdc, reordered_str, count, &sz);
2094 done_extents = TRUE;
2096 width = INTERNAL_XWSTODS(dc, sz.cx);
2098 xwidth = width * cosEsc;
2099 ywidth = width * sinEsc;
2101 tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
2102 tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
2103 switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
2105 case TA_LEFT:
2106 if (align & TA_UPDATECP)
2108 pt.x = x + xwidth;
2109 pt.y = y - ywidth;
2110 DPtoLP(hdc, &pt, 1);
2111 MoveToEx(hdc, pt.x, pt.y, NULL);
2113 break;
2115 case TA_CENTER:
2116 x -= xwidth / 2;
2117 y += ywidth / 2;
2118 break;
2120 case TA_RIGHT:
2121 x -= xwidth;
2122 y += ywidth;
2123 if (align & TA_UPDATECP)
2125 pt.x = x;
2126 pt.y = y;
2127 DPtoLP(hdc, &pt, 1);
2128 MoveToEx(hdc, pt.x, pt.y, NULL);
2130 break;
2133 switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
2135 case TA_TOP:
2136 y += tm.tmAscent * cosEsc;
2137 x += tm.tmAscent * sinEsc;
2138 break;
2140 case TA_BOTTOM:
2141 y -= tm.tmDescent * cosEsc;
2142 x -= tm.tmDescent * sinEsc;
2143 break;
2145 case TA_BASELINE:
2146 break;
2149 if (GetBkMode(hdc) != TRANSPARENT && !PATH_IsPathOpen(dc->path))
2151 if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
2153 if(!(flags & ETO_OPAQUE) || x < rc.left || x + width >= rc.right ||
2154 y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
2156 RECT rc;
2157 rc.left = x;
2158 rc.right = x + width;
2159 rc.top = y - tm.tmAscent;
2160 rc.bottom = y + tm.tmDescent;
2161 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
2166 if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
2168 HFONT orig_font = dc->hFont, cur_font;
2169 UINT glyph;
2170 INT span = 0, *offsets = NULL;
2171 unsigned int i;
2173 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2174 for(i = 0; i < count; i++)
2176 WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
2177 if(cur_font != dc->hFont)
2179 if(!offsets)
2181 unsigned int j;
2182 offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
2183 offsets[0] = 0;
2184 if(!deltas)
2186 SIZE tmpsz;
2187 for(j = 1; j < count; j++)
2189 GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
2190 offsets[j] = offsets[j-1] + INTERNAL_XWSTODS(dc, tmpsz.cx);
2193 else
2195 for(j = 1; j < count; j++)
2196 offsets[j] = offsets[j-1] + deltas[j];
2199 if(span)
2201 if (PATH_IsPathOpen(dc->path))
2202 ret = PATH_ExtTextOut(dc, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
2203 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2204 glyphs, span, deltas ? deltas + i - span : NULL);
2205 else
2206 dc->funcs->pExtTextOut(dc->physDev, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
2207 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2208 glyphs, span, deltas ? deltas + i - span : NULL);
2209 span = 0;
2211 SelectObject(hdc, cur_font);
2213 glyphs[span++] = glyph;
2215 if(i == count - 1)
2217 if (PATH_IsPathOpen(dc->path))
2218 ret = PATH_ExtTextOut(dc, x + (offsets ? offsets[count - span] * cosEsc : 0),
2219 y - (offsets ? offsets[count - span] * sinEsc : 0),
2220 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2221 glyphs, span, deltas ? deltas + count - span : NULL);
2222 else
2223 ret = dc->funcs->pExtTextOut(dc->physDev, x + (offsets ? offsets[count - span] * cosEsc : 0),
2224 y - (offsets ? offsets[count - span] * sinEsc : 0),
2225 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2226 glyphs, span, deltas ? deltas + count - span : NULL);
2227 SelectObject(hdc, orig_font);
2228 HeapFree(GetProcessHeap(), 0, offsets);
2232 else
2234 if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
2236 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2237 GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
2238 flags |= ETO_GLYPH_INDEX;
2241 if (PATH_IsPathOpen(dc->path))
2242 ret = PATH_ExtTextOut(dc, x, y, (flags & ~ETO_OPAQUE), &rc,
2243 glyphs ? glyphs : reordered_str, count, deltas);
2244 else
2245 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, (flags & ~ETO_OPAQUE), &rc,
2246 glyphs ? glyphs : reordered_str, count, deltas);
2249 done:
2250 HeapFree(GetProcessHeap(), 0, deltas);
2251 if(glyphs != reordered_str)
2252 HeapFree(GetProcessHeap(), 0, glyphs);
2253 if(reordered_str != str)
2254 HeapFree(GetProcessHeap(), 0, reordered_str);
2256 release_dc_ptr( dc );
2258 if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2260 int underlinePos, strikeoutPos;
2261 int underlineWidth, strikeoutWidth;
2262 UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2263 OUTLINETEXTMETRICW* otm = NULL;
2265 if(!size)
2267 underlinePos = 0;
2268 underlineWidth = tm.tmAscent / 20 + 1;
2269 strikeoutPos = tm.tmAscent / 2;
2270 strikeoutWidth = underlineWidth;
2272 else
2274 otm = HeapAlloc(GetProcessHeap(), 0, size);
2275 GetOutlineTextMetricsW(hdc, size, otm);
2276 underlinePos = otm->otmsUnderscorePosition;
2277 underlineWidth = otm->otmsUnderscoreSize;
2278 strikeoutPos = otm->otmsStrikeoutPosition;
2279 strikeoutWidth = otm->otmsStrikeoutSize;
2280 HeapFree(GetProcessHeap(), 0, otm);
2283 if (PATH_IsPathOpen(dc->path))
2285 POINT pts[5];
2286 HPEN hpen;
2287 HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2289 hbrush = SelectObject(hdc, hbrush);
2290 hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2292 if (lf.lfUnderline)
2294 pts[0].x = x - underlinePos * sinEsc;
2295 pts[0].y = y - underlinePos * cosEsc;
2296 pts[1].x = x + xwidth - underlinePos * sinEsc;
2297 pts[1].y = y - ywidth - underlinePos * cosEsc;
2298 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2299 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2300 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2301 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2302 pts[4].x = pts[0].x;
2303 pts[4].y = pts[0].y;
2304 DPtoLP(hdc, pts, 5);
2305 Polygon(hdc, pts, 5);
2308 if (lf.lfStrikeOut)
2310 pts[0].x = x - strikeoutPos * sinEsc;
2311 pts[0].y = y - strikeoutPos * cosEsc;
2312 pts[1].x = x + xwidth - strikeoutPos * sinEsc;
2313 pts[1].y = y - ywidth - strikeoutPos * cosEsc;
2314 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2315 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2316 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2317 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2318 pts[4].x = pts[0].x;
2319 pts[4].y = pts[0].y;
2320 DPtoLP(hdc, pts, 5);
2321 Polygon(hdc, pts, 5);
2324 SelectObject(hdc, hpen);
2325 hbrush = SelectObject(hdc, hbrush);
2326 DeleteObject(hbrush);
2328 else
2330 POINT pts[2], oldpt;
2331 HPEN hpen;
2333 if (lf.lfUnderline)
2335 hpen = CreatePen(PS_SOLID, underlineWidth, GetTextColor(hdc));
2336 hpen = SelectObject(hdc, hpen);
2337 pts[0].x = x;
2338 pts[0].y = y;
2339 pts[1].x = x + xwidth;
2340 pts[1].y = y - ywidth;
2341 DPtoLP(hdc, pts, 2);
2342 MoveToEx(hdc, pts[0].x - underlinePos * sinEsc, pts[0].y - underlinePos * cosEsc, &oldpt);
2343 LineTo(hdc, pts[1].x - underlinePos * sinEsc, pts[1].y - underlinePos * cosEsc);
2344 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2345 DeleteObject(SelectObject(hdc, hpen));
2348 if (lf.lfStrikeOut)
2350 hpen = CreatePen(PS_SOLID, strikeoutWidth, GetTextColor(hdc));
2351 hpen = SelectObject(hdc, hpen);
2352 pts[0].x = x;
2353 pts[0].y = y;
2354 pts[1].x = x + xwidth;
2355 pts[1].y = y - ywidth;
2356 DPtoLP(hdc, pts, 2);
2357 MoveToEx(hdc, pts[0].x - strikeoutPos * sinEsc, pts[0].y - strikeoutPos * cosEsc, &oldpt);
2358 LineTo(hdc, pts[1].x - strikeoutPos * sinEsc, pts[1].y - strikeoutPos * cosEsc);
2359 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2360 DeleteObject(SelectObject(hdc, hpen));
2365 return ret;
2369 /***********************************************************************
2370 * TextOutA (GDI32.@)
2372 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2374 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2378 /***********************************************************************
2379 * TextOutW (GDI32.@)
2381 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2383 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2387 /***********************************************************************
2388 * PolyTextOutA (GDI32.@)
2390 * See PolyTextOutW.
2392 BOOL WINAPI PolyTextOutA( HDC hdc, const POLYTEXTA *pptxt, INT cStrings )
2394 for (; cStrings>0; cStrings--, pptxt++)
2395 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2396 return FALSE;
2397 return TRUE;
2402 /***********************************************************************
2403 * PolyTextOutW (GDI32.@)
2405 * Draw several Strings
2407 * RETURNS
2408 * TRUE: Success.
2409 * FALSE: Failure.
2411 BOOL WINAPI PolyTextOutW( HDC hdc, const POLYTEXTW *pptxt, INT cStrings )
2413 for (; cStrings>0; cStrings--, pptxt++)
2414 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2415 return FALSE;
2416 return TRUE;
2420 /* FIXME: all following APIs ******************************************/
2423 /***********************************************************************
2424 * SetMapperFlags (GDI32.@)
2426 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
2428 DC *dc = DC_GetDCPtr( hDC );
2429 DWORD ret = 0;
2430 if(!dc) return 0;
2431 if(dc->funcs->pSetMapperFlags)
2433 ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
2434 /* FIXME: ret is just a success flag, we should return a proper value */
2436 else
2437 FIXME("(%p, 0x%08x): stub - harmless\n", hDC, dwFlag);
2438 DC_ReleaseDCPtr( dc );
2439 return ret;
2442 /***********************************************************************
2443 * GetAspectRatioFilterEx (GDI.486)
2445 BOOL16 WINAPI GetAspectRatioFilterEx16( HDC16 hdc, LPSIZE16 pAspectRatio )
2447 FIXME("(%04x, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2448 return FALSE;
2451 /***********************************************************************
2452 * GetAspectRatioFilterEx (GDI32.@)
2454 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2456 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2457 return FALSE;
2461 /***********************************************************************
2462 * GetCharABCWidthsA (GDI32.@)
2464 * See GetCharABCWidthsW.
2466 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2467 LPABC abc )
2469 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
2470 LPSTR str;
2471 LPWSTR wstr;
2472 BOOL ret = TRUE;
2474 if(count <= 0) return FALSE;
2476 str = HeapAlloc(GetProcessHeap(), 0, count);
2477 for(i = 0; i < count; i++)
2478 str[i] = (BYTE)(firstChar + i);
2480 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
2482 for(i = 0; i < wlen; i++)
2484 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2486 ret = FALSE;
2487 break;
2489 abc++;
2492 HeapFree(GetProcessHeap(), 0, str);
2493 HeapFree(GetProcessHeap(), 0, wstr);
2495 return ret;
2499 /******************************************************************************
2500 * GetCharABCWidthsW [GDI32.@]
2502 * Retrieves widths of characters in range.
2504 * PARAMS
2505 * hdc [I] Handle of device context
2506 * firstChar [I] First character in range to query
2507 * lastChar [I] Last character in range to query
2508 * abc [O] Address of character-width structure
2510 * NOTES
2511 * Only works with TrueType fonts
2513 * RETURNS
2514 * Success: TRUE
2515 * Failure: FALSE
2517 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2518 LPABC abc )
2520 DC *dc = DC_GetDCPtr(hdc);
2521 unsigned int i;
2522 BOOL ret = FALSE;
2524 if (!dc) return FALSE;
2526 if (!abc)
2528 DC_ReleaseDCPtr( dc );
2529 return FALSE;
2532 if(dc->gdiFont)
2533 ret = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
2534 else
2535 FIXME(": stub\n");
2537 if (ret)
2539 /* convert device units to logical */
2540 for( i = firstChar; i <= lastChar; i++, abc++ ) {
2541 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2542 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2543 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2545 ret = TRUE;
2548 DC_ReleaseDCPtr( dc );
2549 return ret;
2553 /******************************************************************************
2554 * GetCharABCWidthsI [GDI32.@]
2556 * Retrieves widths of characters in range.
2558 * PARAMS
2559 * hdc [I] Handle of device context
2560 * firstChar [I] First glyphs in range to query
2561 * count [I] Last glyphs in range to query
2562 * pgi [i] Array of glyphs to query
2563 * abc [O] Address of character-width structure
2565 * NOTES
2566 * Only works with TrueType fonts
2568 * RETURNS
2569 * Success: TRUE
2570 * Failure: FALSE
2572 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2573 LPWORD pgi, LPABC abc)
2575 DC *dc = DC_GetDCPtr(hdc);
2576 unsigned int i;
2577 BOOL ret = FALSE;
2579 if (!dc) return FALSE;
2581 if (!abc)
2583 DC_ReleaseDCPtr( dc );
2584 return FALSE;
2587 if(dc->gdiFont)
2588 ret = WineEngGetCharABCWidthsI( dc->gdiFont, firstChar, count, pgi, abc );
2589 else
2590 FIXME(": stub\n");
2592 if (ret)
2594 /* convert device units to logical */
2595 for( i = 0; i < count; i++, abc++ ) {
2596 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2597 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2598 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2600 ret = TRUE;
2603 DC_ReleaseDCPtr( dc );
2604 return ret;
2608 /***********************************************************************
2609 * GetGlyphOutlineA (GDI32.@)
2611 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2612 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2613 LPVOID lpBuffer, const MAT2 *lpmat2 )
2615 LPWSTR p = NULL;
2616 DWORD ret;
2617 UINT c;
2619 if(!(fuFormat & GGO_GLYPH_INDEX)) {
2620 int len;
2621 char mbchs[2];
2622 if(uChar > 0xff) { /* but, 2 bytes character only */
2623 len = 2;
2624 mbchs[0] = (uChar & 0xff00) >> 8;
2625 mbchs[1] = (uChar & 0xff);
2626 } else {
2627 len = 1;
2628 mbchs[0] = (uChar & 0xff);
2630 p = FONT_mbtowc(hdc, mbchs, len, NULL, NULL);
2631 c = p[0];
2632 } else
2633 c = uChar;
2634 ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
2635 lpmat2);
2636 HeapFree(GetProcessHeap(), 0, p);
2637 return ret;
2640 /***********************************************************************
2641 * GetGlyphOutlineW (GDI32.@)
2643 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2644 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2645 LPVOID lpBuffer, const MAT2 *lpmat2 )
2647 DC *dc = DC_GetDCPtr(hdc);
2648 DWORD ret;
2650 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2651 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2653 if(!dc) return GDI_ERROR;
2655 if(dc->gdiFont)
2656 ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
2657 cbBuffer, lpBuffer, lpmat2);
2658 else
2659 ret = GDI_ERROR;
2661 DC_ReleaseDCPtr( dc );
2662 return ret;
2666 /***********************************************************************
2667 * CreateScalableFontResourceA (GDI32.@)
2669 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2670 LPCSTR lpszResourceFile,
2671 LPCSTR lpszFontFile,
2672 LPCSTR lpszCurrentPath )
2674 HANDLE f;
2676 /* fHidden=1 - only visible for the calling app, read-only, not
2677 * enumbered with EnumFonts/EnumFontFamilies
2678 * lpszCurrentPath can be NULL
2680 FIXME("(%d,%s,%s,%s): stub\n",
2681 fHidden, debugstr_a(lpszResourceFile), debugstr_a(lpszFontFile),
2682 debugstr_a(lpszCurrentPath) );
2684 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2685 if ((f = CreateFileA(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2686 CloseHandle(f);
2687 SetLastError(ERROR_FILE_EXISTS);
2688 return FALSE;
2690 return FALSE; /* create failed */
2693 /***********************************************************************
2694 * CreateScalableFontResourceW (GDI32.@)
2696 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2697 LPCWSTR lpszResourceFile,
2698 LPCWSTR lpszFontFile,
2699 LPCWSTR lpszCurrentPath )
2701 FIXME("(%d,%p,%p,%p): stub\n",
2702 fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
2703 return FALSE; /* create failed */
2706 /*************************************************************************
2707 * GetKerningPairsA (GDI32.@)
2709 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2710 LPKERNINGPAIR kern_pairA )
2712 INT charset;
2713 CHARSETINFO csi;
2714 CPINFO cpi;
2715 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2716 KERNINGPAIR *kern_pairW;
2718 if (!cPairs && kern_pairA)
2720 SetLastError(ERROR_INVALID_PARAMETER);
2721 return 0;
2724 charset = GetTextCharset(hDC);
2725 if (!TranslateCharsetInfo(ULongToPtr(charset), &csi, TCI_SRCCHARSET))
2727 FIXME("Can't find codepage for charset %d\n", charset);
2728 return 0;
2730 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2731 * to fail on an invalid character for CP_SYMBOL.
2733 cpi.DefaultChar[0] = 0;
2734 if (csi.ciACP != CP_SYMBOL && !GetCPInfo(csi.ciACP, &cpi))
2736 FIXME("Can't find codepage %u info\n", csi.ciACP);
2737 return 0;
2739 TRACE("charset %d => codepage %u\n", charset, csi.ciACP);
2741 total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2742 if (!total_kern_pairs) return 0;
2744 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2745 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2747 for (i = 0; i < total_kern_pairs; i++)
2749 char first, second;
2751 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2752 continue;
2754 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2755 continue;
2757 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2758 continue;
2760 if (kern_pairA)
2762 if (kern_pairs_copied >= cPairs) break;
2764 kern_pairA->wFirst = (BYTE)first;
2765 kern_pairA->wSecond = (BYTE)second;
2766 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2767 kern_pairA++;
2769 kern_pairs_copied++;
2772 HeapFree(GetProcessHeap(), 0, kern_pairW);
2774 return kern_pairs_copied;
2777 /*************************************************************************
2778 * GetKerningPairsW (GDI32.@)
2780 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2781 LPKERNINGPAIR lpKerningPairs )
2783 DC *dc;
2784 DWORD ret = 0;
2786 TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2788 if (!cPairs && lpKerningPairs)
2790 SetLastError(ERROR_INVALID_PARAMETER);
2791 return 0;
2794 dc = DC_GetDCPtr(hDC);
2795 if (!dc) return 0;
2797 if (dc->gdiFont)
2798 ret = WineEngGetKerningPairs(dc->gdiFont, cPairs, lpKerningPairs);
2800 DC_ReleaseDCPtr( dc );
2801 return ret;
2804 /*************************************************************************
2805 * TranslateCharsetInfo [GDI32.@]
2807 * Fills a CHARSETINFO structure for a character set, code page, or
2808 * font. This allows making the correspondence between different labels
2809 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2810 * of the same encoding.
2812 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2813 * only one codepage should be set in *lpSrc.
2815 * RETURNS
2816 * TRUE on success, FALSE on failure.
2819 BOOL WINAPI TranslateCharsetInfo(
2820 LPDWORD lpSrc, /* [in]
2821 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2822 if flags == TCI_SRCCHARSET: a character set value
2823 if flags == TCI_SRCCODEPAGE: a code page value
2825 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2826 DWORD flags /* [in] determines interpretation of lpSrc */)
2828 int index = 0;
2829 switch (flags) {
2830 case TCI_SRCFONTSIG:
2831 while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
2832 break;
2833 case TCI_SRCCODEPAGE:
2834 while (PtrToUlong(lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
2835 break;
2836 case TCI_SRCCHARSET:
2837 while (PtrToUlong(lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
2838 break;
2839 default:
2840 return FALSE;
2842 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2843 memcpy(lpCs, &FONT_tci[index], sizeof(CHARSETINFO));
2844 return TRUE;
2847 /*************************************************************************
2848 * GetFontLanguageInfo (GDI32.@)
2850 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2852 FONTSIGNATURE fontsig;
2853 static const DWORD GCP_DBCS_MASK=0x003F0000,
2854 GCP_DIACRITIC_MASK=0x00000000,
2855 FLI_GLYPHS_MASK=0x00000000,
2856 GCP_GLYPHSHAPE_MASK=0x00000040,
2857 GCP_KASHIDA_MASK=0x00000000,
2858 GCP_LIGATE_MASK=0x00000000,
2859 GCP_USEKERNING_MASK=0x00000000,
2860 GCP_REORDER_MASK=0x00000060;
2862 DWORD result=0;
2864 GetTextCharsetInfo( hdc, &fontsig, 0 );
2865 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2867 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2868 result|=GCP_DBCS;
2870 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2871 result|=GCP_DIACRITIC;
2873 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2874 result|=FLI_GLYPHS;
2876 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2877 result|=GCP_GLYPHSHAPE;
2879 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2880 result|=GCP_KASHIDA;
2882 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2883 result|=GCP_LIGATE;
2885 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2886 result|=GCP_USEKERNING;
2888 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2889 if( GetTextAlign( hdc) & TA_RTLREADING )
2890 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2891 result|=GCP_REORDER;
2893 return result;
2897 /*************************************************************************
2898 * GetFontData [GDI32.@]
2900 * Retrieve data for TrueType font.
2902 * RETURNS
2904 * success: Number of bytes returned
2905 * failure: GDI_ERROR
2907 * NOTES
2909 * Calls SetLastError()
2912 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2913 LPVOID buffer, DWORD length)
2915 DC *dc = DC_GetDCPtr(hdc);
2916 DWORD ret = GDI_ERROR;
2918 if(!dc) return GDI_ERROR;
2920 if(dc->gdiFont)
2921 ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2923 DC_ReleaseDCPtr( dc );
2924 return ret;
2927 /*************************************************************************
2928 * GetGlyphIndicesA [GDI32.@]
2930 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2931 LPWORD pgi, DWORD flags)
2933 DWORD ret;
2934 WCHAR *lpstrW;
2935 INT countW;
2937 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2938 hdc, debugstr_an(lpstr, count), count, pgi, flags);
2940 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2941 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2942 HeapFree(GetProcessHeap(), 0, lpstrW);
2944 return ret;
2947 /*************************************************************************
2948 * GetGlyphIndicesW [GDI32.@]
2950 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2951 LPWORD pgi, DWORD flags)
2953 DC *dc = DC_GetDCPtr(hdc);
2954 DWORD ret = GDI_ERROR;
2956 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2957 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2959 if(!dc) return GDI_ERROR;
2961 if(dc->gdiFont)
2962 ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2964 DC_ReleaseDCPtr( dc );
2965 return ret;
2968 /*************************************************************************
2969 * GetCharacterPlacementA [GDI32.@]
2971 * See GetCharacterPlacementW.
2973 * NOTES:
2974 * the web browser control of ie4 calls this with dwFlags=0
2976 DWORD WINAPI
2977 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2978 INT nMaxExtent, GCP_RESULTSA *lpResults,
2979 DWORD dwFlags)
2981 WCHAR *lpStringW;
2982 INT uCountW;
2983 GCP_RESULTSW resultsW;
2984 DWORD ret;
2985 UINT font_cp;
2987 TRACE("%s, %d, %d, 0x%08x\n",
2988 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2990 /* both structs are equal in size */
2991 memcpy(&resultsW, lpResults, sizeof(resultsW));
2993 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2994 if(lpResults->lpOutString)
2995 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2997 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2999 lpResults->nGlyphs = resultsW.nGlyphs;
3000 lpResults->nMaxFit = resultsW.nMaxFit;
3002 if(lpResults->lpOutString) {
3003 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
3004 lpResults->lpOutString, uCount, NULL, NULL );
3007 HeapFree(GetProcessHeap(), 0, lpStringW);
3008 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
3010 return ret;
3013 /*************************************************************************
3014 * GetCharacterPlacementW [GDI32.@]
3016 * Retrieve information about a string. This includes the width, reordering,
3017 * Glyphing and so on.
3019 * RETURNS
3021 * The width and height of the string if successful, 0 if failed.
3023 * BUGS
3025 * All flags except GCP_REORDER are not yet implemented.
3026 * Reordering is not 100% complient to the Windows BiDi method.
3027 * Caret positioning is not yet implemented for BiDi.
3028 * Classes are not yet implemented.
3031 DWORD WINAPI
3032 GetCharacterPlacementW(
3033 HDC hdc, /* [in] Device context for which the rendering is to be done */
3034 LPCWSTR lpString, /* [in] The string for which information is to be returned */
3035 INT uCount, /* [in] Number of WORDS in string. */
3036 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
3037 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
3038 DWORD dwFlags /* [in] Flags specifying how to process the string */
3041 DWORD ret=0;
3042 SIZE size;
3043 UINT i, nSet;
3045 TRACE("%s, %d, %d, 0x%08x\n",
3046 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
3048 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
3049 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
3050 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
3051 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
3052 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
3054 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08x ignored\n", dwFlags);
3055 if(lpResults->lpClass) FIXME("classes not implemented\n");
3056 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
3057 FIXME("Caret positions for complex scripts not implemented\n");
3059 nSet = (UINT)uCount;
3060 if(nSet > lpResults->nGlyphs)
3061 nSet = lpResults->nGlyphs;
3063 /* return number of initialized fields */
3064 lpResults->nGlyphs = nSet;
3066 if((dwFlags&GCP_REORDER)==0 )
3068 /* Treat the case where no special handling was requested in a fastpath way */
3069 /* copy will do if the GCP_REORDER flag is not set */
3070 if(lpResults->lpOutString)
3071 memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
3073 if(lpResults->lpOrder)
3075 for(i = 0; i < nSet; i++)
3076 lpResults->lpOrder[i] = i;
3078 } else
3080 BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
3081 nSet, lpResults->lpOrder );
3084 /* FIXME: Will use the placement chars */
3085 if (lpResults->lpDx)
3087 int c;
3088 for (i = 0; i < nSet; i++)
3090 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
3091 lpResults->lpDx[i]= c;
3095 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
3097 int pos = 0;
3099 lpResults->lpCaretPos[0] = 0;
3100 for (i = 1; i < nSet; i++)
3101 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
3102 lpResults->lpCaretPos[i] = (pos += size.cx);
3105 if(lpResults->lpGlyphs)
3106 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
3108 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
3109 ret = MAKELONG(size.cx, size.cy);
3111 return ret;
3114 /*************************************************************************
3115 * GetCharABCWidthsFloatA [GDI32.@]
3117 * See GetCharABCWidthsFloatW.
3119 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3121 INT i, wlen, count = (INT)(last - first + 1);
3122 LPSTR str;
3123 LPWSTR wstr;
3124 BOOL ret = TRUE;
3126 if (count <= 0) return FALSE;
3128 str = HeapAlloc(GetProcessHeap(), 0, count);
3130 for(i = 0; i < count; i++)
3131 str[i] = (BYTE)(first + i);
3133 wstr = FONT_mbtowc( hdc, str, count, &wlen, NULL );
3135 for (i = 0; i < wlen; i++)
3137 if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
3139 ret = FALSE;
3140 break;
3142 abcf++;
3145 HeapFree( GetProcessHeap(), 0, str );
3146 HeapFree( GetProcessHeap(), 0, wstr );
3148 return ret;
3151 /*************************************************************************
3152 * GetCharABCWidthsFloatW [GDI32.@]
3154 * Retrieves widths of a range of characters.
3156 * PARAMS
3157 * hdc [I] Handle to device context.
3158 * first [I] First character in range to query.
3159 * last [I] Last character in range to query.
3160 * abcf [O] Array of LPABCFLOAT structures.
3162 * RETURNS
3163 * Success: TRUE
3164 * Failure: FALSE
3166 * BUGS
3167 * Only works with TrueType fonts. It also doesn't return real
3168 * floats but converted integers because it's implemented on
3169 * top of GetCharABCWidthsW.
3171 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3173 ABC *abc;
3174 unsigned int i, size = sizeof(ABC) * (last - first + 1);
3175 BOOL ret;
3177 TRACE("%p, %d, %d, %p - partial stub\n", hdc, first, last, abcf);
3179 abc = HeapAlloc( GetProcessHeap(), 0, size );
3180 if (!abc) return FALSE;
3182 ret = GetCharABCWidthsW( hdc, first, last, abc );
3183 if (ret)
3185 for (i = first; i <= last; i++, abc++, abcf++)
3187 abcf->abcfA = abc->abcA;
3188 abcf->abcfB = abc->abcB;
3189 abcf->abcfC = abc->abcC;
3192 HeapFree( GetProcessHeap(), 0, abc );
3193 return ret;
3196 /*************************************************************************
3197 * GetCharWidthFloatA [GDI32.@]
3199 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
3200 UINT iLastChar, PFLOAT pxBuffer)
3202 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3203 return 0;
3206 /*************************************************************************
3207 * GetCharWidthFloatW [GDI32.@]
3209 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
3210 UINT iLastChar, PFLOAT pxBuffer)
3212 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3213 return 0;
3217 /***********************************************************************
3219 * Font Resource API *
3221 ***********************************************************************/
3223 /***********************************************************************
3224 * AddFontResourceA (GDI32.@)
3226 INT WINAPI AddFontResourceA( LPCSTR str )
3228 return AddFontResourceExA( str, 0, NULL);
3231 /***********************************************************************
3232 * AddFontResourceW (GDI32.@)
3234 INT WINAPI AddFontResourceW( LPCWSTR str )
3236 return AddFontResourceExW(str, 0, NULL);
3240 /***********************************************************************
3241 * AddFontResourceExA (GDI32.@)
3243 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3245 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3246 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3247 INT ret;
3249 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3250 ret = AddFontResourceExW(strW, fl, pdv);
3251 HeapFree(GetProcessHeap(), 0, strW);
3252 return ret;
3255 static BOOL CALLBACK load_enumed_resource(HMODULE hModule, LPCWSTR type, LPWSTR name, LONG_PTR lParam)
3257 HRSRC rsrc = FindResourceW(hModule, name, type);
3258 HGLOBAL hMem = LoadResource(hModule, rsrc);
3259 LPVOID *pMem = LockResource(hMem);
3260 int *num_total = (int *)lParam;
3261 DWORD num_in_res;
3263 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type));
3264 if (!AddFontMemResourceEx(pMem, SizeofResource(hModule, rsrc), NULL, &num_in_res))
3266 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule, hMem);
3267 return FALSE;
3270 *num_total += num_in_res;
3271 return TRUE;
3274 /***********************************************************************
3275 * AddFontResourceExW (GDI32.@)
3277 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3279 int ret = WineEngAddFontResourceEx(str, fl, pdv);
3280 if (ret == 0)
3282 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3283 HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
3284 if (hModule != NULL)
3286 int num_resources = 0;
3287 LPWSTR rt_font = (LPWSTR)((ULONG_PTR)8); /* we don't want to include winuser.h */
3289 TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3290 wine_dbgstr_w(str));
3291 if (EnumResourceNamesW(hModule, rt_font, load_enumed_resource, (LONG_PTR)&num_resources))
3292 ret = num_resources;
3293 FreeLibrary(hModule);
3296 return ret;
3299 /***********************************************************************
3300 * RemoveFontResourceA (GDI32.@)
3302 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3304 return RemoveFontResourceExA(str, 0, 0);
3307 /***********************************************************************
3308 * RemoveFontResourceW (GDI32.@)
3310 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3312 return RemoveFontResourceExW(str, 0, 0);
3315 /***********************************************************************
3316 * AddFontMemResourceEx (GDI32.@)
3318 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3320 return WineEngAddFontMemResourceEx(pbFont, cbFont, pdv, pcFonts);
3323 /***********************************************************************
3324 * RemoveFontMemResourceEx (GDI32.@)
3326 BOOL WINAPI RemoveFontMemResourceEx( HANDLE fh )
3328 FIXME("(%p) stub\n", fh);
3329 return TRUE;
3332 /***********************************************************************
3333 * RemoveFontResourceExA (GDI32.@)
3335 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3337 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3338 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3339 INT ret;
3341 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3342 ret = RemoveFontResourceExW(strW, fl, pdv);
3343 HeapFree(GetProcessHeap(), 0, strW);
3344 return ret;
3347 /***********************************************************************
3348 * RemoveFontResourceExW (GDI32.@)
3350 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3352 return WineEngRemoveFontResourceEx(str, fl, pdv);
3355 /***********************************************************************
3356 * GetTextCharset (GDI32.@)
3358 UINT WINAPI GetTextCharset(HDC hdc)
3360 /* MSDN docs say this is equivalent */
3361 return GetTextCharsetInfo(hdc, NULL, 0);
3364 /***********************************************************************
3365 * GetTextCharsetInfo (GDI32.@)
3367 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3369 UINT ret = DEFAULT_CHARSET;
3370 DC *dc = DC_GetDCPtr(hdc);
3372 if (dc)
3374 if (dc->gdiFont)
3375 ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
3377 DC_ReleaseDCPtr( dc );
3380 if (ret == DEFAULT_CHARSET && fs)
3381 memset(fs, 0, sizeof(FONTSIGNATURE));
3382 return ret;
3385 /***********************************************************************
3386 * GdiGetCharDimensions (GDI32.@)
3388 * Gets the average width of the characters in the English alphabet.
3390 * PARAMS
3391 * hdc [I] Handle to the device context to measure on.
3392 * lptm [O] Pointer to memory to store the text metrics into.
3393 * height [O] On exit, the maximum height of characters in the English alphabet.
3395 * RETURNS
3396 * The average width of characters in the English alphabet.
3398 * NOTES
3399 * This function is used by the dialog manager to get the size of a dialog
3400 * unit. It should also be used by other pieces of code that need to know
3401 * the size of a dialog unit in logical units without having access to the
3402 * window handle of the dialog.
3403 * Windows caches the font metrics from this function, but we don't and
3404 * there doesn't appear to be an immediate advantage to do so.
3406 * SEE ALSO
3407 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3409 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3411 SIZE sz;
3412 static const WCHAR alphabet[] = {
3413 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3414 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3415 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3417 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3419 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3421 if (height) *height = sz.cy;
3422 return (sz.cx / 26 + 1) / 2;
3425 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3427 FIXME("(%d): stub\n", fEnableEUDC);
3428 return FALSE;
3431 /***********************************************************************
3432 * GetCharWidthI (GDI32.@)
3434 * Retrieve widths of characters.
3436 * PARAMS
3437 * hdc [I] Handle to a device context.
3438 * first [I] First glyph in range to query.
3439 * count [I] Number of glyph indices to query.
3440 * glyphs [I] Array of glyphs to query.
3441 * buffer [O] Buffer to receive character widths.
3443 * NOTES
3444 * Only works with TrueType fonts.
3446 * RETURNS
3447 * Success: TRUE
3448 * Failure: FALSE
3450 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3452 ABC *abc;
3453 unsigned int i;
3455 TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3457 if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3458 return FALSE;
3460 if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3462 HeapFree(GetProcessHeap(), 0, abc);
3463 return FALSE;
3466 for (i = 0; i < count; i++)
3467 buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3469 HeapFree(GetProcessHeap(), 0, abc);
3470 return TRUE;
3473 /***********************************************************************
3474 * GetFontUnicodeRanges (GDI32.@)
3476 * Retrieve a list of supported Unicode characters in a font.
3478 * PARAMS
3479 * hdc [I] Handle to a device context.
3480 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3482 * RETURNS
3483 * Success: Number of bytes written to the buffer pointed to by lpgs.
3484 * Failure: 0
3487 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3489 DWORD ret = 0;
3490 DC *dc = DC_GetDCPtr(hdc);
3492 TRACE("(%p, %p)\n", hdc, lpgs);
3494 if (!dc) return 0;
3496 if (dc->gdiFont) ret = WineEngGetFontUnicodeRanges(dc->gdiFont, lpgs);
3497 DC_ReleaseDCPtr(dc);
3498 return ret;
3502 /*************************************************************
3503 * FontIsLinked (GDI32.@)
3505 BOOL WINAPI FontIsLinked(HDC hdc)
3507 DC *dc = DC_GetDCPtr(hdc);
3508 BOOL ret = FALSE;
3510 if (!dc) return FALSE;
3511 if (dc->gdiFont) ret = WineEngFontIsLinked(dc->gdiFont);
3512 DC_ReleaseDCPtr(dc);
3513 TRACE("returning %d\n", ret);
3514 return ret;