gdi32: Move EnumFonts16 and EnumFontFamilies16 to gdi16.c.
[wine/wine-kai.git] / dlls / gdi32 / font.c
blobe2aca593f21401cd444f3f0e28e51e13c9514492
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_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
91 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
92 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj );
94 static const struct gdi_obj_funcs font_funcs =
96 FONT_SelectObject, /* pSelectObject */
97 FONT_GetObjectA, /* pGetObjectA */
98 FONT_GetObjectW, /* pGetObjectW */
99 NULL, /* pUnrealizeObject */
100 FONT_DeleteObject /* pDeleteObject */
103 #define ENUM_UNICODE 0x00000001
104 #define ENUM_CALLED 0x00000002
106 typedef struct
108 GDIOBJHDR header;
109 LOGFONTW logfont;
110 } FONTOBJ;
112 typedef struct
114 LPLOGFONT16 lpLogFontParam;
115 FONTENUMPROC16 lpEnumFunc;
116 LPARAM lpData;
118 LPNEWTEXTMETRICEX16 lpTextMetric;
119 LPENUMLOGFONTEX16 lpLogFont;
120 SEGPTR segTextMetric;
121 SEGPTR segLogFont;
122 DWORD dwFlags;
123 HDC hdc;
124 } fontEnum16;
126 typedef struct
128 LPLOGFONTW lpLogFontParam;
129 FONTENUMPROCW lpEnumFunc;
130 LPARAM lpData;
131 DWORD dwFlags;
132 HDC hdc;
133 } fontEnum32;
136 * For TranslateCharsetInfo
138 #define MAXTCIINDEX 32
139 static const CHARSETINFO FONT_tci[MAXTCIINDEX] = {
140 /* ANSI */
141 { ANSI_CHARSET, 1252, {{0,0,0,0},{FS_LATIN1,0}} },
142 { EASTEUROPE_CHARSET, 1250, {{0,0,0,0},{FS_LATIN2,0}} },
143 { RUSSIAN_CHARSET, 1251, {{0,0,0,0},{FS_CYRILLIC,0}} },
144 { GREEK_CHARSET, 1253, {{0,0,0,0},{FS_GREEK,0}} },
145 { TURKISH_CHARSET, 1254, {{0,0,0,0},{FS_TURKISH,0}} },
146 { HEBREW_CHARSET, 1255, {{0,0,0,0},{FS_HEBREW,0}} },
147 { ARABIC_CHARSET, 1256, {{0,0,0,0},{FS_ARABIC,0}} },
148 { BALTIC_CHARSET, 1257, {{0,0,0,0},{FS_BALTIC,0}} },
149 { VIETNAMESE_CHARSET, 1258, {{0,0,0,0},{FS_VIETNAMESE,0}} },
150 /* reserved by ANSI */
151 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
152 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
153 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
154 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
155 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
156 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
157 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
158 /* ANSI and OEM */
159 { THAI_CHARSET, 874, {{0,0,0,0},{FS_THAI,0}} },
160 { SHIFTJIS_CHARSET, 932, {{0,0,0,0},{FS_JISJAPAN,0}} },
161 { GB2312_CHARSET, 936, {{0,0,0,0},{FS_CHINESESIMP,0}} },
162 { HANGEUL_CHARSET, 949, {{0,0,0,0},{FS_WANSUNG,0}} },
163 { CHINESEBIG5_CHARSET, 950, {{0,0,0,0},{FS_CHINESETRAD,0}} },
164 { JOHAB_CHARSET, 1361, {{0,0,0,0},{FS_JOHAB,0}} },
165 /* reserved for alternate ANSI and OEM */
166 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
167 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
168 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
169 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
170 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
171 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
172 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
173 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
174 /* reserved for system */
175 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
176 { SYMBOL_CHARSET, CP_SYMBOL, {{0,0,0,0},{FS_SYMBOL,0}} }
179 /***********************************************************************
180 * LOGFONT conversion functions.
182 static void FONT_LogFontWTo16( const LOGFONTW* font32, LPLOGFONT16 font16 )
184 font16->lfHeight = font32->lfHeight;
185 font16->lfWidth = font32->lfWidth;
186 font16->lfEscapement = font32->lfEscapement;
187 font16->lfOrientation = font32->lfOrientation;
188 font16->lfWeight = font32->lfWeight;
189 font16->lfItalic = font32->lfItalic;
190 font16->lfUnderline = font32->lfUnderline;
191 font16->lfStrikeOut = font32->lfStrikeOut;
192 font16->lfCharSet = font32->lfCharSet;
193 font16->lfOutPrecision = font32->lfOutPrecision;
194 font16->lfClipPrecision = font32->lfClipPrecision;
195 font16->lfQuality = font32->lfQuality;
196 font16->lfPitchAndFamily = font32->lfPitchAndFamily;
197 WideCharToMultiByte( CP_ACP, 0, font32->lfFaceName, -1,
198 font16->lfFaceName, LF_FACESIZE, NULL, NULL );
199 font16->lfFaceName[LF_FACESIZE-1] = 0;
202 static void FONT_LogFont16ToW( const LOGFONT16 *font16, LPLOGFONTW font32 )
204 font32->lfHeight = font16->lfHeight;
205 font32->lfWidth = font16->lfWidth;
206 font32->lfEscapement = font16->lfEscapement;
207 font32->lfOrientation = font16->lfOrientation;
208 font32->lfWeight = font16->lfWeight;
209 font32->lfItalic = font16->lfItalic;
210 font32->lfUnderline = font16->lfUnderline;
211 font32->lfStrikeOut = font16->lfStrikeOut;
212 font32->lfCharSet = font16->lfCharSet;
213 font32->lfOutPrecision = font16->lfOutPrecision;
214 font32->lfClipPrecision = font16->lfClipPrecision;
215 font32->lfQuality = font16->lfQuality;
216 font32->lfPitchAndFamily = font16->lfPitchAndFamily;
217 MultiByteToWideChar( CP_ACP, 0, font16->lfFaceName, -1, font32->lfFaceName, LF_FACESIZE );
218 font32->lfFaceName[LF_FACESIZE-1] = 0;
221 static void FONT_LogFontAToW( const LOGFONTA *fontA, LPLOGFONTW fontW )
223 memcpy(fontW, fontA, sizeof(LOGFONTA) - LF_FACESIZE);
224 MultiByteToWideChar(CP_ACP, 0, fontA->lfFaceName, -1, fontW->lfFaceName,
225 LF_FACESIZE);
226 fontW->lfFaceName[LF_FACESIZE-1] = 0;
229 static void FONT_LogFontWToA( const LOGFONTW *fontW, LPLOGFONTA fontA )
231 memcpy(fontA, fontW, sizeof(LOGFONTA) - LF_FACESIZE);
232 WideCharToMultiByte(CP_ACP, 0, fontW->lfFaceName, -1, fontA->lfFaceName,
233 LF_FACESIZE, NULL, NULL);
234 fontA->lfFaceName[LF_FACESIZE-1] = 0;
237 static void FONT_EnumLogFontExWTo16( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEX16 font16 )
239 FONT_LogFontWTo16( (const LOGFONTW *)fontW, (LPLOGFONT16)font16);
241 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
242 (LPSTR) font16->elfFullName, LF_FULLFACESIZE, NULL, NULL );
243 font16->elfFullName[LF_FULLFACESIZE-1] = '\0';
244 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
245 (LPSTR) font16->elfStyle, LF_FACESIZE, NULL, NULL );
246 font16->elfStyle[LF_FACESIZE-1] = '\0';
247 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
248 (LPSTR) font16->elfScript, LF_FACESIZE, NULL, NULL );
249 font16->elfScript[LF_FACESIZE-1] = '\0';
252 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEXA fontA )
254 FONT_LogFontWToA( (const LOGFONTW *)fontW, (LPLOGFONTA)fontA);
256 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
257 (LPSTR) fontA->elfFullName, LF_FULLFACESIZE, NULL, NULL );
258 fontA->elfFullName[LF_FULLFACESIZE-1] = '\0';
259 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
260 (LPSTR) fontA->elfStyle, LF_FACESIZE, NULL, NULL );
261 fontA->elfStyle[LF_FACESIZE-1] = '\0';
262 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
263 (LPSTR) fontA->elfScript, LF_FACESIZE, NULL, NULL );
264 fontA->elfScript[LF_FACESIZE-1] = '\0';
267 /***********************************************************************
268 * TEXTMETRIC conversion functions.
270 static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
272 ptmA->tmHeight = ptmW->tmHeight;
273 ptmA->tmAscent = ptmW->tmAscent;
274 ptmA->tmDescent = ptmW->tmDescent;
275 ptmA->tmInternalLeading = ptmW->tmInternalLeading;
276 ptmA->tmExternalLeading = ptmW->tmExternalLeading;
277 ptmA->tmAveCharWidth = ptmW->tmAveCharWidth;
278 ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth;
279 ptmA->tmWeight = ptmW->tmWeight;
280 ptmA->tmOverhang = ptmW->tmOverhang;
281 ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX;
282 ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
283 ptmA->tmFirstChar = min(ptmW->tmFirstChar, 255);
284 if (ptmW->tmCharSet == SYMBOL_CHARSET)
286 UINT last_char = ptmW->tmLastChar;
287 if (last_char > 0xf000) last_char -= 0xf000;
288 ptmA->tmLastChar = min(last_char, 255);
290 else
291 ptmA->tmLastChar = min(ptmW->tmLastChar, 255);
292 ptmA->tmDefaultChar = min(ptmW->tmDefaultChar, 255);
293 ptmA->tmBreakChar = min(ptmW->tmBreakChar, 255);
294 ptmA->tmItalic = ptmW->tmItalic;
295 ptmA->tmUnderlined = ptmW->tmUnderlined;
296 ptmA->tmStruckOut = ptmW->tmStruckOut;
297 ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
298 ptmA->tmCharSet = ptmW->tmCharSet;
302 static void FONT_NewTextMetricExWTo16(const NEWTEXTMETRICEXW *ptmW, LPNEWTEXTMETRICEX16 ptm16 )
304 ptm16->ntmTm.tmHeight = ptmW->ntmTm.tmHeight;
305 ptm16->ntmTm.tmAscent = ptmW->ntmTm.tmAscent;
306 ptm16->ntmTm.tmDescent = ptmW->ntmTm.tmDescent;
307 ptm16->ntmTm.tmInternalLeading = ptmW->ntmTm.tmInternalLeading;
308 ptm16->ntmTm.tmExternalLeading = ptmW->ntmTm.tmExternalLeading;
309 ptm16->ntmTm.tmAveCharWidth = ptmW->ntmTm.tmAveCharWidth;
310 ptm16->ntmTm.tmMaxCharWidth = ptmW->ntmTm.tmMaxCharWidth;
311 ptm16->ntmTm.tmWeight = ptmW->ntmTm.tmWeight;
312 ptm16->ntmTm.tmOverhang = ptmW->ntmTm.tmOverhang;
313 ptm16->ntmTm.tmDigitizedAspectX = ptmW->ntmTm.tmDigitizedAspectX;
314 ptm16->ntmTm.tmDigitizedAspectY = ptmW->ntmTm.tmDigitizedAspectY;
315 ptm16->ntmTm.tmFirstChar = ptmW->ntmTm.tmFirstChar > 255 ? 255 : ptmW->ntmTm.tmFirstChar;
316 ptm16->ntmTm.tmLastChar = ptmW->ntmTm.tmLastChar > 255 ? 255 : ptmW->ntmTm.tmLastChar;
317 ptm16->ntmTm.tmDefaultChar = ptmW->ntmTm.tmDefaultChar > 255 ? 255 : ptmW->ntmTm.tmDefaultChar;
318 ptm16->ntmTm.tmBreakChar = ptmW->ntmTm.tmBreakChar > 255 ? 255 : ptmW->ntmTm.tmBreakChar;
319 ptm16->ntmTm.tmItalic = ptmW->ntmTm.tmItalic;
320 ptm16->ntmTm.tmUnderlined = ptmW->ntmTm.tmUnderlined;
321 ptm16->ntmTm.tmStruckOut = ptmW->ntmTm.tmStruckOut;
322 ptm16->ntmTm.tmPitchAndFamily = ptmW->ntmTm.tmPitchAndFamily;
323 ptm16->ntmTm.tmCharSet = ptmW->ntmTm.tmCharSet;
324 ptm16->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
325 ptm16->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
326 ptm16->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
327 ptm16->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
328 memcpy(&ptm16->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
331 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW *ptmW, NEWTEXTMETRICEXA *ptmA )
333 FONT_TextMetricWToA((const TEXTMETRICW *)ptmW, (LPTEXTMETRICA)ptmA);
334 ptmA->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
335 ptmA->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
336 ptmA->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
337 ptmA->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
338 memcpy(&ptmA->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
342 /***********************************************************************
343 * GdiGetCodePage (GDI32.@)
345 DWORD WINAPI GdiGetCodePage( HDC hdc )
347 UINT cp = CP_ACP;
348 CHARSETINFO csi;
349 int charset = GetTextCharset(hdc);
351 /* Hmm, nicely designed api this one! */
352 if(TranslateCharsetInfo(ULongToPtr(charset), &csi, TCI_SRCCHARSET))
353 cp = csi.ciACP;
354 else {
355 switch(charset) {
356 case OEM_CHARSET:
357 cp = GetOEMCP();
358 break;
359 case DEFAULT_CHARSET:
360 cp = GetACP();
361 break;
363 case VISCII_CHARSET:
364 case TCVN_CHARSET:
365 case KOI8_CHARSET:
366 case ISO3_CHARSET:
367 case ISO4_CHARSET:
368 case ISO10_CHARSET:
369 case CELTIC_CHARSET:
370 /* FIXME: These have no place here, but because x11drv
371 enumerates fonts with these (made up) charsets some apps
372 might use them and then the FIXME below would become
373 annoying. Now we could pick the intended codepage for
374 each of these, but since it's broken anyway we'll just
375 use CP_ACP and hope it'll go away...
377 cp = CP_ACP;
378 break;
380 default:
381 FIXME("Can't find codepage for charset %d\n", charset);
382 break;
386 TRACE("charset %d => cp %d\n", charset, cp);
387 return cp;
390 /***********************************************************************
391 * FONT_mbtowc
393 * Returns a Unicode translation of str using the charset of the
394 * currently selected font in hdc. If count is -1 then str is assumed
395 * to be '\0' terminated, otherwise it contains the number of bytes to
396 * convert. If plenW is non-NULL, on return it will point to the
397 * number of WCHARs that have been written. If pCP is non-NULL, on
398 * return it will point to the codepage used in the conversion. The
399 * caller should free the returned LPWSTR from the process heap
400 * itself.
402 static LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
404 UINT cp;
405 INT lenW;
406 LPWSTR strW;
408 cp = GdiGetCodePage( hdc );
410 if(count == -1) count = strlen(str);
411 lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
412 strW = HeapAlloc(GetProcessHeap(), 0, lenW*sizeof(WCHAR));
413 MultiByteToWideChar(cp, 0, str, count, strW, lenW);
414 TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW));
415 if(plenW) *plenW = lenW;
416 if(pCP) *pCP = cp;
417 return strW;
421 /***********************************************************************
422 * CreateFontIndirectA (GDI32.@)
424 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *plfA )
426 LOGFONTW lfW;
428 if (!plfA) return 0;
430 FONT_LogFontAToW( plfA, &lfW );
431 return CreateFontIndirectW( &lfW );
434 /***********************************************************************
435 * CreateFontIndirectW (GDI32.@)
437 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
439 static const WCHAR ItalicW[] = {' ','I','t','a','l','i','c','\0'};
440 static const WCHAR BoldW[] = {' ','B','o','l','d','\0'};
441 WCHAR *pFaceNameItalicSuffix, *pFaceNameBoldSuffix;
442 WCHAR *pFaceNameSuffix = NULL;
443 HFONT hFont;
444 FONTOBJ *fontPtr;
446 if (!plf) return 0;
448 if (!(fontPtr = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC, (HGDIOBJ *)&hFont,
449 &font_funcs ))) return 0;
451 memcpy( &fontPtr->logfont, plf, sizeof(LOGFONTW) );
453 TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
454 plf->lfHeight, plf->lfWidth,
455 plf->lfEscapement, plf->lfOrientation,
456 plf->lfPitchAndFamily,
457 plf->lfOutPrecision, plf->lfClipPrecision,
458 plf->lfQuality, plf->lfCharSet,
459 debugstr_w(plf->lfFaceName),
460 plf->lfWeight > 400 ? "Bold" : "",
461 plf->lfItalic ? "Italic" : "",
462 plf->lfUnderline ? "Underline" : "", hFont);
464 if (plf->lfEscapement != plf->lfOrientation)
466 /* this should really depend on whether GM_ADVANCED is set */
467 fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
468 WARN("orientation angle %f set to "
469 "escapement angle %f for new font %p\n",
470 plf->lfOrientation/10., plf->lfEscapement/10., hFont);
473 pFaceNameItalicSuffix = strstrW(fontPtr->logfont.lfFaceName, ItalicW);
474 if (pFaceNameItalicSuffix)
476 fontPtr->logfont.lfItalic = TRUE;
477 pFaceNameSuffix = pFaceNameItalicSuffix;
480 pFaceNameBoldSuffix = strstrW(fontPtr->logfont.lfFaceName, BoldW);
481 if (pFaceNameBoldSuffix)
483 if (fontPtr->logfont.lfWeight < FW_BOLD)
484 fontPtr->logfont.lfWeight = FW_BOLD;
485 if (!pFaceNameSuffix || (pFaceNameBoldSuffix < pFaceNameSuffix))
486 pFaceNameSuffix = pFaceNameBoldSuffix;
489 if (pFaceNameSuffix) *pFaceNameSuffix = 0;
491 GDI_ReleaseObj( hFont );
492 return hFont;
495 /*************************************************************************
496 * CreateFontA (GDI32.@)
498 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
499 INT orient, INT weight, DWORD italic,
500 DWORD underline, DWORD strikeout, DWORD charset,
501 DWORD outpres, DWORD clippres, DWORD quality,
502 DWORD pitch, LPCSTR name )
504 LOGFONTA logfont;
506 logfont.lfHeight = height;
507 logfont.lfWidth = width;
508 logfont.lfEscapement = esc;
509 logfont.lfOrientation = orient;
510 logfont.lfWeight = weight;
511 logfont.lfItalic = italic;
512 logfont.lfUnderline = underline;
513 logfont.lfStrikeOut = strikeout;
514 logfont.lfCharSet = charset;
515 logfont.lfOutPrecision = outpres;
516 logfont.lfClipPrecision = clippres;
517 logfont.lfQuality = quality;
518 logfont.lfPitchAndFamily = pitch;
520 if (name)
521 lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
522 else
523 logfont.lfFaceName[0] = '\0';
525 return CreateFontIndirectA( &logfont );
528 /*************************************************************************
529 * CreateFontW (GDI32.@)
531 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
532 INT orient, INT weight, DWORD italic,
533 DWORD underline, DWORD strikeout, DWORD charset,
534 DWORD outpres, DWORD clippres, DWORD quality,
535 DWORD pitch, LPCWSTR name )
537 LOGFONTW logfont;
539 logfont.lfHeight = height;
540 logfont.lfWidth = width;
541 logfont.lfEscapement = esc;
542 logfont.lfOrientation = orient;
543 logfont.lfWeight = weight;
544 logfont.lfItalic = italic;
545 logfont.lfUnderline = underline;
546 logfont.lfStrikeOut = strikeout;
547 logfont.lfCharSet = charset;
548 logfont.lfOutPrecision = outpres;
549 logfont.lfClipPrecision = clippres;
550 logfont.lfQuality = quality;
551 logfont.lfPitchAndFamily = pitch;
553 if (name)
554 lstrcpynW(logfont.lfFaceName, name,
555 sizeof(logfont.lfFaceName) / sizeof(WCHAR));
556 else
557 logfont.lfFaceName[0] = '\0';
559 return CreateFontIndirectW( &logfont );
563 /***********************************************************************
564 * FONT_SelectObject
566 * If the driver supports vector fonts we create a gdi font first and
567 * then call the driver to give it a chance to supply its own device
568 * font. If the driver wants to do this it returns TRUE and we can
569 * delete the gdi font, if the driver wants to use the gdi font it
570 * should return FALSE, to signal an error return GDI_ERROR. For
571 * drivers that don't support vector fonts they must supply their own
572 * font.
574 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc )
576 HGDIOBJ ret = 0;
577 DC *dc = get_dc_ptr( hdc );
579 if (!dc) return 0;
581 if (!GDI_inc_ref_count( handle ))
583 release_dc_ptr( dc );
584 return 0;
587 if (dc->hFont != handle || dc->gdiFont == NULL)
589 if(GetDeviceCaps(dc->hSelf, TEXTCAPS) & TC_VA_ABLE)
591 FONTOBJ *font = GDI_GetObjPtr( handle, FONT_MAGIC ); /* to grab the GDI lock (FIXME) */
592 dc->gdiFont = WineEngCreateFontInstance(dc, handle);
593 if (font) GDI_ReleaseObj( handle );
597 if (dc->funcs->pSelectFont) ret = dc->funcs->pSelectFont( dc->physDev, handle, dc->gdiFont );
599 if (ret && dc->gdiFont) dc->gdiFont = 0;
601 if (ret == HGDI_ERROR)
603 GDI_dec_ref_count( handle );
604 ret = 0; /* SelectObject returns 0 on error */
606 else
608 ret = dc->hFont;
609 dc->hFont = handle;
610 GDI_dec_ref_count( ret );
612 release_dc_ptr( dc );
613 return ret;
617 /***********************************************************************
618 * FONT_GetObjectA
620 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
622 FONTOBJ *font = obj;
623 LOGFONTA lfA;
625 if(!buffer)
626 return sizeof(lfA);
627 FONT_LogFontWToA( &font->logfont, &lfA );
629 if (count > sizeof(lfA)) count = sizeof(lfA);
630 memcpy( buffer, &lfA, count );
631 return count;
634 /***********************************************************************
635 * FONT_GetObjectW
637 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
639 FONTOBJ *font = obj;
640 if(!buffer)
641 return sizeof(LOGFONTW);
642 if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
643 memcpy( buffer, &font->logfont, count );
644 return count;
648 /***********************************************************************
649 * FONT_DeleteObject
651 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj )
653 WineEngDestroyFontInstance( handle );
654 return GDI_FreeObject( handle, obj );
658 /***********************************************************************
659 * FONT_EnumInstance16
661 * Called by the device driver layer to pass font info
662 * down to the application.
664 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
665 * We have to use other types because of the FONTENUMPROCW definition.
667 static INT CALLBACK FONT_EnumInstance16( const LOGFONTW *plf, const TEXTMETRICW *ptm,
668 DWORD fType, LPARAM lp )
670 fontEnum16 *pfe = (fontEnum16*)lp;
671 INT ret = 1;
673 if (!pfe->lpLogFontParam ||
674 pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
675 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet )
677 WORD args[7];
678 DWORD result;
680 FONT_EnumLogFontExWTo16((const ENUMLOGFONTEXW *)plf, pfe->lpLogFont);
681 FONT_NewTextMetricExWTo16((const NEWTEXTMETRICEXW *)ptm, pfe->lpTextMetric);
682 pfe->dwFlags |= ENUM_CALLED;
684 args[6] = SELECTOROF(pfe->segLogFont);
685 args[5] = OFFSETOF(pfe->segLogFont);
686 args[4] = SELECTOROF(pfe->segTextMetric);
687 args[3] = OFFSETOF(pfe->segTextMetric);
688 args[2] = fType;
689 args[1] = HIWORD(pfe->lpData);
690 args[0] = LOWORD(pfe->lpData);
691 WOWCallback16Ex( (DWORD)pfe->lpEnumFunc, WCB16_PASCAL, sizeof(args), args, &result );
692 ret = LOWORD(result);
694 return ret;
697 /***********************************************************************
698 * FONT_EnumInstance
700 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
701 * We have to use other types because of the FONTENUMPROCW definition.
703 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
704 DWORD fType, LPARAM lp )
706 fontEnum32 *pfe = (fontEnum32*)lp;
707 INT ret = 1;
709 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
710 if ((!pfe->lpLogFontParam ||
711 pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
712 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
713 (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
715 /* convert font metrics */
716 ENUMLOGFONTEXA logfont;
717 NEWTEXTMETRICEXA tmA;
719 pfe->dwFlags |= ENUM_CALLED;
720 if (!(pfe->dwFlags & ENUM_UNICODE))
722 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
723 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
724 plf = (LOGFONTW *)&logfont.elfLogFont;
725 ptm = (TEXTMETRICW *)&tmA;
728 ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
730 return ret;
733 /***********************************************************************
734 * EnumFontFamiliesEx (GDI.613)
736 INT16 WINAPI EnumFontFamiliesEx16( HDC16 hDC, LPLOGFONT16 plf,
737 FONTENUMPROC16 efproc, LPARAM lParam,
738 DWORD dwFlags)
740 fontEnum16 fe16;
741 INT16 ret = 1, ret2;
742 DC* dc = get_dc_ptr( HDC_32(hDC) );
743 NEWTEXTMETRICEX16 tm16;
744 ENUMLOGFONTEX16 lf16;
745 LOGFONTW lfW, *plfW;
746 BOOL enum_gdi_fonts;
748 if (!dc) return 0;
750 if (plf)
752 FONT_LogFont16ToW(plf, &lfW);
753 plfW = &lfW;
755 else plfW = NULL;
757 fe16.hdc = HDC_32(hDC);
758 fe16.lpLogFontParam = plf;
759 fe16.lpEnumFunc = efproc;
760 fe16.lpData = lParam;
761 fe16.lpTextMetric = &tm16;
762 fe16.lpLogFont = &lf16;
763 fe16.segTextMetric = MapLS( &tm16 );
764 fe16.segLogFont = MapLS( &lf16 );
765 fe16.dwFlags = 0;
767 enum_gdi_fonts = GetDeviceCaps(fe16.hdc, TEXTCAPS) & TC_VA_ABLE;
769 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
771 ret = 0;
772 goto done;
775 if (enum_gdi_fonts)
776 ret = WineEngEnumFonts( plfW, FONT_EnumInstance16, (LPARAM)&fe16 );
777 fe16.dwFlags &= ~ENUM_CALLED;
778 if (ret && dc->funcs->pEnumDeviceFonts) {
779 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, plfW, FONT_EnumInstance16, (LPARAM)&fe16 );
780 if(fe16.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
781 ret = ret2;
783 done:
784 UnMapLS( fe16.segTextMetric );
785 UnMapLS( fe16.segLogFont );
786 release_dc_ptr( dc );
787 return ret;
790 /***********************************************************************
791 * FONT_EnumFontFamiliesEx
793 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf,
794 FONTENUMPROCW efproc,
795 LPARAM lParam, DWORD dwUnicode)
797 INT ret = 1, ret2;
798 DC *dc = get_dc_ptr( hDC );
799 fontEnum32 fe32;
800 BOOL enum_gdi_fonts;
802 if (!dc) return 0;
804 if (plf)
805 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName),
806 plf->lfCharSet);
807 fe32.lpLogFontParam = plf;
808 fe32.lpEnumFunc = efproc;
809 fe32.lpData = lParam;
810 fe32.dwFlags = dwUnicode;
811 fe32.hdc = hDC;
813 enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE;
815 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
817 ret = 0;
818 goto done;
821 if (enum_gdi_fonts)
822 ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
823 fe32.dwFlags &= ~ENUM_CALLED;
824 if (ret && dc->funcs->pEnumDeviceFonts) {
825 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, plf, FONT_EnumInstance, (LPARAM)&fe32 );
826 if(fe32.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
827 ret = ret2;
829 done:
830 release_dc_ptr( dc );
831 return ret;
834 /***********************************************************************
835 * EnumFontFamiliesExW (GDI32.@)
837 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
838 FONTENUMPROCW efproc,
839 LPARAM lParam, DWORD dwFlags )
841 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, ENUM_UNICODE );
844 /***********************************************************************
845 * EnumFontFamiliesExA (GDI32.@)
847 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
848 FONTENUMPROCA efproc,
849 LPARAM lParam, DWORD dwFlags)
851 LOGFONTW lfW, *plfW;
853 if (plf)
855 FONT_LogFontAToW( plf, &lfW );
856 plfW = &lfW;
858 else plfW = NULL;
860 return FONT_EnumFontFamiliesEx( hDC, plfW, (FONTENUMPROCW)efproc, lParam, 0);
863 /***********************************************************************
864 * EnumFontFamiliesA (GDI32.@)
866 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
867 FONTENUMPROCA efproc, LPARAM lpData )
869 LOGFONTA lf, *plf;
871 if (lpFamily)
873 if (!*lpFamily) return 1;
874 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
875 lf.lfCharSet = DEFAULT_CHARSET;
876 lf.lfPitchAndFamily = 0;
877 plf = &lf;
879 else plf = NULL;
881 return EnumFontFamiliesExA( hDC, plf, efproc, lpData, 0 );
884 /***********************************************************************
885 * EnumFontFamiliesW (GDI32.@)
887 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
888 FONTENUMPROCW efproc, LPARAM lpData )
890 LOGFONTW lf, *plf;
892 if (lpFamily)
894 if (!*lpFamily) return 1;
895 lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
896 lf.lfCharSet = DEFAULT_CHARSET;
897 lf.lfPitchAndFamily = 0;
898 plf = &lf;
900 else plf = NULL;
902 return EnumFontFamiliesExW( hDC, plf, efproc, lpData, 0 );
905 /***********************************************************************
906 * EnumFontsA (GDI32.@)
908 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
909 LPARAM lpData )
911 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
914 /***********************************************************************
915 * EnumFontsW (GDI32.@)
917 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
918 LPARAM lpData )
920 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
924 /***********************************************************************
925 * GetTextCharacterExtra (GDI32.@)
927 INT WINAPI GetTextCharacterExtra( HDC hdc )
929 INT ret;
930 DC *dc = get_dc_ptr( hdc );
931 if (!dc) return 0x80000000;
932 ret = dc->charExtra;
933 release_dc_ptr( dc );
934 return ret;
938 /***********************************************************************
939 * SetTextCharacterExtra (GDI32.@)
941 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
943 INT prev;
944 DC * dc = get_dc_ptr( hdc );
945 if (!dc) return 0x80000000;
946 if (dc->funcs->pSetTextCharacterExtra)
947 prev = dc->funcs->pSetTextCharacterExtra( dc->physDev, extra );
948 else
950 prev = dc->charExtra;
951 dc->charExtra = extra;
953 release_dc_ptr( dc );
954 return prev;
958 /***********************************************************************
959 * SetTextJustification (GDI32.@)
961 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
963 BOOL ret = TRUE;
964 DC * dc = get_dc_ptr( hdc );
965 if (!dc) return FALSE;
966 if (dc->funcs->pSetTextJustification)
967 ret = dc->funcs->pSetTextJustification( dc->physDev, extra, breaks );
968 else
970 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
971 if (!extra) breaks = 0;
972 if (breaks)
974 dc->breakExtra = extra / breaks;
975 dc->breakRem = extra - (breaks * dc->breakExtra);
977 else
979 dc->breakExtra = 0;
980 dc->breakRem = 0;
983 release_dc_ptr( dc );
984 return ret;
988 /***********************************************************************
989 * GetTextFaceA (GDI32.@)
991 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
993 INT res = GetTextFaceW(hdc, 0, NULL);
994 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
995 GetTextFaceW( hdc, res, nameW );
997 if (name)
999 if (count && !WideCharToMultiByte( CP_ACP, 0, nameW, -1, name, count, NULL, NULL))
1000 name[count-1] = 0;
1001 res = strlen(name);
1003 else
1004 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
1005 HeapFree( GetProcessHeap(), 0, nameW );
1006 return res;
1009 /***********************************************************************
1010 * GetTextFaceW (GDI32.@)
1012 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
1014 FONTOBJ *font;
1015 INT ret = 0;
1017 DC * dc = get_dc_ptr( hdc );
1018 if (!dc) return 0;
1020 if(dc->gdiFont)
1021 ret = WineEngGetTextFace(dc->gdiFont, count, name);
1022 else if ((font = (FONTOBJ *) GDI_GetObjPtr( dc->hFont, FONT_MAGIC )))
1024 if (name)
1026 lstrcpynW( name, font->logfont.lfFaceName, count );
1027 ret = strlenW(name);
1029 else ret = strlenW(font->logfont.lfFaceName) + 1;
1030 GDI_ReleaseObj( dc->hFont );
1032 release_dc_ptr( dc );
1033 return ret;
1037 /***********************************************************************
1038 * GetTextExtentPoint32A (GDI32.@)
1040 * See GetTextExtentPoint32W.
1042 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
1043 LPSIZE size )
1045 BOOL ret = FALSE;
1046 INT wlen;
1047 LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1049 if (p) {
1050 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
1051 HeapFree( GetProcessHeap(), 0, p );
1054 TRACE("(%p %s %d %p): returning %d x %d\n",
1055 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
1056 return ret;
1060 /***********************************************************************
1061 * GetTextExtentPoint32W [GDI32.@]
1063 * Computes width/height for a string.
1065 * Computes width and height of the specified string.
1067 * RETURNS
1068 * Success: TRUE
1069 * Failure: FALSE
1071 BOOL WINAPI GetTextExtentPoint32W(
1072 HDC hdc, /* [in] Handle of device context */
1073 LPCWSTR str, /* [in] Address of text string */
1074 INT count, /* [in] Number of characters in string */
1075 LPSIZE size) /* [out] Address of structure for string size */
1077 return GetTextExtentExPointW(hdc, str, count, 0, NULL, NULL, size);
1080 /***********************************************************************
1081 * GetTextExtentExPointI [GDI32.@]
1083 * Computes width and height of the array of glyph indices.
1085 * PARAMS
1086 * hdc [I] Handle of device context.
1087 * indices [I] Glyph index array.
1088 * count [I] Number of glyphs in array.
1089 * max_ext [I] Maximum width in glyphs.
1090 * nfit [O] Maximum number of characters.
1091 * dxs [O] Partial string widths.
1092 * size [O] Returned string size.
1094 * RETURNS
1095 * Success: TRUE
1096 * Failure: FALSE
1098 BOOL WINAPI GetTextExtentExPointI( HDC hdc, const WORD *indices, INT count, INT max_ext,
1099 LPINT nfit, LPINT dxs, LPSIZE size )
1101 BOOL ret = FALSE;
1102 DC * dc = get_dc_ptr( hdc );
1103 if (!dc) return FALSE;
1105 if(dc->gdiFont) {
1106 ret = WineEngGetTextExtentExPointI(dc->gdiFont, indices, count, max_ext, nfit, dxs, size);
1107 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1108 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1109 size->cx += count * dc->charExtra;
1111 else if(dc->funcs->pGetTextExtentExPoint) {
1112 FIXME("calling GetTextExtentExPoint\n");
1113 ret = dc->funcs->pGetTextExtentExPoint( dc->physDev, (LPCWSTR)indices,
1114 count, max_ext, nfit, dxs, size );
1117 release_dc_ptr( dc );
1119 TRACE("(%p %p %d %p): returning %d x %d\n",
1120 hdc, indices, count, size, size->cx, size->cy );
1121 return ret;
1124 /***********************************************************************
1125 * GetTextExtentPointI [GDI32.@]
1127 * Computes width and height of the array of glyph indices.
1129 * PARAMS
1130 * hdc [I] Handle of device context.
1131 * indices [I] Glyph index array.
1132 * count [I] Number of glyphs in array.
1133 * size [O] Returned string size.
1135 * RETURNS
1136 * Success: TRUE
1137 * Failure: FALSE
1139 BOOL WINAPI GetTextExtentPointI( HDC hdc, const WORD *indices, INT count, LPSIZE size )
1141 return GetTextExtentExPointI( hdc, indices, count, 0, NULL, NULL, size );
1145 /***********************************************************************
1146 * GetTextExtentPointA (GDI32.@)
1148 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
1149 LPSIZE size )
1151 TRACE("not bug compatible.\n");
1152 return GetTextExtentPoint32A( hdc, str, count, size );
1155 /***********************************************************************
1156 * GetTextExtentPointW (GDI32.@)
1158 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1159 LPSIZE size )
1161 TRACE("not bug compatible.\n");
1162 return GetTextExtentPoint32W( hdc, str, count, size );
1166 /***********************************************************************
1167 * GetTextExtentExPointA (GDI32.@)
1169 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1170 INT maxExt, LPINT lpnFit,
1171 LPINT alpDx, LPSIZE size )
1173 BOOL ret;
1174 INT wlen;
1175 INT *walpDx = NULL;
1176 LPWSTR p = NULL;
1178 if (alpDx &&
1179 NULL == (walpDx = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT))))
1180 return FALSE;
1182 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1183 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
1184 if (walpDx)
1186 INT n = lpnFit ? *lpnFit : wlen;
1187 INT i, j;
1188 for(i = 0, j = 0; i < n; i++, j++)
1190 alpDx[j] = walpDx[i];
1191 if (IsDBCSLeadByte(str[j])) alpDx[++j] = walpDx[i];
1194 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1195 HeapFree( GetProcessHeap(), 0, p );
1196 HeapFree( GetProcessHeap(), 0, walpDx );
1197 return ret;
1201 /***********************************************************************
1202 * GetTextExtentExPointW (GDI32.@)
1204 * Return the size of the string as it would be if it was output properly by
1205 * e.g. TextOut.
1207 * This should include
1208 * - Intercharacter spacing
1209 * - justification spacing (not yet done)
1210 * - kerning? see below
1212 * Kerning. Since kerning would be carried out by the rendering code it should
1213 * be done by the driver. However they don't support it yet. Also I am not
1214 * yet persuaded that (certainly under Win95) any kerning is actually done.
1216 * str: According to MSDN this should be null-terminated. That is not true; a
1217 * null will not terminate it early.
1218 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1219 * than count. I have seen it be either the size of the full string or
1220 * 1 less than the size of the full string. I have not seen it bear any
1221 * resemblance to the portion that would fit.
1222 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1223 * trailing intercharacter spacing and any trailing justification.
1225 * FIXME
1226 * Currently we do this by measuring each character etc. We should do it by
1227 * passing the request to the driver, perhaps by extending the
1228 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1229 * thinking about kerning issues and rounding issues in the justification.
1232 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1233 INT maxExt, LPINT lpnFit,
1234 LPINT alpDx, LPSIZE size )
1236 INT nFit = 0;
1237 LPINT dxs = NULL;
1238 DC *dc;
1239 BOOL ret = FALSE;
1240 TEXTMETRICW tm;
1242 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1244 dc = get_dc_ptr(hdc);
1245 if (! dc)
1246 return FALSE;
1248 GetTextMetricsW(hdc, &tm);
1250 /* If we need to calculate nFit, then we need the partial extents even if
1251 the user hasn't provided us with an array. */
1252 if (lpnFit)
1254 dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]);
1255 if (! dxs)
1257 release_dc_ptr(dc);
1258 SetLastError(ERROR_OUTOFMEMORY);
1259 return FALSE;
1262 else
1263 dxs = alpDx;
1265 if (dc->gdiFont)
1266 ret = WineEngGetTextExtentExPoint(dc->gdiFont, str, count,
1267 0, NULL, dxs, size);
1268 else if (dc->funcs->pGetTextExtentExPoint)
1269 ret = dc->funcs->pGetTextExtentExPoint(dc->physDev, str, count,
1270 0, NULL, dxs, size);
1272 /* Perform device size to world size transformations. */
1273 if (ret)
1275 INT extra = dc->charExtra,
1276 breakExtra = dc->breakExtra,
1277 breakRem = dc->breakRem,
1280 if (dxs)
1282 for (i = 0; i < count; ++i)
1284 dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
1285 dxs[i] += (i+1) * extra;
1286 if (count > 1 && (breakExtra || breakRem) && str[i] == tm.tmBreakChar)
1288 dxs[i] += breakExtra;
1289 if (breakRem > 0)
1291 breakRem--;
1292 dxs[i]++;
1295 if (dxs[i] <= maxExt)
1296 ++nFit;
1298 breakRem = dc->breakRem;
1300 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1301 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1303 if (!dxs && count > 1 && (breakExtra || breakRem))
1305 for (i = 0; i < count; i++)
1307 if (str[i] == tm.tmBreakChar)
1309 size->cx += breakExtra;
1310 if (breakRem > 0)
1312 breakRem--;
1313 (size->cx)++;
1320 if (lpnFit)
1321 *lpnFit = nFit;
1323 if (! alpDx)
1324 HeapFree(GetProcessHeap(), 0, dxs);
1326 release_dc_ptr( dc );
1328 TRACE("returning %d %d x %d\n",nFit,size->cx,size->cy);
1329 return ret;
1332 /***********************************************************************
1333 * GetTextMetricsA (GDI32.@)
1335 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1337 TEXTMETRICW tm32;
1339 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1340 FONT_TextMetricWToA( &tm32, metrics );
1341 return TRUE;
1344 /***********************************************************************
1345 * GetTextMetricsW (GDI32.@)
1347 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1349 BOOL ret = FALSE;
1350 DC * dc = get_dc_ptr( hdc );
1351 if (!dc) return FALSE;
1353 if (dc->gdiFont)
1354 ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1355 else if (dc->funcs->pGetTextMetrics)
1356 ret = dc->funcs->pGetTextMetrics( dc->physDev, metrics );
1358 if (ret)
1360 /* device layer returns values in device units
1361 * therefore we have to convert them to logical */
1363 metrics->tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1364 metrics->tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1366 #define WDPTOLP(x) ((x<0)? \
1367 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1368 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1369 #define HDPTOLP(y) ((y<0)? \
1370 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1371 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1373 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1374 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1375 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1376 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1377 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1378 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1379 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1380 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1381 ret = TRUE;
1382 #undef WDPTOLP
1383 #undef HDPTOLP
1384 TRACE("text metrics:\n"
1385 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1386 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1387 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1388 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1389 " PitchAndFamily = %02x\n"
1390 " --------------------\n"
1391 " InternalLeading = %i\n"
1392 " Ascent = %i\n"
1393 " Descent = %i\n"
1394 " Height = %i\n",
1395 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1396 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1397 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1398 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1399 metrics->tmPitchAndFamily,
1400 metrics->tmInternalLeading,
1401 metrics->tmAscent,
1402 metrics->tmDescent,
1403 metrics->tmHeight );
1405 release_dc_ptr( dc );
1406 return ret;
1410 /***********************************************************************
1411 * GetOutlineTextMetricsA (GDI32.@)
1412 * Gets metrics for TrueType fonts.
1414 * NOTES
1415 * If the supplied buffer isn't big enough Windows partially fills it up to
1416 * its given length and returns that length.
1418 * RETURNS
1419 * Success: Non-zero or size of required buffer
1420 * Failure: 0
1422 UINT WINAPI GetOutlineTextMetricsA(
1423 HDC hdc, /* [in] Handle of device context */
1424 UINT cbData, /* [in] Size of metric data array */
1425 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1427 char buf[512], *ptr;
1428 UINT ret, needed;
1429 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1430 OUTLINETEXTMETRICA *output = lpOTM;
1431 INT left, len;
1433 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1434 return 0;
1435 if(ret > sizeof(buf))
1436 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1437 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1439 needed = sizeof(OUTLINETEXTMETRICA);
1440 if(lpOTMW->otmpFamilyName)
1441 needed += WideCharToMultiByte(CP_ACP, 0,
1442 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1443 NULL, 0, NULL, NULL);
1444 if(lpOTMW->otmpFaceName)
1445 needed += WideCharToMultiByte(CP_ACP, 0,
1446 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1447 NULL, 0, NULL, NULL);
1448 if(lpOTMW->otmpStyleName)
1449 needed += WideCharToMultiByte(CP_ACP, 0,
1450 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1451 NULL, 0, NULL, NULL);
1452 if(lpOTMW->otmpFullName)
1453 needed += WideCharToMultiByte(CP_ACP, 0,
1454 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1455 NULL, 0, NULL, NULL);
1457 if(!lpOTM) {
1458 ret = needed;
1459 goto end;
1462 TRACE("needed = %d\n", needed);
1463 if(needed > cbData)
1464 /* Since the supplied buffer isn't big enough, we'll alloc one
1465 that is and memcpy the first cbData bytes into the lpOTM at
1466 the end. */
1467 output = HeapAlloc(GetProcessHeap(), 0, needed);
1469 ret = output->otmSize = min(needed, cbData);
1470 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1471 output->otmFiller = 0;
1472 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1473 output->otmfsSelection = lpOTMW->otmfsSelection;
1474 output->otmfsType = lpOTMW->otmfsType;
1475 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1476 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1477 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1478 output->otmEMSquare = lpOTMW->otmEMSquare;
1479 output->otmAscent = lpOTMW->otmAscent;
1480 output->otmDescent = lpOTMW->otmDescent;
1481 output->otmLineGap = lpOTMW->otmLineGap;
1482 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1483 output->otmsXHeight = lpOTMW->otmsXHeight;
1484 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1485 output->otmMacAscent = lpOTMW->otmMacAscent;
1486 output->otmMacDescent = lpOTMW->otmMacDescent;
1487 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1488 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1489 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1490 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1491 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1492 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1493 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1494 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1495 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1496 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1499 ptr = (char*)(output + 1);
1500 left = needed - sizeof(*output);
1502 if(lpOTMW->otmpFamilyName) {
1503 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1504 len = WideCharToMultiByte(CP_ACP, 0,
1505 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1506 ptr, left, NULL, NULL);
1507 left -= len;
1508 ptr += len;
1509 } else
1510 output->otmpFamilyName = 0;
1512 if(lpOTMW->otmpFaceName) {
1513 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1514 len = WideCharToMultiByte(CP_ACP, 0,
1515 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1516 ptr, left, NULL, NULL);
1517 left -= len;
1518 ptr += len;
1519 } else
1520 output->otmpFaceName = 0;
1522 if(lpOTMW->otmpStyleName) {
1523 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1524 len = WideCharToMultiByte(CP_ACP, 0,
1525 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1526 ptr, left, NULL, NULL);
1527 left -= len;
1528 ptr += len;
1529 } else
1530 output->otmpStyleName = 0;
1532 if(lpOTMW->otmpFullName) {
1533 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1534 len = WideCharToMultiByte(CP_ACP, 0,
1535 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1536 ptr, left, NULL, NULL);
1537 left -= len;
1538 } else
1539 output->otmpFullName = 0;
1541 assert(left == 0);
1543 if(output != lpOTM) {
1544 memcpy(lpOTM, output, cbData);
1545 HeapFree(GetProcessHeap(), 0, output);
1547 /* check if the string offsets really fit into the provided size */
1548 /* FIXME: should we check string length as well? */
1549 /* make sure that we don't read/write beyond the provided buffer */
1550 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(LPSTR))
1552 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1553 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1556 /* make sure that we don't read/write beyond the provided buffer */
1557 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(LPSTR))
1559 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1560 lpOTM->otmpFaceName = 0; /* doesn't fit */
1563 /* make sure that we don't read/write beyond the provided buffer */
1564 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(LPSTR))
1566 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1567 lpOTM->otmpStyleName = 0; /* doesn't fit */
1570 /* make sure that we don't read/write beyond the provided buffer */
1571 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(LPSTR))
1573 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1574 lpOTM->otmpFullName = 0; /* doesn't fit */
1578 end:
1579 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1580 HeapFree(GetProcessHeap(), 0, lpOTMW);
1582 return ret;
1586 /***********************************************************************
1587 * GetOutlineTextMetricsW [GDI32.@]
1589 UINT WINAPI GetOutlineTextMetricsW(
1590 HDC hdc, /* [in] Handle of device context */
1591 UINT cbData, /* [in] Size of metric data array */
1592 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1594 DC *dc = get_dc_ptr( hdc );
1595 OUTLINETEXTMETRICW *output = lpOTM;
1596 UINT ret;
1598 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1599 if(!dc) return 0;
1601 if(dc->gdiFont) {
1602 ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, output);
1603 if(lpOTM && ret) {
1604 if(ret > cbData) {
1605 output = HeapAlloc(GetProcessHeap(), 0, ret);
1606 WineEngGetOutlineTextMetrics(dc->gdiFont, ret, output);
1609 #define WDPTOLP(x) ((x<0)? \
1610 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1611 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1612 #define HDPTOLP(y) ((y<0)? \
1613 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1614 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1616 output->otmTextMetrics.tmHeight = HDPTOLP(output->otmTextMetrics.tmHeight);
1617 output->otmTextMetrics.tmAscent = HDPTOLP(output->otmTextMetrics.tmAscent);
1618 output->otmTextMetrics.tmDescent = HDPTOLP(output->otmTextMetrics.tmDescent);
1619 output->otmTextMetrics.tmInternalLeading = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1620 output->otmTextMetrics.tmExternalLeading = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1621 output->otmTextMetrics.tmAveCharWidth = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1622 output->otmTextMetrics.tmMaxCharWidth = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1623 output->otmTextMetrics.tmOverhang = WDPTOLP(output->otmTextMetrics.tmOverhang);
1624 output->otmAscent = HDPTOLP(output->otmAscent);
1625 output->otmDescent = HDPTOLP(output->otmDescent);
1626 output->otmLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmLineGap));
1627 output->otmsCapEmHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsCapEmHeight));
1628 output->otmsXHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsXHeight));
1629 output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1630 output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1631 output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1632 output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1633 output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1634 output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1635 output->otmMacLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmMacLineGap));
1636 output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1637 output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1638 output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1639 output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1640 output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1641 output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1642 output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1643 output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1644 output->otmsStrikeoutSize = abs(INTERNAL_YDSTOWS(dc,output->otmsStrikeoutSize));
1645 output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1646 output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1647 output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1648 #undef WDPTOLP
1649 #undef HDPTOLP
1650 if(output != lpOTM) {
1651 memcpy(lpOTM, output, cbData);
1652 HeapFree(GetProcessHeap(), 0, output);
1653 ret = cbData;
1658 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1659 but really this should just be a return 0. */
1661 ret = sizeof(*lpOTM);
1662 if (lpOTM) {
1663 if(cbData < ret)
1664 ret = 0;
1665 else {
1666 memset(lpOTM, 0, ret);
1667 lpOTM->otmSize = sizeof(*lpOTM);
1668 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1670 Further fill of the structure not implemented,
1671 Needs real values for the structure members
1676 release_dc_ptr(dc);
1677 return ret;
1681 /***********************************************************************
1682 * GetCharWidthW (GDI32.@)
1683 * GetCharWidth32W (GDI32.@)
1685 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1686 LPINT buffer )
1688 UINT i;
1689 BOOL ret = FALSE;
1690 DC * dc = get_dc_ptr( hdc );
1691 if (!dc) return FALSE;
1693 if (dc->gdiFont)
1694 ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1695 else if (dc->funcs->pGetCharWidth)
1696 ret = dc->funcs->pGetCharWidth( dc->physDev, firstChar, lastChar, buffer);
1698 if (ret)
1700 /* convert device units to logical */
1701 for( i = firstChar; i <= lastChar; i++, buffer++ )
1702 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1703 ret = TRUE;
1705 release_dc_ptr( dc );
1706 return ret;
1710 /***********************************************************************
1711 * GetCharWidthA (GDI32.@)
1712 * GetCharWidth32A (GDI32.@)
1714 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1715 LPINT buffer )
1717 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1718 LPSTR str;
1719 LPWSTR wstr;
1720 BOOL ret = TRUE;
1722 if(count <= 0) return FALSE;
1724 str = HeapAlloc(GetProcessHeap(), 0, count);
1725 for(i = 0; i < count; i++)
1726 str[i] = (BYTE)(firstChar + i);
1728 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1730 for(i = 0; i < wlen; i++)
1732 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1734 ret = FALSE;
1735 break;
1737 buffer++;
1740 HeapFree(GetProcessHeap(), 0, str);
1741 HeapFree(GetProcessHeap(), 0, wstr);
1743 return ret;
1747 /***********************************************************************
1748 * ExtTextOutA (GDI32.@)
1750 * See ExtTextOutW.
1752 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1753 const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1755 INT wlen;
1756 UINT codepage;
1757 LPWSTR p;
1758 BOOL ret;
1759 LPINT lpDxW = NULL;
1761 if (flags & ETO_GLYPH_INDEX)
1762 return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
1764 p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
1766 if (lpDx) {
1767 unsigned int i = 0, j = 0;
1769 lpDxW = HeapAlloc( GetProcessHeap(), 0, wlen*sizeof(INT));
1770 while(i < count) {
1771 if(IsDBCSLeadByteEx(codepage, str[i])) {
1772 lpDxW[j++] = lpDx[i] + lpDx[i+1];
1773 i = i + 2;
1774 } else {
1775 lpDxW[j++] = lpDx[i];
1776 i = i + 1;
1781 ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1783 HeapFree( GetProcessHeap(), 0, p );
1784 HeapFree( GetProcessHeap(), 0, lpDxW );
1785 return ret;
1789 /***********************************************************************
1790 * ExtTextOutW (GDI32.@)
1792 * Draws text using the currently selected font, background color, and text color.
1795 * PARAMS
1796 * x,y [I] coordinates of string
1797 * flags [I]
1798 * ETO_GRAYED - undocumented on MSDN
1799 * ETO_OPAQUE - use background color for fill the rectangle
1800 * ETO_CLIPPED - clipping text to the rectangle
1801 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1802 * than encoded characters. Implies ETO_IGNORELANGUAGE
1803 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1804 * Affects BiDi ordering
1805 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1806 * ETO_PDY - unimplemented
1807 * ETO_NUMERICSLATIN - unimplemented always assumed -
1808 * do not translate numbers into locale representations
1809 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1810 * lprect [I] dimensions for clipping or/and opaquing
1811 * str [I] text string
1812 * count [I] number of symbols in string
1813 * lpDx [I] optional parameter with distance between drawing characters
1815 * RETURNS
1816 * Success: TRUE
1817 * Failure: FALSE
1819 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1820 const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1822 BOOL ret = FALSE;
1823 LPWSTR reordered_str = (LPWSTR)str;
1824 WORD *glyphs = NULL;
1825 UINT align = GetTextAlign( hdc );
1826 POINT pt;
1827 TEXTMETRICW tm;
1828 LOGFONTW lf;
1829 double cosEsc, sinEsc;
1830 INT *deltas = NULL, char_extra;
1831 SIZE sz;
1832 RECT rc;
1833 BOOL done_extents = FALSE;
1834 INT width = 0, xwidth = 0, ywidth = 0;
1835 DWORD type;
1836 DC * dc = get_dc_ptr( hdc );
1837 INT breakRem;
1839 if (!dc) return FALSE;
1841 breakRem = dc->breakRem;
1843 if (flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY))
1844 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY unimplemented\n");
1846 if (!dc->funcs->pExtTextOut && !PATH_IsPathOpen(dc->path))
1848 release_dc_ptr( dc );
1849 return ret;
1852 update_dc( dc );
1853 type = GetObjectType(hdc);
1854 if(type == OBJ_METADC || type == OBJ_ENHMETADC)
1856 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, flags, lprect, str, count, lpDx);
1857 release_dc_ptr( dc );
1858 return ret;
1861 if (!lprect)
1862 flags &= ~ETO_CLIPPED;
1864 if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && count > 0 )
1866 reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1868 BIDI_Reorder( str, count, GCP_REORDER,
1869 ((flags&ETO_RTLREADING)!=0 || (GetTextAlign(hdc)&TA_RTLREADING)!=0)?
1870 WINE_GCPW_FORCE_RTL:WINE_GCPW_FORCE_LTR,
1871 reordered_str, count, NULL );
1873 flags |= ETO_IGNORELANGUAGE;
1876 TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc, x, y, flags,
1877 lprect, debugstr_wn(str, count), count, lpDx);
1879 if(flags & ETO_GLYPH_INDEX)
1880 glyphs = reordered_str;
1882 if(lprect)
1883 TRACE("rect: %d,%d - %d,%d\n", lprect->left, lprect->top, lprect->right,
1884 lprect->bottom);
1885 TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
1887 if(align & TA_UPDATECP)
1889 GetCurrentPositionEx( hdc, &pt );
1890 x = pt.x;
1891 y = pt.y;
1894 GetTextMetricsW(hdc, &tm);
1895 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1897 if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
1898 lf.lfEscapement = 0;
1900 if(lf.lfEscapement != 0)
1902 cosEsc = cos(lf.lfEscapement * M_PI / 1800);
1903 sinEsc = sin(lf.lfEscapement * M_PI / 1800);
1905 else
1907 cosEsc = 1;
1908 sinEsc = 0;
1911 if(flags & (ETO_CLIPPED | ETO_OPAQUE))
1913 if(!lprect)
1915 if(flags & ETO_GLYPH_INDEX)
1916 GetTextExtentPointI(hdc, glyphs, count, &sz);
1917 else
1918 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1920 done_extents = TRUE;
1921 rc.left = x;
1922 rc.top = y;
1923 rc.right = x + sz.cx;
1924 rc.bottom = y + sz.cy;
1926 else
1928 rc = *lprect;
1931 LPtoDP(hdc, (POINT*)&rc, 2);
1933 if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
1934 if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
1937 if ((flags & ETO_OPAQUE) && !PATH_IsPathOpen(dc->path))
1938 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1940 if(count == 0)
1942 ret = TRUE;
1943 goto done;
1946 pt.x = x;
1947 pt.y = y;
1948 LPtoDP(hdc, &pt, 1);
1949 x = pt.x;
1950 y = pt.y;
1952 char_extra = GetTextCharacterExtra(hdc);
1953 if(char_extra || dc->breakExtra || breakRem || lpDx || lf.lfEscapement != 0)
1955 UINT i;
1956 SIZE tmpsz;
1957 deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT));
1958 for(i = 0; i < count; i++)
1960 if(lpDx && (flags & ETO_PDY))
1961 deltas[i] = lpDx[i*2] + char_extra;
1962 else if(lpDx)
1963 deltas[i] = lpDx[i] + char_extra;
1964 else
1966 if(flags & ETO_GLYPH_INDEX)
1967 GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
1968 else
1969 GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
1971 deltas[i] = tmpsz.cx;
1974 if (!(flags & ETO_GLYPH_INDEX) && (dc->breakExtra || breakRem) && reordered_str[i] == tm.tmBreakChar)
1976 deltas[i] = deltas[i] + dc->breakExtra;
1977 if (breakRem > 0)
1979 breakRem--;
1980 deltas[i]++;
1983 deltas[i] = INTERNAL_XWSTODS(dc, deltas[i]);
1984 width += deltas[i];
1987 else
1989 if(!done_extents)
1991 if(flags & ETO_GLYPH_INDEX)
1992 GetTextExtentPointI(hdc, glyphs, count, &sz);
1993 else
1994 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1995 done_extents = TRUE;
1997 width = INTERNAL_XWSTODS(dc, sz.cx);
1999 xwidth = width * cosEsc;
2000 ywidth = width * sinEsc;
2002 tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
2003 tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
2004 switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
2006 case TA_LEFT:
2007 if (align & TA_UPDATECP)
2009 pt.x = x + xwidth;
2010 pt.y = y - ywidth;
2011 DPtoLP(hdc, &pt, 1);
2012 MoveToEx(hdc, pt.x, pt.y, NULL);
2014 break;
2016 case TA_CENTER:
2017 x -= xwidth / 2;
2018 y += ywidth / 2;
2019 break;
2021 case TA_RIGHT:
2022 x -= xwidth;
2023 y += ywidth;
2024 if (align & TA_UPDATECP)
2026 pt.x = x;
2027 pt.y = y;
2028 DPtoLP(hdc, &pt, 1);
2029 MoveToEx(hdc, pt.x, pt.y, NULL);
2031 break;
2034 switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
2036 case TA_TOP:
2037 y += tm.tmAscent * cosEsc;
2038 x += tm.tmAscent * sinEsc;
2039 break;
2041 case TA_BOTTOM:
2042 y -= tm.tmDescent * cosEsc;
2043 x -= tm.tmDescent * sinEsc;
2044 break;
2046 case TA_BASELINE:
2047 break;
2050 if (GetBkMode(hdc) != TRANSPARENT && !PATH_IsPathOpen(dc->path))
2052 if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
2054 if(!(flags & ETO_OPAQUE) || x < rc.left || x + width >= rc.right ||
2055 y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
2057 RECT rc;
2058 rc.left = x;
2059 rc.right = x + width;
2060 rc.top = y - tm.tmAscent;
2061 rc.bottom = y + tm.tmDescent;
2062 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
2067 if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
2069 HFONT orig_font = dc->hFont, cur_font;
2070 UINT glyph;
2071 INT span = 0, *offsets = NULL;
2072 unsigned int i;
2074 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2075 for(i = 0; i < count; i++)
2077 WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
2078 if(cur_font != dc->hFont)
2080 if(!offsets)
2082 unsigned int j;
2083 offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
2084 offsets[0] = 0;
2085 if(!deltas)
2087 SIZE tmpsz;
2088 for(j = 1; j < count; j++)
2090 GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
2091 offsets[j] = offsets[j-1] + INTERNAL_XWSTODS(dc, tmpsz.cx);
2094 else
2096 for(j = 1; j < count; j++)
2097 offsets[j] = offsets[j-1] + deltas[j];
2100 if(span)
2102 if (PATH_IsPathOpen(dc->path))
2103 ret = PATH_ExtTextOut(dc, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
2104 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2105 glyphs, span, deltas ? deltas + i - span : NULL);
2106 else
2107 dc->funcs->pExtTextOut(dc->physDev, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
2108 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2109 glyphs, span, deltas ? deltas + i - span : NULL);
2110 span = 0;
2112 SelectObject(hdc, cur_font);
2114 glyphs[span++] = glyph;
2116 if(i == count - 1)
2118 if (PATH_IsPathOpen(dc->path))
2119 ret = PATH_ExtTextOut(dc, x + (offsets ? offsets[count - span] * cosEsc : 0),
2120 y - (offsets ? offsets[count - span] * sinEsc : 0),
2121 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2122 glyphs, span, deltas ? deltas + count - span : NULL);
2123 else
2124 ret = dc->funcs->pExtTextOut(dc->physDev, x + (offsets ? offsets[count - span] * cosEsc : 0),
2125 y - (offsets ? offsets[count - span] * sinEsc : 0),
2126 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2127 glyphs, span, deltas ? deltas + count - span : NULL);
2128 SelectObject(hdc, orig_font);
2129 HeapFree(GetProcessHeap(), 0, offsets);
2133 else
2135 if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
2137 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2138 GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
2139 flags |= ETO_GLYPH_INDEX;
2142 if (PATH_IsPathOpen(dc->path))
2143 ret = PATH_ExtTextOut(dc, x, y, (flags & ~ETO_OPAQUE), &rc,
2144 glyphs ? glyphs : reordered_str, count, deltas);
2145 else
2146 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, (flags & ~ETO_OPAQUE), &rc,
2147 glyphs ? glyphs : reordered_str, count, deltas);
2150 done:
2151 HeapFree(GetProcessHeap(), 0, deltas);
2152 if(glyphs != reordered_str)
2153 HeapFree(GetProcessHeap(), 0, glyphs);
2154 if(reordered_str != str)
2155 HeapFree(GetProcessHeap(), 0, reordered_str);
2157 release_dc_ptr( dc );
2159 if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2161 int underlinePos, strikeoutPos;
2162 int underlineWidth, strikeoutWidth;
2163 UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2164 OUTLINETEXTMETRICW* otm = NULL;
2166 if(!size)
2168 underlinePos = 0;
2169 underlineWidth = tm.tmAscent / 20 + 1;
2170 strikeoutPos = tm.tmAscent / 2;
2171 strikeoutWidth = underlineWidth;
2173 else
2175 otm = HeapAlloc(GetProcessHeap(), 0, size);
2176 GetOutlineTextMetricsW(hdc, size, otm);
2177 underlinePos = otm->otmsUnderscorePosition;
2178 underlineWidth = otm->otmsUnderscoreSize;
2179 strikeoutPos = otm->otmsStrikeoutPosition;
2180 strikeoutWidth = otm->otmsStrikeoutSize;
2181 HeapFree(GetProcessHeap(), 0, otm);
2184 if (PATH_IsPathOpen(dc->path))
2186 POINT pts[5];
2187 HPEN hpen;
2188 HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2190 hbrush = SelectObject(hdc, hbrush);
2191 hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2193 if (lf.lfUnderline)
2195 pts[0].x = x - underlinePos * sinEsc;
2196 pts[0].y = y - underlinePos * cosEsc;
2197 pts[1].x = x + xwidth - underlinePos * sinEsc;
2198 pts[1].y = y - ywidth - underlinePos * cosEsc;
2199 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2200 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2201 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2202 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2203 pts[4].x = pts[0].x;
2204 pts[4].y = pts[0].y;
2205 DPtoLP(hdc, pts, 5);
2206 Polygon(hdc, pts, 5);
2209 if (lf.lfStrikeOut)
2211 pts[0].x = x - strikeoutPos * sinEsc;
2212 pts[0].y = y - strikeoutPos * cosEsc;
2213 pts[1].x = x + xwidth - strikeoutPos * sinEsc;
2214 pts[1].y = y - ywidth - strikeoutPos * cosEsc;
2215 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2216 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2217 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2218 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2219 pts[4].x = pts[0].x;
2220 pts[4].y = pts[0].y;
2221 DPtoLP(hdc, pts, 5);
2222 Polygon(hdc, pts, 5);
2225 SelectObject(hdc, hpen);
2226 hbrush = SelectObject(hdc, hbrush);
2227 DeleteObject(hbrush);
2229 else
2231 POINT pts[2], oldpt;
2232 HPEN hpen;
2234 if (lf.lfUnderline)
2236 hpen = CreatePen(PS_SOLID, underlineWidth, GetTextColor(hdc));
2237 hpen = SelectObject(hdc, hpen);
2238 pts[0].x = x;
2239 pts[0].y = y;
2240 pts[1].x = x + xwidth;
2241 pts[1].y = y - ywidth;
2242 DPtoLP(hdc, pts, 2);
2243 MoveToEx(hdc, pts[0].x - underlinePos * sinEsc, pts[0].y - underlinePos * cosEsc, &oldpt);
2244 LineTo(hdc, pts[1].x - underlinePos * sinEsc, pts[1].y - underlinePos * cosEsc);
2245 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2246 DeleteObject(SelectObject(hdc, hpen));
2249 if (lf.lfStrikeOut)
2251 hpen = CreatePen(PS_SOLID, strikeoutWidth, GetTextColor(hdc));
2252 hpen = SelectObject(hdc, hpen);
2253 pts[0].x = x;
2254 pts[0].y = y;
2255 pts[1].x = x + xwidth;
2256 pts[1].y = y - ywidth;
2257 DPtoLP(hdc, pts, 2);
2258 MoveToEx(hdc, pts[0].x - strikeoutPos * sinEsc, pts[0].y - strikeoutPos * cosEsc, &oldpt);
2259 LineTo(hdc, pts[1].x - strikeoutPos * sinEsc, pts[1].y - strikeoutPos * cosEsc);
2260 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2261 DeleteObject(SelectObject(hdc, hpen));
2266 return ret;
2270 /***********************************************************************
2271 * TextOutA (GDI32.@)
2273 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2275 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2279 /***********************************************************************
2280 * TextOutW (GDI32.@)
2282 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2284 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2288 /***********************************************************************
2289 * PolyTextOutA (GDI32.@)
2291 * See PolyTextOutW.
2293 BOOL WINAPI PolyTextOutA( HDC hdc, const POLYTEXTA *pptxt, INT cStrings )
2295 for (; cStrings>0; cStrings--, pptxt++)
2296 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2297 return FALSE;
2298 return TRUE;
2303 /***********************************************************************
2304 * PolyTextOutW (GDI32.@)
2306 * Draw several Strings
2308 * RETURNS
2309 * TRUE: Success.
2310 * FALSE: Failure.
2312 BOOL WINAPI PolyTextOutW( HDC hdc, const POLYTEXTW *pptxt, INT cStrings )
2314 for (; cStrings>0; cStrings--, pptxt++)
2315 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2316 return FALSE;
2317 return TRUE;
2321 /* FIXME: all following APIs ******************************************/
2324 /***********************************************************************
2325 * SetMapperFlags (GDI32.@)
2327 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
2329 DC *dc = get_dc_ptr( hDC );
2330 DWORD ret = 0;
2331 if(!dc) return 0;
2332 if(dc->funcs->pSetMapperFlags)
2334 ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
2335 /* FIXME: ret is just a success flag, we should return a proper value */
2337 else
2338 FIXME("(%p, 0x%08x): stub - harmless\n", hDC, dwFlag);
2339 release_dc_ptr( dc );
2340 return ret;
2343 /***********************************************************************
2344 * GetAspectRatioFilterEx (GDI32.@)
2346 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2348 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2349 return FALSE;
2353 /***********************************************************************
2354 * GetCharABCWidthsA (GDI32.@)
2356 * See GetCharABCWidthsW.
2358 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2359 LPABC abc )
2361 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
2362 LPSTR str;
2363 LPWSTR wstr;
2364 BOOL ret = TRUE;
2366 if(count <= 0) return FALSE;
2368 str = HeapAlloc(GetProcessHeap(), 0, count);
2369 for(i = 0; i < count; i++)
2370 str[i] = (BYTE)(firstChar + i);
2372 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
2374 for(i = 0; i < wlen; i++)
2376 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2378 ret = FALSE;
2379 break;
2381 abc++;
2384 HeapFree(GetProcessHeap(), 0, str);
2385 HeapFree(GetProcessHeap(), 0, wstr);
2387 return ret;
2391 /******************************************************************************
2392 * GetCharABCWidthsW [GDI32.@]
2394 * Retrieves widths of characters in range.
2396 * PARAMS
2397 * hdc [I] Handle of device context
2398 * firstChar [I] First character in range to query
2399 * lastChar [I] Last character in range to query
2400 * abc [O] Address of character-width structure
2402 * NOTES
2403 * Only works with TrueType fonts
2405 * RETURNS
2406 * Success: TRUE
2407 * Failure: FALSE
2409 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2410 LPABC abc )
2412 DC *dc = get_dc_ptr(hdc);
2413 unsigned int i;
2414 BOOL ret = FALSE;
2416 if (!dc) return FALSE;
2418 if (!abc)
2420 release_dc_ptr( dc );
2421 return FALSE;
2424 if(dc->gdiFont)
2425 ret = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
2426 else
2427 FIXME(": stub\n");
2429 if (ret)
2431 /* convert device units to logical */
2432 for( i = firstChar; i <= lastChar; i++, abc++ ) {
2433 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2434 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2435 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2437 ret = TRUE;
2440 release_dc_ptr( dc );
2441 return ret;
2445 /******************************************************************************
2446 * GetCharABCWidthsI [GDI32.@]
2448 * Retrieves widths of characters in range.
2450 * PARAMS
2451 * hdc [I] Handle of device context
2452 * firstChar [I] First glyphs in range to query
2453 * count [I] Last glyphs in range to query
2454 * pgi [i] Array of glyphs to query
2455 * abc [O] Address of character-width structure
2457 * NOTES
2458 * Only works with TrueType fonts
2460 * RETURNS
2461 * Success: TRUE
2462 * Failure: FALSE
2464 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2465 LPWORD pgi, LPABC abc)
2467 DC *dc = get_dc_ptr(hdc);
2468 unsigned int i;
2469 BOOL ret = FALSE;
2471 if (!dc) return FALSE;
2473 if (!abc)
2475 release_dc_ptr( dc );
2476 return FALSE;
2479 if(dc->gdiFont)
2480 ret = WineEngGetCharABCWidthsI( dc->gdiFont, firstChar, count, pgi, abc );
2481 else
2482 FIXME(": stub\n");
2484 if (ret)
2486 /* convert device units to logical */
2487 for( i = 0; i < count; i++, abc++ ) {
2488 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2489 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2490 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2492 ret = TRUE;
2495 release_dc_ptr( dc );
2496 return ret;
2500 /***********************************************************************
2501 * GetGlyphOutlineA (GDI32.@)
2503 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2504 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2505 LPVOID lpBuffer, const MAT2 *lpmat2 )
2507 LPWSTR p = NULL;
2508 DWORD ret;
2509 UINT c;
2511 if(!(fuFormat & GGO_GLYPH_INDEX)) {
2512 int len;
2513 char mbchs[2];
2514 if(uChar > 0xff) { /* but, 2 bytes character only */
2515 len = 2;
2516 mbchs[0] = (uChar & 0xff00) >> 8;
2517 mbchs[1] = (uChar & 0xff);
2518 } else {
2519 len = 1;
2520 mbchs[0] = (uChar & 0xff);
2522 p = FONT_mbtowc(hdc, mbchs, len, NULL, NULL);
2523 c = p[0];
2524 } else
2525 c = uChar;
2526 ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
2527 lpmat2);
2528 HeapFree(GetProcessHeap(), 0, p);
2529 return ret;
2532 /***********************************************************************
2533 * GetGlyphOutlineW (GDI32.@)
2535 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2536 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2537 LPVOID lpBuffer, const MAT2 *lpmat2 )
2539 DC *dc = get_dc_ptr(hdc);
2540 DWORD ret;
2542 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2543 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2545 if(!dc) return GDI_ERROR;
2547 if(dc->gdiFont)
2548 ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
2549 cbBuffer, lpBuffer, lpmat2);
2550 else
2551 ret = GDI_ERROR;
2553 release_dc_ptr( dc );
2554 return ret;
2558 /***********************************************************************
2559 * CreateScalableFontResourceA (GDI32.@)
2561 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2562 LPCSTR lpszResourceFile,
2563 LPCSTR lpszFontFile,
2564 LPCSTR lpszCurrentPath )
2566 HANDLE f;
2568 /* fHidden=1 - only visible for the calling app, read-only, not
2569 * enumbered with EnumFonts/EnumFontFamilies
2570 * lpszCurrentPath can be NULL
2572 FIXME("(%d,%s,%s,%s): stub\n",
2573 fHidden, debugstr_a(lpszResourceFile), debugstr_a(lpszFontFile),
2574 debugstr_a(lpszCurrentPath) );
2576 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2577 if ((f = CreateFileA(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2578 CloseHandle(f);
2579 SetLastError(ERROR_FILE_EXISTS);
2580 return FALSE;
2582 return FALSE; /* create failed */
2585 /***********************************************************************
2586 * CreateScalableFontResourceW (GDI32.@)
2588 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2589 LPCWSTR lpszResourceFile,
2590 LPCWSTR lpszFontFile,
2591 LPCWSTR lpszCurrentPath )
2593 FIXME("(%d,%p,%p,%p): stub\n",
2594 fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
2595 return FALSE; /* create failed */
2598 /*************************************************************************
2599 * GetKerningPairsA (GDI32.@)
2601 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2602 LPKERNINGPAIR kern_pairA )
2604 INT charset;
2605 CHARSETINFO csi;
2606 CPINFO cpi;
2607 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2608 KERNINGPAIR *kern_pairW;
2610 if (!cPairs && kern_pairA)
2612 SetLastError(ERROR_INVALID_PARAMETER);
2613 return 0;
2616 charset = GetTextCharset(hDC);
2617 if (!TranslateCharsetInfo(ULongToPtr(charset), &csi, TCI_SRCCHARSET))
2619 FIXME("Can't find codepage for charset %d\n", charset);
2620 return 0;
2622 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2623 * to fail on an invalid character for CP_SYMBOL.
2625 cpi.DefaultChar[0] = 0;
2626 if (csi.ciACP != CP_SYMBOL && !GetCPInfo(csi.ciACP, &cpi))
2628 FIXME("Can't find codepage %u info\n", csi.ciACP);
2629 return 0;
2631 TRACE("charset %d => codepage %u\n", charset, csi.ciACP);
2633 total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2634 if (!total_kern_pairs) return 0;
2636 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2637 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2639 for (i = 0; i < total_kern_pairs; i++)
2641 char first, second;
2643 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2644 continue;
2646 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2647 continue;
2649 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2650 continue;
2652 if (kern_pairA)
2654 if (kern_pairs_copied >= cPairs) break;
2656 kern_pairA->wFirst = (BYTE)first;
2657 kern_pairA->wSecond = (BYTE)second;
2658 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2659 kern_pairA++;
2661 kern_pairs_copied++;
2664 HeapFree(GetProcessHeap(), 0, kern_pairW);
2666 return kern_pairs_copied;
2669 /*************************************************************************
2670 * GetKerningPairsW (GDI32.@)
2672 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2673 LPKERNINGPAIR lpKerningPairs )
2675 DC *dc;
2676 DWORD ret = 0;
2678 TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2680 if (!cPairs && lpKerningPairs)
2682 SetLastError(ERROR_INVALID_PARAMETER);
2683 return 0;
2686 dc = get_dc_ptr(hDC);
2687 if (!dc) return 0;
2689 if (dc->gdiFont)
2690 ret = WineEngGetKerningPairs(dc->gdiFont, cPairs, lpKerningPairs);
2692 release_dc_ptr( dc );
2693 return ret;
2696 /*************************************************************************
2697 * TranslateCharsetInfo [GDI32.@]
2699 * Fills a CHARSETINFO structure for a character set, code page, or
2700 * font. This allows making the correspondence between different labels
2701 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2702 * of the same encoding.
2704 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2705 * only one codepage should be set in *lpSrc.
2707 * RETURNS
2708 * TRUE on success, FALSE on failure.
2711 BOOL WINAPI TranslateCharsetInfo(
2712 LPDWORD lpSrc, /* [in]
2713 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2714 if flags == TCI_SRCCHARSET: a character set value
2715 if flags == TCI_SRCCODEPAGE: a code page value
2717 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2718 DWORD flags /* [in] determines interpretation of lpSrc */)
2720 int index = 0;
2721 switch (flags) {
2722 case TCI_SRCFONTSIG:
2723 while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
2724 break;
2725 case TCI_SRCCODEPAGE:
2726 while (PtrToUlong(lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
2727 break;
2728 case TCI_SRCCHARSET:
2729 while (PtrToUlong(lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
2730 break;
2731 default:
2732 return FALSE;
2734 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2735 memcpy(lpCs, &FONT_tci[index], sizeof(CHARSETINFO));
2736 return TRUE;
2739 /*************************************************************************
2740 * GetFontLanguageInfo (GDI32.@)
2742 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2744 FONTSIGNATURE fontsig;
2745 static const DWORD GCP_DBCS_MASK=0x003F0000,
2746 GCP_DIACRITIC_MASK=0x00000000,
2747 FLI_GLYPHS_MASK=0x00000000,
2748 GCP_GLYPHSHAPE_MASK=0x00000040,
2749 GCP_KASHIDA_MASK=0x00000000,
2750 GCP_LIGATE_MASK=0x00000000,
2751 GCP_USEKERNING_MASK=0x00000000,
2752 GCP_REORDER_MASK=0x00000060;
2754 DWORD result=0;
2756 GetTextCharsetInfo( hdc, &fontsig, 0 );
2757 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2759 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2760 result|=GCP_DBCS;
2762 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2763 result|=GCP_DIACRITIC;
2765 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2766 result|=FLI_GLYPHS;
2768 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2769 result|=GCP_GLYPHSHAPE;
2771 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2772 result|=GCP_KASHIDA;
2774 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2775 result|=GCP_LIGATE;
2777 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2778 result|=GCP_USEKERNING;
2780 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2781 if( GetTextAlign( hdc) & TA_RTLREADING )
2782 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2783 result|=GCP_REORDER;
2785 return result;
2789 /*************************************************************************
2790 * GetFontData [GDI32.@]
2792 * Retrieve data for TrueType font.
2794 * RETURNS
2796 * success: Number of bytes returned
2797 * failure: GDI_ERROR
2799 * NOTES
2801 * Calls SetLastError()
2804 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2805 LPVOID buffer, DWORD length)
2807 DC *dc = get_dc_ptr(hdc);
2808 DWORD ret = GDI_ERROR;
2810 if(!dc) return GDI_ERROR;
2812 if(dc->gdiFont)
2813 ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2815 release_dc_ptr( dc );
2816 return ret;
2819 /*************************************************************************
2820 * GetGlyphIndicesA [GDI32.@]
2822 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2823 LPWORD pgi, DWORD flags)
2825 DWORD ret;
2826 WCHAR *lpstrW;
2827 INT countW;
2829 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2830 hdc, debugstr_an(lpstr, count), count, pgi, flags);
2832 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2833 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2834 HeapFree(GetProcessHeap(), 0, lpstrW);
2836 return ret;
2839 /*************************************************************************
2840 * GetGlyphIndicesW [GDI32.@]
2842 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2843 LPWORD pgi, DWORD flags)
2845 DC *dc = get_dc_ptr(hdc);
2846 DWORD ret = GDI_ERROR;
2848 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2849 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2851 if(!dc) return GDI_ERROR;
2853 if(dc->gdiFont)
2854 ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2856 release_dc_ptr( dc );
2857 return ret;
2860 /*************************************************************************
2861 * GetCharacterPlacementA [GDI32.@]
2863 * See GetCharacterPlacementW.
2865 * NOTES:
2866 * the web browser control of ie4 calls this with dwFlags=0
2868 DWORD WINAPI
2869 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2870 INT nMaxExtent, GCP_RESULTSA *lpResults,
2871 DWORD dwFlags)
2873 WCHAR *lpStringW;
2874 INT uCountW;
2875 GCP_RESULTSW resultsW;
2876 DWORD ret;
2877 UINT font_cp;
2879 TRACE("%s, %d, %d, 0x%08x\n",
2880 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2882 /* both structs are equal in size */
2883 memcpy(&resultsW, lpResults, sizeof(resultsW));
2885 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2886 if(lpResults->lpOutString)
2887 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2889 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2891 lpResults->nGlyphs = resultsW.nGlyphs;
2892 lpResults->nMaxFit = resultsW.nMaxFit;
2894 if(lpResults->lpOutString) {
2895 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2896 lpResults->lpOutString, uCount, NULL, NULL );
2899 HeapFree(GetProcessHeap(), 0, lpStringW);
2900 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2902 return ret;
2905 /*************************************************************************
2906 * GetCharacterPlacementW [GDI32.@]
2908 * Retrieve information about a string. This includes the width, reordering,
2909 * Glyphing and so on.
2911 * RETURNS
2913 * The width and height of the string if successful, 0 if failed.
2915 * BUGS
2917 * All flags except GCP_REORDER are not yet implemented.
2918 * Reordering is not 100% complient to the Windows BiDi method.
2919 * Caret positioning is not yet implemented for BiDi.
2920 * Classes are not yet implemented.
2923 DWORD WINAPI
2924 GetCharacterPlacementW(
2925 HDC hdc, /* [in] Device context for which the rendering is to be done */
2926 LPCWSTR lpString, /* [in] The string for which information is to be returned */
2927 INT uCount, /* [in] Number of WORDS in string. */
2928 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
2929 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2930 DWORD dwFlags /* [in] Flags specifying how to process the string */
2933 DWORD ret=0;
2934 SIZE size;
2935 UINT i, nSet;
2937 TRACE("%s, %d, %d, 0x%08x\n",
2938 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2940 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2941 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2942 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2943 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2944 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2946 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08x ignored\n", dwFlags);
2947 if(lpResults->lpClass) FIXME("classes not implemented\n");
2948 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2949 FIXME("Caret positions for complex scripts not implemented\n");
2951 nSet = (UINT)uCount;
2952 if(nSet > lpResults->nGlyphs)
2953 nSet = lpResults->nGlyphs;
2955 /* return number of initialized fields */
2956 lpResults->nGlyphs = nSet;
2958 if((dwFlags&GCP_REORDER)==0 )
2960 /* Treat the case where no special handling was requested in a fastpath way */
2961 /* copy will do if the GCP_REORDER flag is not set */
2962 if(lpResults->lpOutString)
2963 memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
2965 if(lpResults->lpOrder)
2967 for(i = 0; i < nSet; i++)
2968 lpResults->lpOrder[i] = i;
2970 } else
2972 BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
2973 nSet, lpResults->lpOrder );
2976 /* FIXME: Will use the placement chars */
2977 if (lpResults->lpDx)
2979 int c;
2980 for (i = 0; i < nSet; i++)
2982 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
2983 lpResults->lpDx[i]= c;
2987 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
2989 int pos = 0;
2991 lpResults->lpCaretPos[0] = 0;
2992 for (i = 1; i < nSet; i++)
2993 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
2994 lpResults->lpCaretPos[i] = (pos += size.cx);
2997 if(lpResults->lpGlyphs)
2998 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
3000 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
3001 ret = MAKELONG(size.cx, size.cy);
3003 return ret;
3006 /*************************************************************************
3007 * GetCharABCWidthsFloatA [GDI32.@]
3009 * See GetCharABCWidthsFloatW.
3011 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3013 INT i, wlen, count = (INT)(last - first + 1);
3014 LPSTR str;
3015 LPWSTR wstr;
3016 BOOL ret = TRUE;
3018 if (count <= 0) return FALSE;
3020 str = HeapAlloc(GetProcessHeap(), 0, count);
3022 for(i = 0; i < count; i++)
3023 str[i] = (BYTE)(first + i);
3025 wstr = FONT_mbtowc( hdc, str, count, &wlen, NULL );
3027 for (i = 0; i < wlen; i++)
3029 if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
3031 ret = FALSE;
3032 break;
3034 abcf++;
3037 HeapFree( GetProcessHeap(), 0, str );
3038 HeapFree( GetProcessHeap(), 0, wstr );
3040 return ret;
3043 /*************************************************************************
3044 * GetCharABCWidthsFloatW [GDI32.@]
3046 * Retrieves widths of a range of characters.
3048 * PARAMS
3049 * hdc [I] Handle to device context.
3050 * first [I] First character in range to query.
3051 * last [I] Last character in range to query.
3052 * abcf [O] Array of LPABCFLOAT structures.
3054 * RETURNS
3055 * Success: TRUE
3056 * Failure: FALSE
3058 * BUGS
3059 * Only works with TrueType fonts. It also doesn't return real
3060 * floats but converted integers because it's implemented on
3061 * top of GetCharABCWidthsW.
3063 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3065 ABC *abc;
3066 unsigned int i, size = sizeof(ABC) * (last - first + 1);
3067 BOOL ret;
3069 TRACE("%p, %d, %d, %p - partial stub\n", hdc, first, last, abcf);
3071 abc = HeapAlloc( GetProcessHeap(), 0, size );
3072 if (!abc) return FALSE;
3074 ret = GetCharABCWidthsW( hdc, first, last, abc );
3075 if (ret)
3077 for (i = first; i <= last; i++, abc++, abcf++)
3079 abcf->abcfA = abc->abcA;
3080 abcf->abcfB = abc->abcB;
3081 abcf->abcfC = abc->abcC;
3084 HeapFree( GetProcessHeap(), 0, abc );
3085 return ret;
3088 /*************************************************************************
3089 * GetCharWidthFloatA [GDI32.@]
3091 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
3092 UINT iLastChar, PFLOAT pxBuffer)
3094 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3095 return 0;
3098 /*************************************************************************
3099 * GetCharWidthFloatW [GDI32.@]
3101 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
3102 UINT iLastChar, PFLOAT pxBuffer)
3104 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3105 return 0;
3109 /***********************************************************************
3111 * Font Resource API *
3113 ***********************************************************************/
3115 /***********************************************************************
3116 * AddFontResourceA (GDI32.@)
3118 INT WINAPI AddFontResourceA( LPCSTR str )
3120 return AddFontResourceExA( str, 0, NULL);
3123 /***********************************************************************
3124 * AddFontResourceW (GDI32.@)
3126 INT WINAPI AddFontResourceW( LPCWSTR str )
3128 return AddFontResourceExW(str, 0, NULL);
3132 /***********************************************************************
3133 * AddFontResourceExA (GDI32.@)
3135 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3137 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3138 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3139 INT ret;
3141 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3142 ret = AddFontResourceExW(strW, fl, pdv);
3143 HeapFree(GetProcessHeap(), 0, strW);
3144 return ret;
3147 static BOOL CALLBACK load_enumed_resource(HMODULE hModule, LPCWSTR type, LPWSTR name, LONG_PTR lParam)
3149 HRSRC rsrc = FindResourceW(hModule, name, type);
3150 HGLOBAL hMem = LoadResource(hModule, rsrc);
3151 LPVOID *pMem = LockResource(hMem);
3152 int *num_total = (int *)lParam;
3153 DWORD num_in_res;
3155 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type));
3156 if (!AddFontMemResourceEx(pMem, SizeofResource(hModule, rsrc), NULL, &num_in_res))
3158 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule, hMem);
3159 return FALSE;
3162 *num_total += num_in_res;
3163 return TRUE;
3166 /***********************************************************************
3167 * AddFontResourceExW (GDI32.@)
3169 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3171 int ret = WineEngAddFontResourceEx(str, fl, pdv);
3172 if (ret == 0)
3174 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3175 HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
3176 if (hModule != NULL)
3178 int num_resources = 0;
3179 LPWSTR rt_font = (LPWSTR)((ULONG_PTR)8); /* we don't want to include winuser.h */
3181 TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3182 wine_dbgstr_w(str));
3183 if (EnumResourceNamesW(hModule, rt_font, load_enumed_resource, (LONG_PTR)&num_resources))
3184 ret = num_resources;
3185 FreeLibrary(hModule);
3188 return ret;
3191 /***********************************************************************
3192 * RemoveFontResourceA (GDI32.@)
3194 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3196 return RemoveFontResourceExA(str, 0, 0);
3199 /***********************************************************************
3200 * RemoveFontResourceW (GDI32.@)
3202 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3204 return RemoveFontResourceExW(str, 0, 0);
3207 /***********************************************************************
3208 * AddFontMemResourceEx (GDI32.@)
3210 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3212 return WineEngAddFontMemResourceEx(pbFont, cbFont, pdv, pcFonts);
3215 /***********************************************************************
3216 * RemoveFontMemResourceEx (GDI32.@)
3218 BOOL WINAPI RemoveFontMemResourceEx( HANDLE fh )
3220 FIXME("(%p) stub\n", fh);
3221 return TRUE;
3224 /***********************************************************************
3225 * RemoveFontResourceExA (GDI32.@)
3227 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3229 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3230 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3231 INT ret;
3233 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3234 ret = RemoveFontResourceExW(strW, fl, pdv);
3235 HeapFree(GetProcessHeap(), 0, strW);
3236 return ret;
3239 /***********************************************************************
3240 * RemoveFontResourceExW (GDI32.@)
3242 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3244 return WineEngRemoveFontResourceEx(str, fl, pdv);
3247 /***********************************************************************
3248 * GetTextCharset (GDI32.@)
3250 UINT WINAPI GetTextCharset(HDC hdc)
3252 /* MSDN docs say this is equivalent */
3253 return GetTextCharsetInfo(hdc, NULL, 0);
3256 /***********************************************************************
3257 * GetTextCharsetInfo (GDI32.@)
3259 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3261 UINT ret = DEFAULT_CHARSET;
3262 DC *dc = get_dc_ptr(hdc);
3264 if (dc)
3266 if (dc->gdiFont)
3267 ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
3269 release_dc_ptr( dc );
3272 if (ret == DEFAULT_CHARSET && fs)
3273 memset(fs, 0, sizeof(FONTSIGNATURE));
3274 return ret;
3277 /***********************************************************************
3278 * GdiGetCharDimensions (GDI32.@)
3280 * Gets the average width of the characters in the English alphabet.
3282 * PARAMS
3283 * hdc [I] Handle to the device context to measure on.
3284 * lptm [O] Pointer to memory to store the text metrics into.
3285 * height [O] On exit, the maximum height of characters in the English alphabet.
3287 * RETURNS
3288 * The average width of characters in the English alphabet.
3290 * NOTES
3291 * This function is used by the dialog manager to get the size of a dialog
3292 * unit. It should also be used by other pieces of code that need to know
3293 * the size of a dialog unit in logical units without having access to the
3294 * window handle of the dialog.
3295 * Windows caches the font metrics from this function, but we don't and
3296 * there doesn't appear to be an immediate advantage to do so.
3298 * SEE ALSO
3299 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3301 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3303 SIZE sz;
3304 static const WCHAR alphabet[] = {
3305 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3306 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3307 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3309 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3311 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3313 if (height) *height = sz.cy;
3314 return (sz.cx / 26 + 1) / 2;
3317 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3319 FIXME("(%d): stub\n", fEnableEUDC);
3320 return FALSE;
3323 /***********************************************************************
3324 * GetCharWidthI (GDI32.@)
3326 * Retrieve widths of characters.
3328 * PARAMS
3329 * hdc [I] Handle to a device context.
3330 * first [I] First glyph in range to query.
3331 * count [I] Number of glyph indices to query.
3332 * glyphs [I] Array of glyphs to query.
3333 * buffer [O] Buffer to receive character widths.
3335 * NOTES
3336 * Only works with TrueType fonts.
3338 * RETURNS
3339 * Success: TRUE
3340 * Failure: FALSE
3342 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3344 ABC *abc;
3345 unsigned int i;
3347 TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3349 if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3350 return FALSE;
3352 if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3354 HeapFree(GetProcessHeap(), 0, abc);
3355 return FALSE;
3358 for (i = 0; i < count; i++)
3359 buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3361 HeapFree(GetProcessHeap(), 0, abc);
3362 return TRUE;
3365 /***********************************************************************
3366 * GetFontUnicodeRanges (GDI32.@)
3368 * Retrieve a list of supported Unicode characters in a font.
3370 * PARAMS
3371 * hdc [I] Handle to a device context.
3372 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3374 * RETURNS
3375 * Success: Number of bytes written to the buffer pointed to by lpgs.
3376 * Failure: 0
3379 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3381 DWORD ret = 0;
3382 DC *dc = get_dc_ptr(hdc);
3384 TRACE("(%p, %p)\n", hdc, lpgs);
3386 if (!dc) return 0;
3388 if (dc->gdiFont) ret = WineEngGetFontUnicodeRanges(dc->gdiFont, lpgs);
3389 release_dc_ptr(dc);
3390 return ret;
3394 /*************************************************************
3395 * FontIsLinked (GDI32.@)
3397 BOOL WINAPI FontIsLinked(HDC hdc)
3399 DC *dc = get_dc_ptr(hdc);
3400 BOOL ret = FALSE;
3402 if (!dc) return FALSE;
3403 if (dc->gdiFont) ret = WineEngFontIsLinked(dc->gdiFont);
3404 release_dc_ptr(dc);
3405 TRACE("returning %d\n", ret);
3406 return ret;