gdi32: Fix the type of two loop variables.
[wine/gsoc_dplay.git] / dlls / gdi32 / font.c
blob1b80df199e8f0f98a6bc71df7152f5ffffbd7cf8
1 /*
2 * GDI font objects
4 * Copyright 1993 Alexandre Julliard
5 * 1997 Alex Korobka
6 * Copyright 2002,2003 Shachar Shemesh
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "config.h"
24 #include "wine/port.h"
26 #include <stdarg.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <assert.h>
30 #include "winerror.h"
31 #include "windef.h"
32 #include "winbase.h"
33 #include "winnls.h"
34 #include "wownt32.h"
35 #include "gdi_private.h"
36 #include "wine/unicode.h"
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(font);
41 /* Device -> World size conversion */
43 /* Performs a device to world transformation on the specified width (which
44 * is in integer format).
46 static inline INT INTERNAL_XDSTOWS(DC *dc, INT width)
48 FLOAT floatWidth;
50 /* Perform operation with floating point */
51 floatWidth = (FLOAT)width * dc->xformVport2World.eM11;
52 /* Round to integers */
53 return GDI_ROUND(floatWidth);
56 /* Performs a device to world transformation on the specified size (which
57 * is in integer format).
59 static inline INT INTERNAL_YDSTOWS(DC *dc, INT height)
61 FLOAT floatHeight;
63 /* Perform operation with floating point */
64 floatHeight = (FLOAT)height * dc->xformVport2World.eM22;
65 /* Round to integers */
66 return GDI_ROUND(floatHeight);
69 static inline INT INTERNAL_XWSTODS(DC *dc, INT width)
71 POINT pt[2];
72 pt[0].x = pt[0].y = 0;
73 pt[1].x = width;
74 pt[1].y = 0;
75 LPtoDP(dc->hSelf, pt, 2);
76 return pt[1].x - pt[0].x;
79 static inline INT INTERNAL_YWSTODS(DC *dc, INT height)
81 POINT pt[2];
82 pt[0].x = pt[0].y = 0;
83 pt[1].x = 0;
84 pt[1].y = height;
85 LPtoDP(dc->hSelf, pt, 2);
86 return pt[1].y - pt[0].y;
89 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc );
90 static INT FONT_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
91 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
92 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
93 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj );
95 static const struct gdi_obj_funcs font_funcs =
97 FONT_SelectObject, /* pSelectObject */
98 FONT_GetObject16, /* pGetObject16 */
99 FONT_GetObjectA, /* pGetObjectA */
100 FONT_GetObjectW, /* pGetObjectW */
101 NULL, /* pUnrealizeObject */
102 FONT_DeleteObject /* pDeleteObject */
105 #define ENUM_UNICODE 0x00000001
106 #define ENUM_CALLED 0x00000002
108 typedef struct
110 GDIOBJHDR header;
111 LOGFONTW logfont;
112 } FONTOBJ;
114 typedef struct
116 LPLOGFONT16 lpLogFontParam;
117 FONTENUMPROC16 lpEnumFunc;
118 LPARAM lpData;
120 LPNEWTEXTMETRICEX16 lpTextMetric;
121 LPENUMLOGFONTEX16 lpLogFont;
122 SEGPTR segTextMetric;
123 SEGPTR segLogFont;
124 DWORD dwFlags;
125 HDC hdc;
126 DC *dc;
127 PHYSDEV physDev;
128 } fontEnum16;
130 typedef struct
132 LPLOGFONTW lpLogFontParam;
133 FONTENUMPROCW lpEnumFunc;
134 LPARAM lpData;
135 DWORD dwFlags;
136 HDC hdc;
137 DC *dc;
138 PHYSDEV physDev;
139 } fontEnum32;
142 * For TranslateCharsetInfo
144 #define FS(x) {{0,0,0,0},{0x1<<(x),0}}
145 #define MAXTCIINDEX 32
146 static const CHARSETINFO FONT_tci[MAXTCIINDEX] = {
147 /* ANSI */
148 { ANSI_CHARSET, 1252, FS(0)},
149 { EASTEUROPE_CHARSET, 1250, FS(1)},
150 { RUSSIAN_CHARSET, 1251, FS(2)},
151 { GREEK_CHARSET, 1253, FS(3)},
152 { TURKISH_CHARSET, 1254, FS(4)},
153 { HEBREW_CHARSET, 1255, FS(5)},
154 { ARABIC_CHARSET, 1256, FS(6)},
155 { BALTIC_CHARSET, 1257, FS(7)},
156 { VIETNAMESE_CHARSET, 1258, FS(8)},
157 /* reserved by ANSI */
158 { DEFAULT_CHARSET, 0, FS(0)},
159 { DEFAULT_CHARSET, 0, FS(0)},
160 { DEFAULT_CHARSET, 0, FS(0)},
161 { DEFAULT_CHARSET, 0, FS(0)},
162 { DEFAULT_CHARSET, 0, FS(0)},
163 { DEFAULT_CHARSET, 0, FS(0)},
164 { DEFAULT_CHARSET, 0, FS(0)},
165 /* ANSI and OEM */
166 { THAI_CHARSET, 874, FS(16)},
167 { SHIFTJIS_CHARSET, 932, FS(17)},
168 { GB2312_CHARSET, 936, FS(18)},
169 { HANGEUL_CHARSET, 949, FS(19)},
170 { CHINESEBIG5_CHARSET, 950, FS(20)},
171 { JOHAB_CHARSET, 1361, FS(21)},
172 /* reserved for alternate ANSI and OEM */
173 { DEFAULT_CHARSET, 0, FS(0)},
174 { DEFAULT_CHARSET, 0, FS(0)},
175 { DEFAULT_CHARSET, 0, FS(0)},
176 { DEFAULT_CHARSET, 0, FS(0)},
177 { DEFAULT_CHARSET, 0, FS(0)},
178 { DEFAULT_CHARSET, 0, FS(0)},
179 { DEFAULT_CHARSET, 0, FS(0)},
180 { DEFAULT_CHARSET, 0, FS(0)},
181 /* reserved for system */
182 { DEFAULT_CHARSET, 0, FS(0)},
183 { SYMBOL_CHARSET, CP_SYMBOL, FS(31)},
186 /***********************************************************************
187 * LOGFONT conversion functions.
189 static void FONT_LogFontWTo16( const LOGFONTW* font32, LPLOGFONT16 font16 )
191 font16->lfHeight = font32->lfHeight;
192 font16->lfWidth = font32->lfWidth;
193 font16->lfEscapement = font32->lfEscapement;
194 font16->lfOrientation = font32->lfOrientation;
195 font16->lfWeight = font32->lfWeight;
196 font16->lfItalic = font32->lfItalic;
197 font16->lfUnderline = font32->lfUnderline;
198 font16->lfStrikeOut = font32->lfStrikeOut;
199 font16->lfCharSet = font32->lfCharSet;
200 font16->lfOutPrecision = font32->lfOutPrecision;
201 font16->lfClipPrecision = font32->lfClipPrecision;
202 font16->lfQuality = font32->lfQuality;
203 font16->lfPitchAndFamily = font32->lfPitchAndFamily;
204 WideCharToMultiByte( CP_ACP, 0, font32->lfFaceName, -1,
205 font16->lfFaceName, LF_FACESIZE, NULL, NULL );
206 font16->lfFaceName[LF_FACESIZE-1] = 0;
209 static void FONT_LogFont16ToW( const LOGFONT16 *font16, LPLOGFONTW font32 )
211 font32->lfHeight = font16->lfHeight;
212 font32->lfWidth = font16->lfWidth;
213 font32->lfEscapement = font16->lfEscapement;
214 font32->lfOrientation = font16->lfOrientation;
215 font32->lfWeight = font16->lfWeight;
216 font32->lfItalic = font16->lfItalic;
217 font32->lfUnderline = font16->lfUnderline;
218 font32->lfStrikeOut = font16->lfStrikeOut;
219 font32->lfCharSet = font16->lfCharSet;
220 font32->lfOutPrecision = font16->lfOutPrecision;
221 font32->lfClipPrecision = font16->lfClipPrecision;
222 font32->lfQuality = font16->lfQuality;
223 font32->lfPitchAndFamily = font16->lfPitchAndFamily;
224 MultiByteToWideChar( CP_ACP, 0, font16->lfFaceName, -1, font32->lfFaceName, LF_FACESIZE );
225 font32->lfFaceName[LF_FACESIZE-1] = 0;
228 static void FONT_LogFontAToW( const LOGFONTA *fontA, LPLOGFONTW fontW )
230 memcpy(fontW, fontA, sizeof(LOGFONTA) - LF_FACESIZE);
231 MultiByteToWideChar(CP_ACP, 0, fontA->lfFaceName, -1, fontW->lfFaceName,
232 LF_FACESIZE);
233 fontW->lfFaceName[LF_FACESIZE-1] = 0;
236 static void FONT_LogFontWToA( const LOGFONTW *fontW, LPLOGFONTA fontA )
238 memcpy(fontA, fontW, sizeof(LOGFONTA) - LF_FACESIZE);
239 WideCharToMultiByte(CP_ACP, 0, fontW->lfFaceName, -1, fontA->lfFaceName,
240 LF_FACESIZE, NULL, NULL);
241 fontA->lfFaceName[LF_FACESIZE-1] = 0;
244 static void FONT_EnumLogFontExWTo16( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEX16 font16 )
246 FONT_LogFontWTo16( (const LOGFONTW *)fontW, (LPLOGFONT16)font16);
248 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
249 (LPSTR) font16->elfFullName, LF_FULLFACESIZE, NULL, NULL );
250 font16->elfFullName[LF_FULLFACESIZE-1] = '\0';
251 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
252 (LPSTR) font16->elfStyle, LF_FACESIZE, NULL, NULL );
253 font16->elfStyle[LF_FACESIZE-1] = '\0';
254 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
255 (LPSTR) font16->elfScript, LF_FACESIZE, NULL, NULL );
256 font16->elfScript[LF_FACESIZE-1] = '\0';
259 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEXA fontA )
261 FONT_LogFontWToA( (const LOGFONTW *)fontW, (LPLOGFONTA)fontA);
263 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
264 (LPSTR) fontA->elfFullName, LF_FULLFACESIZE, NULL, NULL );
265 fontA->elfFullName[LF_FULLFACESIZE-1] = '\0';
266 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
267 (LPSTR) fontA->elfStyle, LF_FACESIZE, NULL, NULL );
268 fontA->elfStyle[LF_FACESIZE-1] = '\0';
269 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
270 (LPSTR) fontA->elfScript, LF_FACESIZE, NULL, NULL );
271 fontA->elfScript[LF_FACESIZE-1] = '\0';
274 /***********************************************************************
275 * TEXTMETRIC conversion functions.
277 static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
279 ptmA->tmHeight = ptmW->tmHeight;
280 ptmA->tmAscent = ptmW->tmAscent;
281 ptmA->tmDescent = ptmW->tmDescent;
282 ptmA->tmInternalLeading = ptmW->tmInternalLeading;
283 ptmA->tmExternalLeading = ptmW->tmExternalLeading;
284 ptmA->tmAveCharWidth = ptmW->tmAveCharWidth;
285 ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth;
286 ptmA->tmWeight = ptmW->tmWeight;
287 ptmA->tmOverhang = ptmW->tmOverhang;
288 ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX;
289 ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
290 ptmA->tmFirstChar = min(ptmW->tmFirstChar, 255);
291 if (ptmW->tmCharSet == SYMBOL_CHARSET)
293 UINT last_char = ptmW->tmLastChar;
294 if (last_char > 0xf000) last_char -= 0xf000;
295 ptmA->tmLastChar = min(last_char, 255);
297 else
298 ptmA->tmLastChar = min(ptmW->tmLastChar, 255);
299 ptmA->tmDefaultChar = min(ptmW->tmDefaultChar, 255);
300 ptmA->tmBreakChar = min(ptmW->tmBreakChar, 255);
301 ptmA->tmItalic = ptmW->tmItalic;
302 ptmA->tmUnderlined = ptmW->tmUnderlined;
303 ptmA->tmStruckOut = ptmW->tmStruckOut;
304 ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
305 ptmA->tmCharSet = ptmW->tmCharSet;
309 static void FONT_NewTextMetricExWTo16(const NEWTEXTMETRICEXW *ptmW, LPNEWTEXTMETRICEX16 ptm16 )
311 ptm16->ntmTm.tmHeight = ptmW->ntmTm.tmHeight;
312 ptm16->ntmTm.tmAscent = ptmW->ntmTm.tmAscent;
313 ptm16->ntmTm.tmDescent = ptmW->ntmTm.tmDescent;
314 ptm16->ntmTm.tmInternalLeading = ptmW->ntmTm.tmInternalLeading;
315 ptm16->ntmTm.tmExternalLeading = ptmW->ntmTm.tmExternalLeading;
316 ptm16->ntmTm.tmAveCharWidth = ptmW->ntmTm.tmAveCharWidth;
317 ptm16->ntmTm.tmMaxCharWidth = ptmW->ntmTm.tmMaxCharWidth;
318 ptm16->ntmTm.tmWeight = ptmW->ntmTm.tmWeight;
319 ptm16->ntmTm.tmOverhang = ptmW->ntmTm.tmOverhang;
320 ptm16->ntmTm.tmDigitizedAspectX = ptmW->ntmTm.tmDigitizedAspectX;
321 ptm16->ntmTm.tmDigitizedAspectY = ptmW->ntmTm.tmDigitizedAspectY;
322 ptm16->ntmTm.tmFirstChar = ptmW->ntmTm.tmFirstChar > 255 ? 255 : ptmW->ntmTm.tmFirstChar;
323 ptm16->ntmTm.tmLastChar = ptmW->ntmTm.tmLastChar > 255 ? 255 : ptmW->ntmTm.tmLastChar;
324 ptm16->ntmTm.tmDefaultChar = ptmW->ntmTm.tmDefaultChar > 255 ? 255 : ptmW->ntmTm.tmDefaultChar;
325 ptm16->ntmTm.tmBreakChar = ptmW->ntmTm.tmBreakChar > 255 ? 255 : ptmW->ntmTm.tmBreakChar;
326 ptm16->ntmTm.tmItalic = ptmW->ntmTm.tmItalic;
327 ptm16->ntmTm.tmUnderlined = ptmW->ntmTm.tmUnderlined;
328 ptm16->ntmTm.tmStruckOut = ptmW->ntmTm.tmStruckOut;
329 ptm16->ntmTm.tmPitchAndFamily = ptmW->ntmTm.tmPitchAndFamily;
330 ptm16->ntmTm.tmCharSet = ptmW->ntmTm.tmCharSet;
331 ptm16->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
332 ptm16->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
333 ptm16->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
334 ptm16->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
335 memcpy(&ptm16->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
338 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW *ptmW, NEWTEXTMETRICEXA *ptmA )
340 FONT_TextMetricWToA((const TEXTMETRICW *)ptmW, (LPTEXTMETRICA)ptmA);
341 ptmA->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
342 ptmA->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
343 ptmA->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
344 ptmA->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
345 memcpy(&ptmA->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
349 /***********************************************************************
350 * GdiGetCodePage (GDI32.@)
352 DWORD WINAPI GdiGetCodePage( HDC hdc )
354 UINT cp = CP_ACP;
355 CHARSETINFO csi;
356 int charset = GetTextCharset(hdc);
358 /* Hmm, nicely designed api this one! */
359 if(TranslateCharsetInfo(ULongToPtr(charset), &csi, TCI_SRCCHARSET))
360 cp = csi.ciACP;
361 else {
362 switch(charset) {
363 case OEM_CHARSET:
364 cp = GetOEMCP();
365 break;
366 case DEFAULT_CHARSET:
367 cp = GetACP();
368 break;
370 case VISCII_CHARSET:
371 case TCVN_CHARSET:
372 case KOI8_CHARSET:
373 case ISO3_CHARSET:
374 case ISO4_CHARSET:
375 case ISO10_CHARSET:
376 case CELTIC_CHARSET:
377 /* FIXME: These have no place here, but because x11drv
378 enumerates fonts with these (made up) charsets some apps
379 might use them and then the FIXME below would become
380 annoying. Now we could pick the intended codepage for
381 each of these, but since it's broken anyway we'll just
382 use CP_ACP and hope it'll go away...
384 cp = CP_ACP;
385 break;
387 default:
388 FIXME("Can't find codepage for charset %d\n", charset);
389 break;
393 TRACE("charset %d => cp %d\n", charset, cp);
394 return cp;
397 /***********************************************************************
398 * FONT_mbtowc
400 * Returns a Unicode translation of str using the charset of the
401 * currently selected font in hdc. If count is -1 then str is assumed
402 * to be '\0' terminated, otherwise it contains the number of bytes to
403 * convert. If plenW is non-NULL, on return it will point to the
404 * number of WCHARs that have been written. If pCP is non-NULL, on
405 * return it will point to the codepage used in the conversion. The
406 * caller should free the returned LPWSTR from the process heap
407 * itself.
409 static LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
411 UINT cp;
412 INT lenW;
413 LPWSTR strW;
415 cp = GdiGetCodePage( hdc );
417 if(count == -1) count = strlen(str);
418 lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
419 strW = HeapAlloc(GetProcessHeap(), 0, lenW*sizeof(WCHAR));
420 MultiByteToWideChar(cp, 0, str, count, strW, lenW);
421 TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW));
422 if(plenW) *plenW = lenW;
423 if(pCP) *pCP = cp;
424 return strW;
428 /***********************************************************************
429 * CreateFontIndirectA (GDI32.@)
431 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *plfA )
433 LOGFONTW lfW;
435 if (plfA) {
436 FONT_LogFontAToW( plfA, &lfW );
437 return CreateFontIndirectW( &lfW );
438 } else
439 return CreateFontIndirectW( NULL );
443 /***********************************************************************
444 * CreateFontIndirectW (GDI32.@)
446 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
448 HFONT hFont = 0;
450 if (plf)
452 FONTOBJ* fontPtr;
453 if ((fontPtr = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC,
454 (HGDIOBJ *)&hFont, &font_funcs )))
456 static const WCHAR ItalicW[] = {' ','I','t','a','l','i','c','\0'};
457 static const WCHAR BoldW[] = {' ','B','o','l','d','\0'};
458 WCHAR *pFaceNameItalicSuffix, *pFaceNameBoldSuffix;
459 WCHAR* pFaceNameSuffix = NULL;
461 memcpy( &fontPtr->logfont, plf, sizeof(LOGFONTW) );
463 TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
464 plf->lfHeight, plf->lfWidth,
465 plf->lfEscapement, plf->lfOrientation,
466 plf->lfPitchAndFamily,
467 plf->lfOutPrecision, plf->lfClipPrecision,
468 plf->lfQuality, plf->lfCharSet,
469 debugstr_w(plf->lfFaceName),
470 plf->lfWeight > 400 ? "Bold" : "",
471 plf->lfItalic ? "Italic" : "",
472 plf->lfUnderline ? "Underline" : "", hFont);
474 if (plf->lfEscapement != plf->lfOrientation) {
475 /* this should really depend on whether GM_ADVANCED is set */
476 fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
477 WARN("orientation angle %f set to "
478 "escapement angle %f for new font %p\n",
479 plf->lfOrientation/10., plf->lfEscapement/10., hFont);
482 pFaceNameItalicSuffix = strstrW(fontPtr->logfont.lfFaceName, ItalicW);
483 if (pFaceNameItalicSuffix) {
484 fontPtr->logfont.lfItalic = TRUE;
485 pFaceNameSuffix = pFaceNameItalicSuffix;
488 pFaceNameBoldSuffix = strstrW(fontPtr->logfont.lfFaceName, BoldW);
489 if (pFaceNameBoldSuffix) {
490 if (fontPtr->logfont.lfWeight < FW_BOLD) {
491 fontPtr->logfont.lfWeight = FW_BOLD;
493 if (!pFaceNameSuffix ||
494 (pFaceNameBoldSuffix < pFaceNameSuffix)) {
495 pFaceNameSuffix = pFaceNameBoldSuffix;
499 if (pFaceNameSuffix) *pFaceNameSuffix = 0;
501 GDI_ReleaseObj( hFont );
504 else WARN("(NULL) => NULL\n");
506 return hFont;
509 /*************************************************************************
510 * CreateFontA (GDI32.@)
512 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
513 INT orient, INT weight, DWORD italic,
514 DWORD underline, DWORD strikeout, DWORD charset,
515 DWORD outpres, DWORD clippres, DWORD quality,
516 DWORD pitch, LPCSTR name )
518 LOGFONTA logfont;
520 logfont.lfHeight = height;
521 logfont.lfWidth = width;
522 logfont.lfEscapement = esc;
523 logfont.lfOrientation = orient;
524 logfont.lfWeight = weight;
525 logfont.lfItalic = italic;
526 logfont.lfUnderline = underline;
527 logfont.lfStrikeOut = strikeout;
528 logfont.lfCharSet = charset;
529 logfont.lfOutPrecision = outpres;
530 logfont.lfClipPrecision = clippres;
531 logfont.lfQuality = quality;
532 logfont.lfPitchAndFamily = pitch;
534 if (name)
535 lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
536 else
537 logfont.lfFaceName[0] = '\0';
539 return CreateFontIndirectA( &logfont );
542 /*************************************************************************
543 * CreateFontW (GDI32.@)
545 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
546 INT orient, INT weight, DWORD italic,
547 DWORD underline, DWORD strikeout, DWORD charset,
548 DWORD outpres, DWORD clippres, DWORD quality,
549 DWORD pitch, LPCWSTR name )
551 LOGFONTW logfont;
553 logfont.lfHeight = height;
554 logfont.lfWidth = width;
555 logfont.lfEscapement = esc;
556 logfont.lfOrientation = orient;
557 logfont.lfWeight = weight;
558 logfont.lfItalic = italic;
559 logfont.lfUnderline = underline;
560 logfont.lfStrikeOut = strikeout;
561 logfont.lfCharSet = charset;
562 logfont.lfOutPrecision = outpres;
563 logfont.lfClipPrecision = clippres;
564 logfont.lfQuality = quality;
565 logfont.lfPitchAndFamily = pitch;
567 if (name)
568 lstrcpynW(logfont.lfFaceName, name,
569 sizeof(logfont.lfFaceName) / sizeof(WCHAR));
570 else
571 logfont.lfFaceName[0] = '\0';
573 return CreateFontIndirectW( &logfont );
577 /***********************************************************************
578 * FONT_SelectObject
580 * If the driver supports vector fonts we create a gdi font first and
581 * then call the driver to give it a chance to supply its own device
582 * font. If the driver wants to do this it returns TRUE and we can
583 * delete the gdi font, if the driver wants to use the gdi font it
584 * should return FALSE, to signal an error return GDI_ERROR. For
585 * drivers that don't support vector fonts they must supply their own
586 * font.
588 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc )
590 HGDIOBJ ret = 0;
591 DC *dc = get_dc_ptr( hdc );
593 if (!dc) return 0;
595 if (!GDI_inc_ref_count( handle ))
597 release_dc_ptr( dc );
598 return 0;
601 if (dc->hFont != handle || dc->gdiFont == NULL)
603 if(GetDeviceCaps(dc->hSelf, TEXTCAPS) & TC_VA_ABLE)
605 FONTOBJ *font = GDI_GetObjPtr( handle, FONT_MAGIC ); /* to grab the GDI lock (FIXME) */
606 dc->gdiFont = WineEngCreateFontInstance(dc, handle);
607 if (font) GDI_ReleaseObj( handle );
611 if (dc->funcs->pSelectFont) ret = dc->funcs->pSelectFont( dc->physDev, handle, dc->gdiFont );
613 if (ret && dc->gdiFont) dc->gdiFont = 0;
615 if (ret == HGDI_ERROR)
617 GDI_dec_ref_count( handle );
618 ret = 0; /* SelectObject returns 0 on error */
620 else
622 ret = dc->hFont;
623 dc->hFont = handle;
624 GDI_dec_ref_count( ret );
626 release_dc_ptr( dc );
627 return ret;
631 /***********************************************************************
632 * FONT_GetObject16
634 static INT FONT_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
636 FONTOBJ *font = obj;
637 LOGFONT16 lf16;
639 FONT_LogFontWTo16( &font->logfont, &lf16 );
641 if (count > sizeof(LOGFONT16)) count = sizeof(LOGFONT16);
642 memcpy( buffer, &lf16, count );
643 return count;
646 /***********************************************************************
647 * FONT_GetObjectA
649 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
651 FONTOBJ *font = obj;
652 LOGFONTA lfA;
654 if(!buffer)
655 return sizeof(lfA);
656 FONT_LogFontWToA( &font->logfont, &lfA );
658 if (count > sizeof(lfA)) count = sizeof(lfA);
659 memcpy( buffer, &lfA, count );
660 return count;
663 /***********************************************************************
664 * FONT_GetObjectW
666 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
668 FONTOBJ *font = obj;
669 if(!buffer)
670 return sizeof(LOGFONTW);
671 if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
672 memcpy( buffer, &font->logfont, count );
673 return count;
677 /***********************************************************************
678 * FONT_DeleteObject
680 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj )
682 WineEngDestroyFontInstance( handle );
683 return GDI_FreeObject( handle, obj );
687 /***********************************************************************
688 * FONT_EnumInstance16
690 * Called by the device driver layer to pass font info
691 * down to the application.
693 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
694 * We have to use other types because of the FONTENUMPROCW definition.
696 static INT CALLBACK FONT_EnumInstance16( const LOGFONTW *plf, const TEXTMETRICW *ptm,
697 DWORD fType, LPARAM lp )
699 fontEnum16 *pfe = (fontEnum16*)lp;
700 INT ret = 1;
701 DC *dc;
703 if( pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
704 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet )
706 WORD args[7];
707 DWORD result;
709 FONT_EnumLogFontExWTo16((const ENUMLOGFONTEXW *)plf, pfe->lpLogFont);
710 FONT_NewTextMetricExWTo16((const NEWTEXTMETRICEXW *)ptm, pfe->lpTextMetric);
711 pfe->dwFlags |= ENUM_CALLED;
712 DC_ReleaseDCPtr( pfe->dc ); /* release the GDI lock */
714 args[6] = SELECTOROF(pfe->segLogFont);
715 args[5] = OFFSETOF(pfe->segLogFont);
716 args[4] = SELECTOROF(pfe->segTextMetric);
717 args[3] = OFFSETOF(pfe->segTextMetric);
718 args[2] = fType;
719 args[1] = HIWORD(pfe->lpData);
720 args[0] = LOWORD(pfe->lpData);
721 WOWCallback16Ex( (DWORD)pfe->lpEnumFunc, WCB16_PASCAL, sizeof(args), args, &result );
722 ret = LOWORD(result);
724 /* get the lock again and make sure the DC is still valid */
725 dc = DC_GetDCPtr( pfe->hdc );
726 if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
728 if (dc) DC_ReleaseDCPtr( dc );
729 pfe->hdc = 0; /* make sure we don't try to release it later on */
730 pfe->dc = NULL;
731 ret = 0;
734 return ret;
737 /***********************************************************************
738 * FONT_EnumInstance
740 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
741 * We have to use other types because of the FONTENUMPROCW definition.
743 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
744 DWORD fType, LPARAM lp )
746 fontEnum32 *pfe = (fontEnum32*)lp;
747 INT ret = 1;
748 DC *dc;
750 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
751 if((pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
752 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
753 (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
755 /* convert font metrics */
756 ENUMLOGFONTEXA logfont;
757 NEWTEXTMETRICEXA tmA;
759 pfe->dwFlags |= ENUM_CALLED;
760 if (!(pfe->dwFlags & ENUM_UNICODE))
762 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
763 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
764 plf = (LOGFONTW *)&logfont.elfLogFont;
765 ptm = (TEXTMETRICW *)&tmA;
767 DC_ReleaseDCPtr( pfe->dc ); /* release the GDI lock */
769 ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
771 /* get the lock again and make sure the DC is still valid */
772 dc = DC_GetDCPtr( pfe->hdc );
773 if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
775 if (dc) DC_ReleaseDCPtr( dc );
776 pfe->hdc = 0; /* make sure we don't try to release it later on */
777 pfe->dc = NULL;
778 ret = 0;
781 return ret;
784 /***********************************************************************
785 * EnumFontFamiliesEx (GDI.613)
787 INT16 WINAPI EnumFontFamiliesEx16( HDC16 hDC, LPLOGFONT16 plf,
788 FONTENUMPROC16 efproc, LPARAM lParam,
789 DWORD dwFlags)
791 fontEnum16 fe16;
792 INT16 ret = 1, ret2;
793 DC* dc = DC_GetDCPtr( HDC_32(hDC) );
794 NEWTEXTMETRICEX16 tm16;
795 ENUMLOGFONTEX16 lf16;
796 LOGFONTW lfW;
797 BOOL enum_gdi_fonts;
799 if (!dc) return 0;
800 FONT_LogFont16ToW(plf, &lfW);
802 fe16.hdc = HDC_32(hDC);
803 fe16.dc = dc;
804 fe16.physDev = dc->physDev;
805 fe16.lpLogFontParam = plf;
806 fe16.lpEnumFunc = efproc;
807 fe16.lpData = lParam;
808 fe16.lpTextMetric = &tm16;
809 fe16.lpLogFont = &lf16;
810 fe16.segTextMetric = MapLS( &tm16 );
811 fe16.segLogFont = MapLS( &lf16 );
812 fe16.dwFlags = 0;
814 enum_gdi_fonts = GetDeviceCaps(fe16.hdc, TEXTCAPS) & TC_VA_ABLE;
816 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
818 ret = 0;
819 goto done;
822 if (enum_gdi_fonts)
823 ret = WineEngEnumFonts( &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
824 fe16.dwFlags &= ~ENUM_CALLED;
825 if (ret && dc->funcs->pEnumDeviceFonts) {
826 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
827 if(fe16.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
828 ret = ret2;
830 done:
831 UnMapLS( fe16.segTextMetric );
832 UnMapLS( fe16.segLogFont );
833 if (fe16.dc) DC_ReleaseDCPtr( fe16.dc );
834 return ret;
837 /***********************************************************************
838 * FONT_EnumFontFamiliesEx
840 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf,
841 FONTENUMPROCW efproc,
842 LPARAM lParam, DWORD dwUnicode)
844 INT ret = 1, ret2;
845 DC *dc = DC_GetDCPtr( hDC );
846 fontEnum32 fe32;
847 BOOL enum_gdi_fonts;
849 if (!dc) return 0;
851 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName),
852 plf->lfCharSet);
853 fe32.lpLogFontParam = plf;
854 fe32.lpEnumFunc = efproc;
855 fe32.lpData = lParam;
856 fe32.dwFlags = dwUnicode;
857 fe32.hdc = hDC;
858 fe32.dc = dc;
859 fe32.physDev = dc->physDev;
861 enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE;
863 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
865 ret = 0;
866 goto done;
869 if (enum_gdi_fonts)
870 ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
871 fe32.dwFlags &= ~ENUM_CALLED;
872 if (ret && dc->funcs->pEnumDeviceFonts) {
873 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, plf, FONT_EnumInstance, (LPARAM)&fe32 );
874 if(fe32.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
875 ret = ret2;
877 done:
878 if (fe32.dc) DC_ReleaseDCPtr( fe32.dc );
879 return ret;
882 /***********************************************************************
883 * EnumFontFamiliesExW (GDI32.@)
885 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
886 FONTENUMPROCW efproc,
887 LPARAM lParam, DWORD dwFlags )
889 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, ENUM_UNICODE );
892 /***********************************************************************
893 * EnumFontFamiliesExA (GDI32.@)
895 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
896 FONTENUMPROCA efproc,
897 LPARAM lParam, DWORD dwFlags)
899 LOGFONTW lfW;
900 FONT_LogFontAToW( plf, &lfW );
902 return FONT_EnumFontFamiliesEx( hDC, &lfW, (FONTENUMPROCW)efproc, lParam, 0);
905 /***********************************************************************
906 * EnumFontFamilies (GDI.330)
908 INT16 WINAPI EnumFontFamilies16( HDC16 hDC, LPCSTR lpFamily,
909 FONTENUMPROC16 efproc, LPARAM lpData )
911 LOGFONT16 lf;
913 lf.lfCharSet = DEFAULT_CHARSET;
914 if (lpFamily)
916 if (!*lpFamily) return 1;
917 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
919 else lf.lfFaceName[0] = '\0';
921 return EnumFontFamiliesEx16( hDC, &lf, efproc, lpData, 0 );
924 /***********************************************************************
925 * EnumFontFamiliesA (GDI32.@)
927 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
928 FONTENUMPROCA efproc, LPARAM lpData )
930 LOGFONTA lf;
932 lf.lfCharSet = DEFAULT_CHARSET;
933 if (lpFamily)
935 if (!*lpFamily) return 1;
936 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
938 else lf.lfFaceName[0] = lf.lfFaceName[1] = '\0';
940 return EnumFontFamiliesExA( hDC, &lf, efproc, lpData, 0 );
943 /***********************************************************************
944 * EnumFontFamiliesW (GDI32.@)
946 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
947 FONTENUMPROCW efproc, LPARAM lpData )
949 LOGFONTW lf;
951 lf.lfCharSet = DEFAULT_CHARSET;
952 if (lpFamily)
954 if (!*lpFamily) return 1;
955 lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
957 else lf.lfFaceName[0] = 0;
959 return EnumFontFamiliesExW( hDC, &lf, efproc, lpData, 0 );
962 /***********************************************************************
963 * EnumFonts (GDI.70)
965 INT16 WINAPI EnumFonts16( HDC16 hDC, LPCSTR lpName, FONTENUMPROC16 efproc,
966 LPARAM lpData )
968 return EnumFontFamilies16( hDC, lpName, efproc, lpData );
971 /***********************************************************************
972 * EnumFontsA (GDI32.@)
974 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
975 LPARAM lpData )
977 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
980 /***********************************************************************
981 * EnumFontsW (GDI32.@)
983 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
984 LPARAM lpData )
986 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
990 /***********************************************************************
991 * GetTextCharacterExtra (GDI32.@)
993 INT WINAPI GetTextCharacterExtra( HDC hdc )
995 INT ret;
996 DC *dc = DC_GetDCPtr( hdc );
997 if (!dc) return 0x80000000;
998 ret = dc->charExtra;
999 DC_ReleaseDCPtr( dc );
1000 return ret;
1004 /***********************************************************************
1005 * SetTextCharacterExtra (GDI32.@)
1007 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
1009 INT prev;
1010 DC * dc = DC_GetDCPtr( hdc );
1011 if (!dc) return 0x80000000;
1012 if (dc->funcs->pSetTextCharacterExtra)
1013 prev = dc->funcs->pSetTextCharacterExtra( dc->physDev, extra );
1014 else
1016 prev = dc->charExtra;
1017 dc->charExtra = extra;
1019 DC_ReleaseDCPtr( dc );
1020 return prev;
1024 /***********************************************************************
1025 * SetTextJustification (GDI32.@)
1027 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
1029 BOOL ret = TRUE;
1030 DC * dc = DC_GetDCPtr( hdc );
1031 if (!dc) return FALSE;
1032 if (dc->funcs->pSetTextJustification)
1033 ret = dc->funcs->pSetTextJustification( dc->physDev, extra, breaks );
1034 else
1036 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
1037 if (!extra) breaks = 0;
1038 if (breaks)
1040 dc->breakExtra = extra / breaks;
1041 dc->breakRem = extra - (breaks * dc->breakExtra);
1043 else
1045 dc->breakExtra = 0;
1046 dc->breakRem = 0;
1049 DC_ReleaseDCPtr( dc );
1050 return ret;
1054 /***********************************************************************
1055 * GetTextFaceA (GDI32.@)
1057 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
1059 INT res = GetTextFaceW(hdc, 0, NULL);
1060 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
1061 GetTextFaceW( hdc, res, nameW );
1063 if (name)
1065 if (count && !WideCharToMultiByte( CP_ACP, 0, nameW, -1, name, count, NULL, NULL))
1066 name[count-1] = 0;
1067 res = strlen(name);
1069 else
1070 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
1071 HeapFree( GetProcessHeap(), 0, nameW );
1072 return res;
1075 /***********************************************************************
1076 * GetTextFaceW (GDI32.@)
1078 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
1080 FONTOBJ *font;
1081 INT ret = 0;
1083 DC * dc = DC_GetDCPtr( hdc );
1084 if (!dc) return 0;
1086 if(dc->gdiFont)
1087 ret = WineEngGetTextFace(dc->gdiFont, count, name);
1088 else if ((font = (FONTOBJ *) GDI_GetObjPtr( dc->hFont, FONT_MAGIC )))
1090 if (name)
1092 lstrcpynW( name, font->logfont.lfFaceName, count );
1093 ret = strlenW(name);
1095 else ret = strlenW(font->logfont.lfFaceName) + 1;
1096 GDI_ReleaseObj( dc->hFont );
1098 DC_ReleaseDCPtr( dc );
1099 return ret;
1103 /***********************************************************************
1104 * GetTextExtentPoint32A (GDI32.@)
1106 * See GetTextExtentPoint32W.
1108 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
1109 LPSIZE size )
1111 BOOL ret = FALSE;
1112 INT wlen;
1113 LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1115 if (p) {
1116 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
1117 HeapFree( GetProcessHeap(), 0, p );
1120 TRACE("(%p %s %d %p): returning %d x %d\n",
1121 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
1122 return ret;
1126 /***********************************************************************
1127 * GetTextExtentPoint32W [GDI32.@]
1129 * Computes width/height for a string.
1131 * Computes width and height of the specified string.
1133 * RETURNS
1134 * Success: TRUE
1135 * Failure: FALSE
1137 BOOL WINAPI GetTextExtentPoint32W(
1138 HDC hdc, /* [in] Handle of device context */
1139 LPCWSTR str, /* [in] Address of text string */
1140 INT count, /* [in] Number of characters in string */
1141 LPSIZE size) /* [out] Address of structure for string size */
1143 return GetTextExtentExPointW(hdc, str, count, 0, NULL, NULL, size);
1146 /***********************************************************************
1147 * GetTextExtentPointI [GDI32.@]
1149 * Computes width and height of the array of glyph indices.
1151 * RETURNS
1152 * Success: TRUE
1153 * Failure: FALSE
1155 BOOL WINAPI GetTextExtentPointI(
1156 HDC hdc, /* [in] Handle of device context */
1157 const WORD *indices, /* [in] Address of glyph index array */
1158 INT count, /* [in] Number of glyphs in array */
1159 LPSIZE size) /* [out] Address of structure for string size */
1161 BOOL ret = FALSE;
1162 DC * dc = DC_GetDCPtr( hdc );
1163 if (!dc) return FALSE;
1165 if(dc->gdiFont) {
1166 ret = WineEngGetTextExtentPointI(dc->gdiFont, indices, count, size);
1167 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1168 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1169 size->cx += count * dc->charExtra;
1171 else if(dc->funcs->pGetTextExtentExPoint) {
1172 FIXME("calling GetTextExtentExPoint\n");
1173 ret = dc->funcs->pGetTextExtentExPoint( dc->physDev, (LPCWSTR)indices,
1174 count, 0, NULL, NULL, size );
1177 DC_ReleaseDCPtr( dc );
1179 TRACE("(%p %p %d %p): returning %d x %d\n",
1180 hdc, indices, count, size, size->cx, size->cy );
1181 return ret;
1185 /***********************************************************************
1186 * GetTextExtentPointA (GDI32.@)
1188 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
1189 LPSIZE size )
1191 TRACE("not bug compatible.\n");
1192 return GetTextExtentPoint32A( hdc, str, count, size );
1195 /***********************************************************************
1196 * GetTextExtentPointW (GDI32.@)
1198 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1199 LPSIZE size )
1201 TRACE("not bug compatible.\n");
1202 return GetTextExtentPoint32W( hdc, str, count, size );
1206 /***********************************************************************
1207 * GetTextExtentExPointA (GDI32.@)
1209 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1210 INT maxExt, LPINT lpnFit,
1211 LPINT alpDx, LPSIZE size )
1213 BOOL ret;
1214 INT wlen;
1215 INT *walpDx = NULL;
1216 LPWSTR p = NULL;
1218 if (alpDx &&
1219 NULL == (walpDx = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT))))
1220 return FALSE;
1222 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1223 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
1224 if (walpDx)
1226 INT n = lpnFit ? *lpnFit : wlen;
1227 INT i, j;
1228 for(i = 0, j = 0; i < n; i++, j++)
1230 alpDx[j] = walpDx[i];
1231 if (IsDBCSLeadByte(str[j])) alpDx[++j] = walpDx[i];
1234 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1235 HeapFree( GetProcessHeap(), 0, p );
1236 HeapFree( GetProcessHeap(), 0, walpDx );
1237 return ret;
1241 /***********************************************************************
1242 * GetTextExtentExPointW (GDI32.@)
1244 * Return the size of the string as it would be if it was output properly by
1245 * e.g. TextOut.
1247 * This should include
1248 * - Intercharacter spacing
1249 * - justification spacing (not yet done)
1250 * - kerning? see below
1252 * Kerning. Since kerning would be carried out by the rendering code it should
1253 * be done by the driver. However they don't support it yet. Also I am not
1254 * yet persuaded that (certainly under Win95) any kerning is actually done.
1256 * str: According to MSDN this should be null-terminated. That is not true; a
1257 * null will not terminate it early.
1258 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1259 * than count. I have seen it be either the size of the full string or
1260 * 1 less than the size of the full string. I have not seen it bear any
1261 * resemblance to the portion that would fit.
1262 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1263 * trailing intercharacter spacing and any trailing justification.
1265 * FIXME
1266 * Currently we do this by measuring each character etc. We should do it by
1267 * passing the request to the driver, perhaps by extending the
1268 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1269 * thinking about kerning issues and rounding issues in the justification.
1272 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1273 INT maxExt, LPINT lpnFit,
1274 LPINT alpDx, LPSIZE size )
1276 INT nFit = 0;
1277 LPINT dxs = NULL;
1278 DC *dc;
1279 BOOL ret = FALSE;
1280 TEXTMETRICW tm;
1282 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1284 dc = DC_GetDCPtr(hdc);
1285 if (! dc)
1286 return FALSE;
1288 GetTextMetricsW(hdc, &tm);
1290 /* If we need to calculate nFit, then we need the partial extents even if
1291 the user hasn't provided us with an array. */
1292 if (lpnFit)
1294 dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]);
1295 if (! dxs)
1297 DC_ReleaseDCPtr(dc);
1298 SetLastError(ERROR_OUTOFMEMORY);
1299 return FALSE;
1302 else
1303 dxs = alpDx;
1305 if (dc->gdiFont)
1306 ret = WineEngGetTextExtentExPoint(dc->gdiFont, str, count,
1307 0, NULL, dxs, size);
1308 else if (dc->funcs->pGetTextExtentExPoint)
1309 ret = dc->funcs->pGetTextExtentExPoint(dc->physDev, str, count,
1310 0, NULL, dxs, size);
1312 /* Perform device size to world size transformations. */
1313 if (ret)
1315 INT extra = dc->charExtra,
1316 breakExtra = dc->breakExtra,
1317 breakRem = dc->breakRem,
1320 if (dxs)
1322 for (i = 0; i < count; ++i)
1324 dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
1325 dxs[i] += (i+1) * extra;
1326 if (count > 1 && (breakExtra || breakRem) && str[i] == tm.tmBreakChar)
1328 dxs[i] += breakExtra;
1329 if (breakRem > 0)
1331 breakRem--;
1332 dxs[i]++;
1335 if (dxs[i] <= maxExt)
1336 ++nFit;
1338 breakRem = dc->breakRem;
1340 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1341 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1343 if (!dxs && count > 1 && (breakExtra || breakRem))
1345 for (i = 0; i < count; i++)
1347 if (str[i] == tm.tmBreakChar)
1349 size->cx += breakExtra;
1350 if (breakRem > 0)
1352 breakRem--;
1353 (size->cx)++;
1360 if (lpnFit)
1361 *lpnFit = nFit;
1363 if (! alpDx)
1364 HeapFree(GetProcessHeap(), 0, dxs);
1366 DC_ReleaseDCPtr( dc );
1368 TRACE("returning %d %d x %d\n",nFit,size->cx,size->cy);
1369 return ret;
1372 /***********************************************************************
1373 * GetTextMetricsA (GDI32.@)
1375 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1377 TEXTMETRICW tm32;
1379 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1380 FONT_TextMetricWToA( &tm32, metrics );
1381 return TRUE;
1384 /***********************************************************************
1385 * GetTextMetricsW (GDI32.@)
1387 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1389 BOOL ret = FALSE;
1390 DC * dc = DC_GetDCPtr( hdc );
1391 if (!dc) return FALSE;
1393 if (dc->gdiFont)
1394 ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1395 else if (dc->funcs->pGetTextMetrics)
1396 ret = dc->funcs->pGetTextMetrics( dc->physDev, metrics );
1398 if (ret)
1400 /* device layer returns values in device units
1401 * therefore we have to convert them to logical */
1403 metrics->tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1404 metrics->tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1406 #define WDPTOLP(x) ((x<0)? \
1407 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1408 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1409 #define HDPTOLP(y) ((y<0)? \
1410 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1411 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1413 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1414 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1415 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1416 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1417 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1418 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1419 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1420 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1421 ret = TRUE;
1422 #undef WDPTOLP
1423 #undef HDPTOLP
1424 TRACE("text metrics:\n"
1425 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1426 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1427 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1428 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1429 " PitchAndFamily = %02x\n"
1430 " --------------------\n"
1431 " InternalLeading = %i\n"
1432 " Ascent = %i\n"
1433 " Descent = %i\n"
1434 " Height = %i\n",
1435 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1436 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1437 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1438 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1439 metrics->tmPitchAndFamily,
1440 metrics->tmInternalLeading,
1441 metrics->tmAscent,
1442 metrics->tmDescent,
1443 metrics->tmHeight );
1445 DC_ReleaseDCPtr( dc );
1446 return ret;
1450 /***********************************************************************
1451 * GetOutlineTextMetrics [GDI.308] Gets metrics for TrueType fonts.
1453 * NOTES
1454 * lpOTM should be LPOUTLINETEXTMETRIC
1456 * RETURNS
1457 * Success: Non-zero or size of required buffer
1458 * Failure: 0
1460 UINT16 WINAPI GetOutlineTextMetrics16(
1461 HDC16 hdc, /* [in] Handle of device context */
1462 UINT16 cbData, /* [in] Size of metric data array */
1463 LPOUTLINETEXTMETRIC16 lpOTM) /* [out] Address of metric data array */
1465 FIXME("(%04x,%04x,%p): stub\n", hdc,cbData,lpOTM);
1466 return 0;
1470 /***********************************************************************
1471 * GetOutlineTextMetricsA (GDI32.@)
1472 * Gets metrics for TrueType fonts.
1474 * NOTES
1475 * If the supplied buffer isn't big enough Windows partially fills it up to
1476 * its given length and returns that length.
1478 * RETURNS
1479 * Success: Non-zero or size of required buffer
1480 * Failure: 0
1482 UINT WINAPI GetOutlineTextMetricsA(
1483 HDC hdc, /* [in] Handle of device context */
1484 UINT cbData, /* [in] Size of metric data array */
1485 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1487 char buf[512], *ptr;
1488 UINT ret, needed;
1489 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1490 OUTLINETEXTMETRICA *output = lpOTM;
1491 INT left, len;
1493 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1494 return 0;
1495 if(ret > sizeof(buf))
1496 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1497 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1499 needed = sizeof(OUTLINETEXTMETRICA);
1500 if(lpOTMW->otmpFamilyName)
1501 needed += WideCharToMultiByte(CP_ACP, 0,
1502 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1503 NULL, 0, NULL, NULL);
1504 if(lpOTMW->otmpFaceName)
1505 needed += WideCharToMultiByte(CP_ACP, 0,
1506 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1507 NULL, 0, NULL, NULL);
1508 if(lpOTMW->otmpStyleName)
1509 needed += WideCharToMultiByte(CP_ACP, 0,
1510 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1511 NULL, 0, NULL, NULL);
1512 if(lpOTMW->otmpFullName)
1513 needed += WideCharToMultiByte(CP_ACP, 0,
1514 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1515 NULL, 0, NULL, NULL);
1517 if(!lpOTM) {
1518 ret = needed;
1519 goto end;
1522 TRACE("needed = %d\n", needed);
1523 if(needed > cbData)
1524 /* Since the supplied buffer isn't big enough, we'll alloc one
1525 that is and memcpy the first cbData bytes into the lpOTM at
1526 the end. */
1527 output = HeapAlloc(GetProcessHeap(), 0, needed);
1529 ret = output->otmSize = min(needed, cbData);
1530 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1531 output->otmFiller = 0;
1532 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1533 output->otmfsSelection = lpOTMW->otmfsSelection;
1534 output->otmfsType = lpOTMW->otmfsType;
1535 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1536 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1537 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1538 output->otmEMSquare = lpOTMW->otmEMSquare;
1539 output->otmAscent = lpOTMW->otmAscent;
1540 output->otmDescent = lpOTMW->otmDescent;
1541 output->otmLineGap = lpOTMW->otmLineGap;
1542 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1543 output->otmsXHeight = lpOTMW->otmsXHeight;
1544 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1545 output->otmMacAscent = lpOTMW->otmMacAscent;
1546 output->otmMacDescent = lpOTMW->otmMacDescent;
1547 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1548 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1549 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1550 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1551 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1552 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1553 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1554 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1555 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1556 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1559 ptr = (char*)(output + 1);
1560 left = needed - sizeof(*output);
1562 if(lpOTMW->otmpFamilyName) {
1563 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1564 len = WideCharToMultiByte(CP_ACP, 0,
1565 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1566 ptr, left, NULL, NULL);
1567 left -= len;
1568 ptr += len;
1569 } else
1570 output->otmpFamilyName = 0;
1572 if(lpOTMW->otmpFaceName) {
1573 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1574 len = WideCharToMultiByte(CP_ACP, 0,
1575 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1576 ptr, left, NULL, NULL);
1577 left -= len;
1578 ptr += len;
1579 } else
1580 output->otmpFaceName = 0;
1582 if(lpOTMW->otmpStyleName) {
1583 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1584 len = WideCharToMultiByte(CP_ACP, 0,
1585 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1586 ptr, left, NULL, NULL);
1587 left -= len;
1588 ptr += len;
1589 } else
1590 output->otmpStyleName = 0;
1592 if(lpOTMW->otmpFullName) {
1593 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1594 len = WideCharToMultiByte(CP_ACP, 0,
1595 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1596 ptr, left, NULL, NULL);
1597 left -= len;
1598 } else
1599 output->otmpFullName = 0;
1601 assert(left == 0);
1603 if(output != lpOTM) {
1604 memcpy(lpOTM, output, cbData);
1605 HeapFree(GetProcessHeap(), 0, output);
1607 /* check if the string offsets really fit into the provided size */
1608 /* FIXME: should we check string length as well? */
1609 /* make sure that we don't read/write beyond the provided buffer */
1610 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(LPSTR))
1612 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1613 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1616 /* make sure that we don't read/write beyond the provided buffer */
1617 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(LPSTR))
1619 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1620 lpOTM->otmpFaceName = 0; /* doesn't fit */
1623 /* make sure that we don't read/write beyond the provided buffer */
1624 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(LPSTR))
1626 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1627 lpOTM->otmpStyleName = 0; /* doesn't fit */
1630 /* make sure that we don't read/write beyond the provided buffer */
1631 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(LPSTR))
1633 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1634 lpOTM->otmpFullName = 0; /* doesn't fit */
1638 end:
1639 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1640 HeapFree(GetProcessHeap(), 0, lpOTMW);
1642 return ret;
1646 /***********************************************************************
1647 * GetOutlineTextMetricsW [GDI32.@]
1649 UINT WINAPI GetOutlineTextMetricsW(
1650 HDC hdc, /* [in] Handle of device context */
1651 UINT cbData, /* [in] Size of metric data array */
1652 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1654 DC *dc = DC_GetDCPtr( hdc );
1655 OUTLINETEXTMETRICW *output = lpOTM;
1656 UINT ret;
1658 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1659 if(!dc) return 0;
1661 if(dc->gdiFont) {
1662 ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, output);
1663 if(lpOTM && ret) {
1664 if(ret > cbData) {
1665 output = HeapAlloc(GetProcessHeap(), 0, ret);
1666 WineEngGetOutlineTextMetrics(dc->gdiFont, ret, output);
1669 #define WDPTOLP(x) ((x<0)? \
1670 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1671 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1672 #define HDPTOLP(y) ((y<0)? \
1673 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1674 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1676 output->otmTextMetrics.tmHeight = HDPTOLP(output->otmTextMetrics.tmHeight);
1677 output->otmTextMetrics.tmAscent = HDPTOLP(output->otmTextMetrics.tmAscent);
1678 output->otmTextMetrics.tmDescent = HDPTOLP(output->otmTextMetrics.tmDescent);
1679 output->otmTextMetrics.tmInternalLeading = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1680 output->otmTextMetrics.tmExternalLeading = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1681 output->otmTextMetrics.tmAveCharWidth = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1682 output->otmTextMetrics.tmMaxCharWidth = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1683 output->otmTextMetrics.tmOverhang = WDPTOLP(output->otmTextMetrics.tmOverhang);
1684 output->otmAscent = HDPTOLP(output->otmAscent);
1685 output->otmDescent = HDPTOLP(output->otmDescent);
1686 output->otmLineGap = HDPTOLP(output->otmLineGap);
1687 output->otmsCapEmHeight = HDPTOLP(output->otmsCapEmHeight);
1688 output->otmsXHeight = HDPTOLP(output->otmsXHeight);
1689 output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1690 output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1691 output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1692 output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1693 output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1694 output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1695 output->otmMacLineGap = HDPTOLP(output->otmMacLineGap);
1696 output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1697 output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1698 output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1699 output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1700 output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1701 output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1702 output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1703 output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1704 output->otmsStrikeoutSize = HDPTOLP(output->otmsStrikeoutSize);
1705 output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1706 output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1707 output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1708 #undef WDPTOLP
1709 #undef HDPTOLP
1710 if(output != lpOTM) {
1711 memcpy(lpOTM, output, cbData);
1712 HeapFree(GetProcessHeap(), 0, output);
1713 ret = cbData;
1718 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1719 but really this should just be a return 0. */
1721 ret = sizeof(*lpOTM);
1722 if (lpOTM) {
1723 if(cbData < ret)
1724 ret = 0;
1725 else {
1726 memset(lpOTM, 0, ret);
1727 lpOTM->otmSize = sizeof(*lpOTM);
1728 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1730 Further fill of the structure not implemented,
1731 Needs real values for the structure members
1736 DC_ReleaseDCPtr(dc);
1737 return ret;
1741 /***********************************************************************
1742 * GetCharWidthW (GDI32.@)
1743 * GetCharWidth32W (GDI32.@)
1745 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1746 LPINT buffer )
1748 UINT i;
1749 BOOL ret = FALSE;
1750 DC * dc = DC_GetDCPtr( hdc );
1751 if (!dc) return FALSE;
1753 if (dc->gdiFont)
1754 ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1755 else if (dc->funcs->pGetCharWidth)
1756 ret = dc->funcs->pGetCharWidth( dc->physDev, firstChar, lastChar, buffer);
1758 if (ret)
1760 /* convert device units to logical */
1761 for( i = firstChar; i <= lastChar; i++, buffer++ )
1762 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1763 ret = TRUE;
1765 DC_ReleaseDCPtr( dc );
1766 return ret;
1770 /***********************************************************************
1771 * GetCharWidthA (GDI32.@)
1772 * GetCharWidth32A (GDI32.@)
1774 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1775 LPINT buffer )
1777 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1778 LPSTR str;
1779 LPWSTR wstr;
1780 BOOL ret = TRUE;
1782 if(count <= 0) return FALSE;
1784 str = HeapAlloc(GetProcessHeap(), 0, count);
1785 for(i = 0; i < count; i++)
1786 str[i] = (BYTE)(firstChar + i);
1788 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1790 for(i = 0; i < wlen; i++)
1792 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1794 ret = FALSE;
1795 break;
1797 buffer++;
1800 HeapFree(GetProcessHeap(), 0, str);
1801 HeapFree(GetProcessHeap(), 0, wstr);
1803 return ret;
1807 /***********************************************************************
1808 * ExtTextOutA (GDI32.@)
1810 * See ExtTextOutW.
1812 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1813 const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1815 INT wlen;
1816 UINT codepage;
1817 LPWSTR p;
1818 BOOL ret;
1819 LPINT lpDxW = NULL;
1821 if (flags & ETO_GLYPH_INDEX)
1822 return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
1824 p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
1826 if (lpDx) {
1827 unsigned int i = 0, j = 0;
1829 lpDxW = HeapAlloc( GetProcessHeap(), 0, wlen*sizeof(INT));
1830 while(i < count) {
1831 if(IsDBCSLeadByteEx(codepage, str[i])) {
1832 lpDxW[j++] = lpDx[i] + lpDx[i+1];
1833 i = i + 2;
1834 } else {
1835 lpDxW[j++] = lpDx[i];
1836 i = i + 1;
1841 ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1843 HeapFree( GetProcessHeap(), 0, p );
1844 HeapFree( GetProcessHeap(), 0, lpDxW );
1845 return ret;
1849 /***********************************************************************
1850 * ExtTextOutW (GDI32.@)
1852 * Draws text using the currently selected font, background color, and text color.
1855 * PARAMS
1856 * x,y [I] coordinates of string
1857 * flags [I]
1858 * ETO_GRAYED - undocumented on MSDN
1859 * ETO_OPAQUE - use background color for fill the rectangle
1860 * ETO_CLIPPED - clipping text to the rectangle
1861 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1862 * than encoded characters. Implies ETO_IGNORELANGUAGE
1863 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1864 * Affects BiDi ordering
1865 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1866 * ETO_PDY - unimplemented
1867 * ETO_NUMERICSLATIN - unimplemented always assumed -
1868 * do not translate numbers into locale representations
1869 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1870 * lprect [I] dimensions for clipping or/and opaquing
1871 * str [I] text string
1872 * count [I] number of symbols in string
1873 * lpDx [I] optional parameter with distance between drawing characters
1875 * RETURNS
1876 * Success: TRUE
1877 * Failure: FALSE
1879 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1880 const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1882 BOOL ret = FALSE;
1883 LPWSTR reordered_str = (LPWSTR)str;
1884 WORD *glyphs = NULL;
1885 UINT align = GetTextAlign( hdc );
1886 POINT pt;
1887 TEXTMETRICW tm;
1888 LOGFONTW lf;
1889 double cosEsc, sinEsc;
1890 INT *deltas = NULL, char_extra;
1891 SIZE sz;
1892 RECT rc;
1893 BOOL done_extents = FALSE;
1894 INT width = 0, xwidth = 0, ywidth = 0;
1895 DWORD type;
1896 DC * dc = get_dc_ptr( hdc );
1897 INT breakRem;
1899 if (!dc) return FALSE;
1901 breakRem = dc->breakRem;
1903 if (flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY))
1904 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY unimplemented\n");
1906 if (!dc->funcs->pExtTextOut && !PATH_IsPathOpen(dc->path))
1908 release_dc_ptr( dc );
1909 return ret;
1912 update_dc( dc );
1913 type = GetObjectType(hdc);
1914 if(type == OBJ_METADC || type == OBJ_ENHMETADC)
1916 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, flags, lprect, str, count, lpDx);
1917 release_dc_ptr( dc );
1918 return ret;
1921 if (!lprect)
1922 flags &= ~ETO_CLIPPED;
1924 if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && count > 0 )
1926 reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1928 BIDI_Reorder( str, count, GCP_REORDER,
1929 ((flags&ETO_RTLREADING)!=0 || (GetTextAlign(hdc)&TA_RTLREADING)!=0)?
1930 WINE_GCPW_FORCE_RTL:WINE_GCPW_FORCE_LTR,
1931 reordered_str, count, NULL );
1933 flags |= ETO_IGNORELANGUAGE;
1936 TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc, x, y, flags,
1937 lprect, debugstr_wn(str, count), count, lpDx);
1939 if(flags & ETO_GLYPH_INDEX)
1940 glyphs = reordered_str;
1942 if(lprect)
1943 TRACE("rect: %d,%d - %d,%d\n", lprect->left, lprect->top, lprect->right,
1944 lprect->bottom);
1945 TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
1947 if(align & TA_UPDATECP)
1949 GetCurrentPositionEx( hdc, &pt );
1950 x = pt.x;
1951 y = pt.y;
1954 GetTextMetricsW(hdc, &tm);
1955 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1957 if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
1958 lf.lfEscapement = 0;
1960 if(lf.lfEscapement != 0)
1962 cosEsc = cos(lf.lfEscapement * M_PI / 1800);
1963 sinEsc = sin(lf.lfEscapement * M_PI / 1800);
1965 else
1967 cosEsc = 1;
1968 sinEsc = 0;
1971 if(flags & (ETO_CLIPPED | ETO_OPAQUE))
1973 if(!lprect)
1975 if(flags & ETO_GLYPH_INDEX)
1976 GetTextExtentPointI(hdc, glyphs, count, &sz);
1977 else
1978 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1980 done_extents = TRUE;
1981 rc.left = x;
1982 rc.top = y;
1983 rc.right = x + sz.cx;
1984 rc.bottom = y + sz.cy;
1986 else
1988 rc = *lprect;
1991 LPtoDP(hdc, (POINT*)&rc, 2);
1993 if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
1994 if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
1997 if ((flags & ETO_OPAQUE) && !PATH_IsPathOpen(dc->path))
1998 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
2000 if(count == 0)
2002 ret = TRUE;
2003 goto done;
2006 pt.x = x;
2007 pt.y = y;
2008 LPtoDP(hdc, &pt, 1);
2009 x = pt.x;
2010 y = pt.y;
2012 char_extra = GetTextCharacterExtra(hdc);
2013 if(char_extra || dc->breakExtra || breakRem || lpDx || lf.lfEscapement != 0)
2015 UINT i;
2016 SIZE tmpsz;
2017 deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT));
2018 for(i = 0; i < count; i++)
2020 if(lpDx && (flags & ETO_PDY))
2021 deltas[i] = lpDx[i*2] + char_extra;
2022 else if(lpDx)
2023 deltas[i] = lpDx[i] + char_extra;
2024 else
2026 if(flags & ETO_GLYPH_INDEX)
2027 GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
2028 else
2029 GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
2031 deltas[i] = tmpsz.cx;
2034 if (!(flags & ETO_GLYPH_INDEX) && (dc->breakExtra || breakRem) && reordered_str[i] == tm.tmBreakChar)
2036 deltas[i] = deltas[i] + dc->breakExtra;
2037 if (breakRem > 0)
2039 breakRem--;
2040 deltas[i]++;
2043 deltas[i] = INTERNAL_XWSTODS(dc, deltas[i]);
2044 width += deltas[i];
2047 else
2049 if(!done_extents)
2051 if(flags & ETO_GLYPH_INDEX)
2052 GetTextExtentPointI(hdc, glyphs, count, &sz);
2053 else
2054 GetTextExtentPointW(hdc, reordered_str, count, &sz);
2055 done_extents = TRUE;
2057 width = INTERNAL_XWSTODS(dc, sz.cx);
2059 xwidth = width * cosEsc;
2060 ywidth = width * sinEsc;
2062 tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
2063 tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
2064 switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
2066 case TA_LEFT:
2067 if (align & TA_UPDATECP)
2069 pt.x = x + xwidth;
2070 pt.y = y - ywidth;
2071 DPtoLP(hdc, &pt, 1);
2072 MoveToEx(hdc, pt.x, pt.y, NULL);
2074 break;
2076 case TA_CENTER:
2077 x -= xwidth / 2;
2078 y += ywidth / 2;
2079 break;
2081 case TA_RIGHT:
2082 x -= xwidth;
2083 y += ywidth;
2084 if (align & TA_UPDATECP)
2086 pt.x = x;
2087 pt.y = y;
2088 DPtoLP(hdc, &pt, 1);
2089 MoveToEx(hdc, pt.x, pt.y, NULL);
2091 break;
2094 switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
2096 case TA_TOP:
2097 y += tm.tmAscent * cosEsc;
2098 x += tm.tmAscent * sinEsc;
2099 break;
2101 case TA_BOTTOM:
2102 y -= tm.tmDescent * cosEsc;
2103 x -= tm.tmDescent * sinEsc;
2104 break;
2106 case TA_BASELINE:
2107 break;
2110 if (GetBkMode(hdc) != TRANSPARENT && !PATH_IsPathOpen(dc->path))
2112 if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
2114 if(!(flags & ETO_OPAQUE) || x < rc.left || x + width >= rc.right ||
2115 y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
2117 RECT rc;
2118 rc.left = x;
2119 rc.right = x + width;
2120 rc.top = y - tm.tmAscent;
2121 rc.bottom = y + tm.tmDescent;
2122 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
2127 if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
2129 HFONT orig_font = dc->hFont, cur_font;
2130 UINT glyph;
2131 INT span = 0, *offsets = NULL;
2132 unsigned int i;
2134 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2135 for(i = 0; i < count; i++)
2137 WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
2138 if(cur_font != dc->hFont)
2140 if(!offsets)
2142 unsigned int j;
2143 offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
2144 offsets[0] = 0;
2145 if(!deltas)
2147 SIZE tmpsz;
2148 for(j = 1; j < count; j++)
2150 GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
2151 offsets[j] = offsets[j-1] + INTERNAL_XWSTODS(dc, tmpsz.cx);
2154 else
2156 for(j = 1; j < count; j++)
2157 offsets[j] = offsets[j-1] + deltas[j];
2160 if(span)
2162 if (PATH_IsPathOpen(dc->path))
2163 ret = PATH_ExtTextOut(dc, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
2164 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2165 glyphs, span, deltas ? deltas + i - span : NULL);
2166 else
2167 dc->funcs->pExtTextOut(dc->physDev, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
2168 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2169 glyphs, span, deltas ? deltas + i - span : NULL);
2170 span = 0;
2172 SelectObject(hdc, cur_font);
2174 glyphs[span++] = glyph;
2176 if(i == count - 1)
2178 if (PATH_IsPathOpen(dc->path))
2179 ret = PATH_ExtTextOut(dc, x + (offsets ? offsets[count - span] * cosEsc : 0),
2180 y - (offsets ? offsets[count - span] * sinEsc : 0),
2181 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2182 glyphs, span, deltas ? deltas + count - span : NULL);
2183 else
2184 ret = dc->funcs->pExtTextOut(dc->physDev, x + (offsets ? offsets[count - span] * cosEsc : 0),
2185 y - (offsets ? offsets[count - span] * sinEsc : 0),
2186 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2187 glyphs, span, deltas ? deltas + count - span : NULL);
2188 SelectObject(hdc, orig_font);
2189 HeapFree(GetProcessHeap(), 0, offsets);
2193 else
2195 if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
2197 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2198 GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
2199 flags |= ETO_GLYPH_INDEX;
2202 if (PATH_IsPathOpen(dc->path))
2203 ret = PATH_ExtTextOut(dc, x, y, (flags & ~ETO_OPAQUE), &rc,
2204 glyphs ? glyphs : reordered_str, count, deltas);
2205 else
2206 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, (flags & ~ETO_OPAQUE), &rc,
2207 glyphs ? glyphs : reordered_str, count, deltas);
2210 done:
2211 HeapFree(GetProcessHeap(), 0, deltas);
2212 if(glyphs != reordered_str)
2213 HeapFree(GetProcessHeap(), 0, glyphs);
2214 if(reordered_str != str)
2215 HeapFree(GetProcessHeap(), 0, reordered_str);
2217 release_dc_ptr( dc );
2219 if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2221 int underlinePos, strikeoutPos;
2222 int underlineWidth, strikeoutWidth;
2223 UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2224 OUTLINETEXTMETRICW* otm = NULL;
2226 if(!size)
2228 underlinePos = 0;
2229 underlineWidth = tm.tmAscent / 20 + 1;
2230 strikeoutPos = tm.tmAscent / 2;
2231 strikeoutWidth = underlineWidth;
2233 else
2235 otm = HeapAlloc(GetProcessHeap(), 0, size);
2236 GetOutlineTextMetricsW(hdc, size, otm);
2237 underlinePos = otm->otmsUnderscorePosition;
2238 underlineWidth = otm->otmsUnderscoreSize;
2239 strikeoutPos = otm->otmsStrikeoutPosition;
2240 strikeoutWidth = otm->otmsStrikeoutSize;
2241 HeapFree(GetProcessHeap(), 0, otm);
2244 if (PATH_IsPathOpen(dc->path))
2246 POINT pts[5];
2247 HPEN hpen;
2248 HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2250 hbrush = SelectObject(hdc, hbrush);
2251 hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2253 if (lf.lfUnderline)
2255 pts[0].x = x - underlinePos * sinEsc;
2256 pts[0].y = y - underlinePos * cosEsc;
2257 pts[1].x = x + xwidth - underlinePos * sinEsc;
2258 pts[1].y = y - ywidth - underlinePos * cosEsc;
2259 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2260 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2261 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2262 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2263 pts[4].x = pts[0].x;
2264 pts[4].y = pts[0].y;
2265 DPtoLP(hdc, pts, 5);
2266 Polygon(hdc, pts, 5);
2269 if (lf.lfStrikeOut)
2271 pts[0].x = x - strikeoutPos * sinEsc;
2272 pts[0].y = y - strikeoutPos * cosEsc;
2273 pts[1].x = x + xwidth - strikeoutPos * sinEsc;
2274 pts[1].y = y - ywidth - strikeoutPos * cosEsc;
2275 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2276 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2277 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2278 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2279 pts[4].x = pts[0].x;
2280 pts[4].y = pts[0].y;
2281 DPtoLP(hdc, pts, 5);
2282 Polygon(hdc, pts, 5);
2285 SelectObject(hdc, hpen);
2286 hbrush = SelectObject(hdc, hbrush);
2287 DeleteObject(hbrush);
2289 else
2291 POINT pts[2], oldpt;
2292 HPEN hpen;
2294 if (lf.lfUnderline)
2296 hpen = CreatePen(PS_SOLID, underlineWidth, GetTextColor(hdc));
2297 hpen = SelectObject(hdc, hpen);
2298 pts[0].x = x;
2299 pts[0].y = y;
2300 pts[1].x = x + xwidth;
2301 pts[1].y = y - ywidth;
2302 DPtoLP(hdc, pts, 2);
2303 MoveToEx(hdc, pts[0].x - underlinePos * sinEsc, pts[0].y - underlinePos * cosEsc, &oldpt);
2304 LineTo(hdc, pts[1].x - underlinePos * sinEsc, pts[1].y - underlinePos * cosEsc);
2305 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2306 DeleteObject(SelectObject(hdc, hpen));
2309 if (lf.lfStrikeOut)
2311 hpen = CreatePen(PS_SOLID, strikeoutWidth, GetTextColor(hdc));
2312 hpen = SelectObject(hdc, hpen);
2313 pts[0].x = x;
2314 pts[0].y = y;
2315 pts[1].x = x + xwidth;
2316 pts[1].y = y - ywidth;
2317 DPtoLP(hdc, pts, 2);
2318 MoveToEx(hdc, pts[0].x - strikeoutPos * sinEsc, pts[0].y - strikeoutPos * cosEsc, &oldpt);
2319 LineTo(hdc, pts[1].x - strikeoutPos * sinEsc, pts[1].y - strikeoutPos * cosEsc);
2320 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2321 DeleteObject(SelectObject(hdc, hpen));
2326 return ret;
2330 /***********************************************************************
2331 * TextOutA (GDI32.@)
2333 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2335 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2339 /***********************************************************************
2340 * TextOutW (GDI32.@)
2342 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2344 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2348 /***********************************************************************
2349 * PolyTextOutA (GDI32.@)
2351 * See PolyTextOutW.
2353 BOOL WINAPI PolyTextOutA( HDC hdc, const POLYTEXTA *pptxt, INT cStrings )
2355 for (; cStrings>0; cStrings--, pptxt++)
2356 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2357 return FALSE;
2358 return TRUE;
2363 /***********************************************************************
2364 * PolyTextOutW (GDI32.@)
2366 * Draw several Strings
2368 * RETURNS
2369 * TRUE: Success.
2370 * FALSE: Failure.
2372 BOOL WINAPI PolyTextOutW( HDC hdc, const POLYTEXTW *pptxt, INT cStrings )
2374 for (; cStrings>0; cStrings--, pptxt++)
2375 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2376 return FALSE;
2377 return TRUE;
2381 /* FIXME: all following APIs ******************************************/
2384 /***********************************************************************
2385 * SetMapperFlags (GDI32.@)
2387 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
2389 DC *dc = DC_GetDCPtr( hDC );
2390 DWORD ret = 0;
2391 if(!dc) return 0;
2392 if(dc->funcs->pSetMapperFlags)
2394 ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
2395 /* FIXME: ret is just a success flag, we should return a proper value */
2397 else
2398 FIXME("(%p, 0x%08x): stub - harmless\n", hDC, dwFlag);
2399 DC_ReleaseDCPtr( dc );
2400 return ret;
2403 /***********************************************************************
2404 * GetAspectRatioFilterEx (GDI.486)
2406 BOOL16 WINAPI GetAspectRatioFilterEx16( HDC16 hdc, LPSIZE16 pAspectRatio )
2408 FIXME("(%04x, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2409 return FALSE;
2412 /***********************************************************************
2413 * GetAspectRatioFilterEx (GDI32.@)
2415 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2417 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2418 return FALSE;
2422 /***********************************************************************
2423 * GetCharABCWidthsA (GDI32.@)
2425 * See GetCharABCWidthsW.
2427 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2428 LPABC abc )
2430 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
2431 LPSTR str;
2432 LPWSTR wstr;
2433 BOOL ret = TRUE;
2435 if(count <= 0) return FALSE;
2437 str = HeapAlloc(GetProcessHeap(), 0, count);
2438 for(i = 0; i < count; i++)
2439 str[i] = (BYTE)(firstChar + i);
2441 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
2443 for(i = 0; i < wlen; i++)
2445 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2447 ret = FALSE;
2448 break;
2450 abc++;
2453 HeapFree(GetProcessHeap(), 0, str);
2454 HeapFree(GetProcessHeap(), 0, wstr);
2456 return ret;
2460 /******************************************************************************
2461 * GetCharABCWidthsW [GDI32.@]
2463 * Retrieves widths of characters in range.
2465 * PARAMS
2466 * hdc [I] Handle of device context
2467 * firstChar [I] First character in range to query
2468 * lastChar [I] Last character in range to query
2469 * abc [O] Address of character-width structure
2471 * NOTES
2472 * Only works with TrueType fonts
2474 * RETURNS
2475 * Success: TRUE
2476 * Failure: FALSE
2478 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2479 LPABC abc )
2481 DC *dc = DC_GetDCPtr(hdc);
2482 unsigned int i;
2483 BOOL ret = FALSE;
2485 if (!dc) return FALSE;
2487 if(dc->gdiFont)
2488 ret = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
2489 else
2490 FIXME(": stub\n");
2492 if (ret)
2494 /* convert device units to logical */
2495 for( i = firstChar; i <= lastChar; i++, abc++ ) {
2496 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2497 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2498 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2500 ret = TRUE;
2503 DC_ReleaseDCPtr( dc );
2504 return ret;
2508 /******************************************************************************
2509 * GetCharABCWidthsI [GDI32.@]
2511 * Retrieves widths of characters in range.
2513 * PARAMS
2514 * hdc [I] Handle of device context
2515 * firstChar [I] First glyphs in range to query
2516 * count [I] Last glyphs in range to query
2517 * pgi [i] Array of glyphs to query
2518 * abc [O] Address of character-width structure
2520 * NOTES
2521 * Only works with TrueType fonts
2523 * RETURNS
2524 * Success: TRUE
2525 * Failure: FALSE
2527 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2528 LPWORD pgi, LPABC abc)
2530 DC *dc = DC_GetDCPtr(hdc);
2531 unsigned int i;
2532 BOOL ret = FALSE;
2534 if (!dc) return FALSE;
2536 if(dc->gdiFont)
2537 ret = WineEngGetCharABCWidthsI( dc->gdiFont, firstChar, count, pgi, abc );
2538 else
2539 FIXME(": stub\n");
2541 if (ret)
2543 /* convert device units to logical */
2544 for( i = 0; i < count; i++, abc++ ) {
2545 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2546 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2547 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2549 ret = TRUE;
2552 DC_ReleaseDCPtr( dc );
2553 return ret;
2557 /***********************************************************************
2558 * GetGlyphOutlineA (GDI32.@)
2560 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2561 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2562 LPVOID lpBuffer, const MAT2 *lpmat2 )
2564 LPWSTR p = NULL;
2565 DWORD ret;
2566 UINT c;
2568 if(!(fuFormat & GGO_GLYPH_INDEX)) {
2569 int len;
2570 char mbchs[2];
2571 if(uChar > 0xff) { /* but, 2 bytes character only */
2572 len = 2;
2573 mbchs[0] = (uChar & 0xff00) >> 8;
2574 mbchs[1] = (uChar & 0xff);
2575 } else {
2576 len = 1;
2577 mbchs[0] = (uChar & 0xff);
2579 p = FONT_mbtowc(hdc, mbchs, len, NULL, NULL);
2580 c = p[0];
2581 } else
2582 c = uChar;
2583 ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
2584 lpmat2);
2585 HeapFree(GetProcessHeap(), 0, p);
2586 return ret;
2589 /***********************************************************************
2590 * GetGlyphOutlineW (GDI32.@)
2592 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2593 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2594 LPVOID lpBuffer, const MAT2 *lpmat2 )
2596 DC *dc = DC_GetDCPtr(hdc);
2597 DWORD ret;
2599 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2600 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2602 if(!dc) return GDI_ERROR;
2604 if(dc->gdiFont)
2605 ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
2606 cbBuffer, lpBuffer, lpmat2);
2607 else
2608 ret = GDI_ERROR;
2610 DC_ReleaseDCPtr( dc );
2611 return ret;
2615 /***********************************************************************
2616 * CreateScalableFontResourceA (GDI32.@)
2618 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2619 LPCSTR lpszResourceFile,
2620 LPCSTR lpszFontFile,
2621 LPCSTR lpszCurrentPath )
2623 HANDLE f;
2625 /* fHidden=1 - only visible for the calling app, read-only, not
2626 * enumbered with EnumFonts/EnumFontFamilies
2627 * lpszCurrentPath can be NULL
2629 FIXME("(%d,%s,%s,%s): stub\n",
2630 fHidden, debugstr_a(lpszResourceFile), debugstr_a(lpszFontFile),
2631 debugstr_a(lpszCurrentPath) );
2633 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2634 if ((f = CreateFileA(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2635 CloseHandle(f);
2636 SetLastError(ERROR_FILE_EXISTS);
2637 return FALSE;
2639 return FALSE; /* create failed */
2642 /***********************************************************************
2643 * CreateScalableFontResourceW (GDI32.@)
2645 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2646 LPCWSTR lpszResourceFile,
2647 LPCWSTR lpszFontFile,
2648 LPCWSTR lpszCurrentPath )
2650 FIXME("(%d,%p,%p,%p): stub\n",
2651 fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
2652 return FALSE; /* create failed */
2655 /*************************************************************************
2656 * GetKerningPairsA (GDI32.@)
2658 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2659 LPKERNINGPAIR kern_pairA )
2661 INT charset;
2662 CHARSETINFO csi;
2663 CPINFO cpi;
2664 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2665 KERNINGPAIR *kern_pairW;
2667 if (!cPairs && kern_pairA)
2669 SetLastError(ERROR_INVALID_PARAMETER);
2670 return 0;
2673 charset = GetTextCharset(hDC);
2674 if (!TranslateCharsetInfo(ULongToPtr(charset), &csi, TCI_SRCCHARSET))
2676 FIXME("Can't find codepage for charset %d\n", charset);
2677 return 0;
2679 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2680 * to fail on an invalid character for CP_SYMBOL.
2682 cpi.DefaultChar[0] = 0;
2683 if (csi.ciACP != CP_SYMBOL && !GetCPInfo(csi.ciACP, &cpi))
2685 FIXME("Can't find codepage %u info\n", csi.ciACP);
2686 return 0;
2688 TRACE("charset %d => codepage %u\n", charset, csi.ciACP);
2690 total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2691 if (!total_kern_pairs) return 0;
2693 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2694 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2696 for (i = 0; i < total_kern_pairs; i++)
2698 char first, second;
2700 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2701 continue;
2703 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2704 continue;
2706 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2707 continue;
2709 if (kern_pairA)
2711 if (kern_pairs_copied >= cPairs) break;
2713 kern_pairA->wFirst = (BYTE)first;
2714 kern_pairA->wSecond = (BYTE)second;
2715 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2716 kern_pairA++;
2718 kern_pairs_copied++;
2721 HeapFree(GetProcessHeap(), 0, kern_pairW);
2723 return kern_pairs_copied;
2726 /*************************************************************************
2727 * GetKerningPairsW (GDI32.@)
2729 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2730 LPKERNINGPAIR lpKerningPairs )
2732 DC *dc;
2733 DWORD ret = 0;
2735 TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2737 if (!cPairs && lpKerningPairs)
2739 SetLastError(ERROR_INVALID_PARAMETER);
2740 return 0;
2743 dc = DC_GetDCPtr(hDC);
2744 if (!dc) return 0;
2746 if (dc->gdiFont)
2747 ret = WineEngGetKerningPairs(dc->gdiFont, cPairs, lpKerningPairs);
2749 DC_ReleaseDCPtr( dc );
2750 return ret;
2753 /*************************************************************************
2754 * TranslateCharsetInfo [GDI32.@]
2756 * Fills a CHARSETINFO structure for a character set, code page, or
2757 * font. This allows making the correspondance between different labelings
2758 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2759 * of the same encoding.
2761 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2762 * only one codepage should be set in *lpSrc.
2764 * RETURNS
2765 * TRUE on success, FALSE on failure.
2768 BOOL WINAPI TranslateCharsetInfo(
2769 LPDWORD lpSrc, /* [in]
2770 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2771 if flags == TCI_SRCCHARSET: a character set value
2772 if flags == TCI_SRCCODEPAGE: a code page value
2774 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2775 DWORD flags /* [in] determines interpretation of lpSrc */)
2777 int index = 0;
2778 switch (flags) {
2779 case TCI_SRCFONTSIG:
2780 while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
2781 break;
2782 case TCI_SRCCODEPAGE:
2783 while (PtrToUlong(lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
2784 break;
2785 case TCI_SRCCHARSET:
2786 while (PtrToUlong(lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
2787 break;
2788 default:
2789 return FALSE;
2791 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2792 memcpy(lpCs, &FONT_tci[index], sizeof(CHARSETINFO));
2793 return TRUE;
2796 /*************************************************************************
2797 * GetFontLanguageInfo (GDI32.@)
2799 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2801 FONTSIGNATURE fontsig;
2802 static const DWORD GCP_DBCS_MASK=0x003F0000,
2803 GCP_DIACRITIC_MASK=0x00000000,
2804 FLI_GLYPHS_MASK=0x00000000,
2805 GCP_GLYPHSHAPE_MASK=0x00000040,
2806 GCP_KASHIDA_MASK=0x00000000,
2807 GCP_LIGATE_MASK=0x00000000,
2808 GCP_USEKERNING_MASK=0x00000000,
2809 GCP_REORDER_MASK=0x00000060;
2811 DWORD result=0;
2813 GetTextCharsetInfo( hdc, &fontsig, 0 );
2814 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2816 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2817 result|=GCP_DBCS;
2819 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2820 result|=GCP_DIACRITIC;
2822 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2823 result|=FLI_GLYPHS;
2825 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2826 result|=GCP_GLYPHSHAPE;
2828 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2829 result|=GCP_KASHIDA;
2831 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2832 result|=GCP_LIGATE;
2834 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2835 result|=GCP_USEKERNING;
2837 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2838 if( GetTextAlign( hdc) & TA_RTLREADING )
2839 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2840 result|=GCP_REORDER;
2842 return result;
2846 /*************************************************************************
2847 * GetFontData [GDI32.@]
2849 * Retrieve data for TrueType font.
2851 * RETURNS
2853 * success: Number of bytes returned
2854 * failure: GDI_ERROR
2856 * NOTES
2858 * Calls SetLastError()
2861 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2862 LPVOID buffer, DWORD length)
2864 DC *dc = DC_GetDCPtr(hdc);
2865 DWORD ret = GDI_ERROR;
2867 if(!dc) return GDI_ERROR;
2869 if(dc->gdiFont)
2870 ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2872 DC_ReleaseDCPtr( dc );
2873 return ret;
2876 /*************************************************************************
2877 * GetGlyphIndicesA [GDI32.@]
2879 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2880 LPWORD pgi, DWORD flags)
2882 DWORD ret;
2883 WCHAR *lpstrW;
2884 INT countW;
2886 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2887 hdc, debugstr_an(lpstr, count), count, pgi, flags);
2889 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2890 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2891 HeapFree(GetProcessHeap(), 0, lpstrW);
2893 return ret;
2896 /*************************************************************************
2897 * GetGlyphIndicesW [GDI32.@]
2899 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2900 LPWORD pgi, DWORD flags)
2902 DC *dc = DC_GetDCPtr(hdc);
2903 DWORD ret = GDI_ERROR;
2905 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2906 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2908 if(!dc) return GDI_ERROR;
2910 if(dc->gdiFont)
2911 ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2913 DC_ReleaseDCPtr( dc );
2914 return ret;
2917 /*************************************************************************
2918 * GetCharacterPlacementA [GDI32.@]
2920 * See GetCharacterPlacementW.
2922 * NOTES:
2923 * the web browser control of ie4 calls this with dwFlags=0
2925 DWORD WINAPI
2926 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2927 INT nMaxExtent, GCP_RESULTSA *lpResults,
2928 DWORD dwFlags)
2930 WCHAR *lpStringW;
2931 INT uCountW;
2932 GCP_RESULTSW resultsW;
2933 DWORD ret;
2934 UINT font_cp;
2936 TRACE("%s, %d, %d, 0x%08x\n",
2937 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2939 /* both structs are equal in size */
2940 memcpy(&resultsW, lpResults, sizeof(resultsW));
2942 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2943 if(lpResults->lpOutString)
2944 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2946 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2948 lpResults->nGlyphs = resultsW.nGlyphs;
2949 lpResults->nMaxFit = resultsW.nMaxFit;
2951 if(lpResults->lpOutString) {
2952 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2953 lpResults->lpOutString, uCount, NULL, NULL );
2956 HeapFree(GetProcessHeap(), 0, lpStringW);
2957 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2959 return ret;
2962 /*************************************************************************
2963 * GetCharacterPlacementW [GDI32.@]
2965 * Retrieve information about a string. This includes the width, reordering,
2966 * Glyphing and so on.
2968 * RETURNS
2970 * The width and height of the string if successful, 0 if failed.
2972 * BUGS
2974 * All flags except GCP_REORDER are not yet implemented.
2975 * Reordering is not 100% complient to the Windows BiDi method.
2976 * Caret positioning is not yet implemented for BiDi.
2977 * Classes are not yet implemented.
2980 DWORD WINAPI
2981 GetCharacterPlacementW(
2982 HDC hdc, /* [in] Device context for which the rendering is to be done */
2983 LPCWSTR lpString, /* [in] The string for which information is to be returned */
2984 INT uCount, /* [in] Number of WORDS in string. */
2985 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
2986 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2987 DWORD dwFlags /* [in] Flags specifying how to process the string */
2990 DWORD ret=0;
2991 SIZE size;
2992 UINT i, nSet;
2994 TRACE("%s, %d, %d, 0x%08x\n",
2995 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2997 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2998 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2999 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
3000 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
3001 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
3003 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08x ignored\n", dwFlags);
3004 if(lpResults->lpClass) FIXME("classes not implemented\n");
3005 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
3006 FIXME("Caret positions for complex scripts not implemented\n");
3008 nSet = (UINT)uCount;
3009 if(nSet > lpResults->nGlyphs)
3010 nSet = lpResults->nGlyphs;
3012 /* return number of initialized fields */
3013 lpResults->nGlyphs = nSet;
3015 if((dwFlags&GCP_REORDER)==0 )
3017 /* Treat the case where no special handling was requested in a fastpath way */
3018 /* copy will do if the GCP_REORDER flag is not set */
3019 if(lpResults->lpOutString)
3020 memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
3022 if(lpResults->lpOrder)
3024 for(i = 0; i < nSet; i++)
3025 lpResults->lpOrder[i] = i;
3027 } else
3029 BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
3030 nSet, lpResults->lpOrder );
3033 /* FIXME: Will use the placement chars */
3034 if (lpResults->lpDx)
3036 int c;
3037 for (i = 0; i < nSet; i++)
3039 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
3040 lpResults->lpDx[i]= c;
3044 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
3046 int pos = 0;
3048 lpResults->lpCaretPos[0] = 0;
3049 for (i = 1; i < nSet; i++)
3050 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
3051 lpResults->lpCaretPos[i] = (pos += size.cx);
3054 if(lpResults->lpGlyphs)
3055 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
3057 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
3058 ret = MAKELONG(size.cx, size.cy);
3060 return ret;
3063 /*************************************************************************
3064 * GetCharABCWidthsFloatA [GDI32.@]
3066 * See GetCharABCWidthsFloatW.
3068 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3070 INT i, wlen, count = (INT)(last - first + 1);
3071 LPSTR str;
3072 LPWSTR wstr;
3073 BOOL ret = TRUE;
3075 if (count <= 0) return FALSE;
3077 str = HeapAlloc(GetProcessHeap(), 0, count);
3079 for(i = 0; i < count; i++)
3080 str[i] = (BYTE)(first + i);
3082 wstr = FONT_mbtowc( hdc, str, count, &wlen, NULL );
3084 for (i = 0; i < wlen; i++)
3086 if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
3088 ret = FALSE;
3089 break;
3091 abcf++;
3094 HeapFree( GetProcessHeap(), 0, str );
3095 HeapFree( GetProcessHeap(), 0, wstr );
3097 return ret;
3100 /*************************************************************************
3101 * GetCharABCWidthsFloatW [GDI32.@]
3103 * Retrieves widths of a range of characters.
3105 * PARAMS
3106 * hdc [I] Handle to device context.
3107 * first [I] First character in range to query.
3108 * last [I] Last character in range to query.
3109 * abcf [O] Array of LPABCFLOAT structures.
3111 * RETURNS
3112 * Success: TRUE
3113 * Failure: FALSE
3115 * BUGS
3116 * Only works with TrueType fonts. It also doesn't return real
3117 * floats but converted integers because it's implemented on
3118 * top of GetCharABCWidthsW.
3120 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3122 ABC *abc;
3123 unsigned int i, size = sizeof(ABC) * (last - first + 1);
3124 BOOL ret;
3126 TRACE("%p, %d, %d, %p - partial stub\n", hdc, first, last, abcf);
3128 abc = HeapAlloc( GetProcessHeap(), 0, size );
3129 if (!abc) return FALSE;
3131 ret = GetCharABCWidthsW( hdc, first, last, abc );
3132 if (ret)
3134 for (i = first; i <= last; i++, abc++, abcf++)
3136 abcf->abcfA = abc->abcA;
3137 abcf->abcfB = abc->abcB;
3138 abcf->abcfC = abc->abcC;
3141 HeapFree( GetProcessHeap(), 0, abc );
3142 return ret;
3145 /*************************************************************************
3146 * GetCharWidthFloatA [GDI32.@]
3148 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
3149 UINT iLastChar, PFLOAT pxBuffer)
3151 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3152 return 0;
3155 /*************************************************************************
3156 * GetCharWidthFloatW [GDI32.@]
3158 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
3159 UINT iLastChar, PFLOAT pxBuffer)
3161 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3162 return 0;
3166 /***********************************************************************
3168 * Font Resource API *
3170 ***********************************************************************/
3172 /***********************************************************************
3173 * AddFontResourceA (GDI32.@)
3175 INT WINAPI AddFontResourceA( LPCSTR str )
3177 return AddFontResourceExA( str, 0, NULL);
3180 /***********************************************************************
3181 * AddFontResourceW (GDI32.@)
3183 INT WINAPI AddFontResourceW( LPCWSTR str )
3185 return AddFontResourceExW(str, 0, NULL);
3189 /***********************************************************************
3190 * AddFontResourceExA (GDI32.@)
3192 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3194 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3195 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3196 INT ret;
3198 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3199 ret = AddFontResourceExW(strW, fl, pdv);
3200 HeapFree(GetProcessHeap(), 0, strW);
3201 return ret;
3204 static BOOL CALLBACK load_enumed_resource(HMODULE hModule, LPCWSTR type, LPWSTR name, LONG_PTR lParam)
3206 HRSRC rsrc = FindResourceW(hModule, name, type);
3207 HGLOBAL hMem = LoadResource(hModule, rsrc);
3208 LPVOID *pMem = LockResource(hMem);
3209 int *num_total = (int *)lParam;
3210 DWORD num_in_res;
3212 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type));
3213 if (!AddFontMemResourceEx(pMem, SizeofResource(hModule, rsrc), NULL, &num_in_res))
3215 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule, hMem);
3216 return FALSE;
3219 *num_total += num_in_res;
3220 return TRUE;
3223 /***********************************************************************
3224 * AddFontResourceExW (GDI32.@)
3226 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3228 int ret = WineEngAddFontResourceEx(str, fl, pdv);
3229 if (ret == 0)
3231 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3232 HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
3233 if (hModule != NULL)
3235 int num_resources = 0;
3236 LPWSTR rt_font = (LPWSTR)((ULONG_PTR)8); /* we don't want to include winuser.h */
3238 TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3239 wine_dbgstr_w(str));
3240 if (EnumResourceNamesW(hModule, rt_font, load_enumed_resource, (LONG_PTR)&num_resources))
3241 ret = num_resources;
3242 FreeLibrary(hModule);
3245 return ret;
3248 /***********************************************************************
3249 * RemoveFontResourceA (GDI32.@)
3251 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3253 return RemoveFontResourceExA(str, 0, 0);
3256 /***********************************************************************
3257 * RemoveFontResourceW (GDI32.@)
3259 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3261 return RemoveFontResourceExW(str, 0, 0);
3264 /***********************************************************************
3265 * AddFontMemResourceEx (GDI32.@)
3267 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3269 return WineEngAddFontMemResourceEx(pbFont, cbFont, pdv, pcFonts);
3272 /***********************************************************************
3273 * RemoveFontResourceExA (GDI32.@)
3275 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3277 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3278 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3279 INT ret;
3281 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3282 ret = RemoveFontResourceExW(strW, fl, pdv);
3283 HeapFree(GetProcessHeap(), 0, strW);
3284 return ret;
3287 /***********************************************************************
3288 * RemoveFontResourceExW (GDI32.@)
3290 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3292 return WineEngRemoveFontResourceEx(str, fl, pdv);
3295 /***********************************************************************
3296 * GetTextCharset (GDI32.@)
3298 UINT WINAPI GetTextCharset(HDC hdc)
3300 /* MSDN docs say this is equivalent */
3301 return GetTextCharsetInfo(hdc, NULL, 0);
3304 /***********************************************************************
3305 * GetTextCharsetInfo (GDI32.@)
3307 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3309 UINT ret = DEFAULT_CHARSET;
3310 DC *dc = DC_GetDCPtr(hdc);
3312 if (dc)
3314 if (dc->gdiFont)
3315 ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
3317 DC_ReleaseDCPtr( dc );
3320 if (ret == DEFAULT_CHARSET && fs)
3321 memset(fs, 0, sizeof(FONTSIGNATURE));
3322 return ret;
3325 /***********************************************************************
3326 * GdiGetCharDimensions (GDI32.@)
3328 * Gets the average width of the characters in the English alphabet.
3330 * PARAMS
3331 * hdc [I] Handle to the device context to measure on.
3332 * lptm [O] Pointer to memory to store the text metrics into.
3333 * height [O] On exit, the maximum height of characters in the English alphabet.
3335 * RETURNS
3336 * The average width of characters in the English alphabet.
3338 * NOTES
3339 * This function is used by the dialog manager to get the size of a dialog
3340 * unit. It should also be used by other pieces of code that need to know
3341 * the size of a dialog unit in logical units without having access to the
3342 * window handle of the dialog.
3343 * Windows caches the font metrics from this function, but we don't and
3344 * there doesn't appear to be an immediate advantage to do so.
3346 * SEE ALSO
3347 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3349 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3351 SIZE sz;
3352 static const WCHAR alphabet[] = {
3353 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3354 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3355 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3357 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3359 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3361 if (height) *height = sz.cy;
3362 return (sz.cx / 26 + 1) / 2;
3365 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3367 FIXME("(%d): stub\n", fEnableEUDC);
3368 return FALSE;
3371 /***********************************************************************
3372 * GetCharWidthI (GDI32.@)
3374 * Retrieve widths of characters.
3376 * PARAMS
3377 * hdc [I] Handle to a device context.
3378 * first [I] First glyph in range to query.
3379 * count [I] Number of glyph indices to query.
3380 * glyphs [I] Array of glyphs to query.
3381 * buffer [O] Buffer to receive character widths.
3383 * NOTES
3384 * Only works with TrueType fonts.
3386 * RETURNS
3387 * Success: TRUE
3388 * Failure: FALSE
3390 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3392 ABC *abc;
3393 unsigned int i;
3395 TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3397 if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3398 return FALSE;
3400 if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3402 HeapFree(GetProcessHeap(), 0, abc);
3403 return FALSE;
3406 for (i = 0; i < count; i++)
3407 buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3409 HeapFree(GetProcessHeap(), 0, abc);
3410 return TRUE;
3413 /***********************************************************************
3414 * GetFontUnicodeRanges (GDI32.@)
3416 * Retrieve a list of supported Unicode characters in a font.
3418 * PARAMS
3419 * hdc [I] Handle to a device context.
3420 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3422 * RETURNS
3423 * Success: Number of bytes written to the buffer pointed to by lpgs.
3424 * Failure: 0
3427 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3429 DWORD ret = 0;
3430 DC *dc = DC_GetDCPtr(hdc);
3432 TRACE("(%p, %p)\n", hdc, lpgs);
3434 if (!dc) return 0;
3436 if (dc->gdiFont) ret = WineEngGetFontUnicodeRanges(dc->gdiFont, lpgs);
3437 DC_ReleaseDCPtr(dc);
3438 return ret;
3442 /*************************************************************
3443 * FontIsLinked (GDI32.@)
3445 BOOL WINAPI FontIsLinked(HDC hdc)
3447 DC *dc = DC_GetDCPtr(hdc);
3448 BOOL ret = FALSE;
3450 if (!dc) return FALSE;
3451 if (dc->gdiFont) ret = WineEngFontIsLinked(dc->gdiFont);
3452 DC_ReleaseDCPtr(dc);
3453 TRACE("returning %d\n", ret);
3454 return ret;