jscript: Removed no longer needed caller argument from jsdisp_get_idx.
[wine.git] / dlls / gdi32 / font.c
blob4191904d12011bca039a7b3db3ee727822099ab4
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 <limits.h>
27 #include <stdarg.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <assert.h>
31 #include "winerror.h"
32 #include "windef.h"
33 #include "winbase.h"
34 #include "winnls.h"
35 #include "winternl.h"
36 #include "gdi_private.h"
37 #include "wine/exception.h"
38 #include "wine/unicode.h"
39 #include "wine/debug.h"
41 #ifdef WORDS_BIGENDIAN
42 #define get_be_word(x) (x)
43 #else
44 #define get_be_word(x) RtlUshortByteSwap(x)
45 #endif
47 WINE_DEFAULT_DEBUG_CHANNEL(font);
49 /* Device -> World size conversion */
51 /* Performs a device to world transformation on the specified width (which
52 * is in integer format).
54 static inline INT INTERNAL_XDSTOWS(DC *dc, INT width)
56 double floatWidth;
58 /* Perform operation with floating point */
59 floatWidth = (double)width * dc->xformVport2World.eM11;
60 /* Round to integers */
61 return GDI_ROUND(floatWidth);
64 /* Performs a device to world transformation on the specified size (which
65 * is in integer format).
67 static inline INT INTERNAL_YDSTOWS(DC *dc, INT height)
69 double floatHeight;
71 /* Perform operation with floating point */
72 floatHeight = (double)height * dc->xformVport2World.eM22;
73 /* Round to integers */
74 return GDI_ROUND(floatHeight);
77 static inline INT INTERNAL_XWSTODS(DC *dc, INT width)
79 POINT pt[2];
80 pt[0].x = pt[0].y = 0;
81 pt[1].x = width;
82 pt[1].y = 0;
83 LPtoDP(dc->hSelf, pt, 2);
84 return pt[1].x - pt[0].x;
87 static inline INT INTERNAL_YWSTODS(DC *dc, INT height)
89 POINT pt[2];
90 pt[0].x = pt[0].y = 0;
91 pt[1].x = 0;
92 pt[1].y = height;
93 LPtoDP(dc->hSelf, pt, 2);
94 return pt[1].y - pt[0].y;
97 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc );
98 static INT FONT_GetObjectA( HGDIOBJ handle, INT count, LPVOID buffer );
99 static INT FONT_GetObjectW( HGDIOBJ handle, INT count, LPVOID buffer );
100 static BOOL FONT_DeleteObject( HGDIOBJ handle );
102 static const struct gdi_obj_funcs font_funcs =
104 FONT_SelectObject, /* pSelectObject */
105 FONT_GetObjectA, /* pGetObjectA */
106 FONT_GetObjectW, /* pGetObjectW */
107 NULL, /* pUnrealizeObject */
108 FONT_DeleteObject /* pDeleteObject */
111 typedef struct
113 GDIOBJHDR header;
114 LOGFONTW logfont;
115 } FONTOBJ;
117 struct font_enum
119 LPLOGFONTW lpLogFontParam;
120 FONTENUMPROCW lpEnumFunc;
121 LPARAM lpData;
122 BOOL unicode;
123 HDC hdc;
127 * For TranslateCharsetInfo
129 #define MAXTCIINDEX 32
130 static const CHARSETINFO FONT_tci[MAXTCIINDEX] = {
131 /* ANSI */
132 { ANSI_CHARSET, 1252, {{0,0,0,0},{FS_LATIN1,0}} },
133 { EASTEUROPE_CHARSET, 1250, {{0,0,0,0},{FS_LATIN2,0}} },
134 { RUSSIAN_CHARSET, 1251, {{0,0,0,0},{FS_CYRILLIC,0}} },
135 { GREEK_CHARSET, 1253, {{0,0,0,0},{FS_GREEK,0}} },
136 { TURKISH_CHARSET, 1254, {{0,0,0,0},{FS_TURKISH,0}} },
137 { HEBREW_CHARSET, 1255, {{0,0,0,0},{FS_HEBREW,0}} },
138 { ARABIC_CHARSET, 1256, {{0,0,0,0},{FS_ARABIC,0}} },
139 { BALTIC_CHARSET, 1257, {{0,0,0,0},{FS_BALTIC,0}} },
140 { VIETNAMESE_CHARSET, 1258, {{0,0,0,0},{FS_VIETNAMESE,0}} },
141 /* reserved by ANSI */
142 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
143 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
144 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
145 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
146 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
147 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
148 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
149 /* ANSI and OEM */
150 { THAI_CHARSET, 874, {{0,0,0,0},{FS_THAI,0}} },
151 { SHIFTJIS_CHARSET, 932, {{0,0,0,0},{FS_JISJAPAN,0}} },
152 { GB2312_CHARSET, 936, {{0,0,0,0},{FS_CHINESESIMP,0}} },
153 { HANGEUL_CHARSET, 949, {{0,0,0,0},{FS_WANSUNG,0}} },
154 { CHINESEBIG5_CHARSET, 950, {{0,0,0,0},{FS_CHINESETRAD,0}} },
155 { JOHAB_CHARSET, 1361, {{0,0,0,0},{FS_JOHAB,0}} },
156 /* reserved for alternate ANSI and OEM */
157 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
158 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
159 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
160 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
161 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
162 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
163 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
164 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
165 /* reserved for system */
166 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
167 { SYMBOL_CHARSET, CP_SYMBOL, {{0,0,0,0},{FS_SYMBOL,0}} }
170 static void FONT_LogFontAToW( const LOGFONTA *fontA, LPLOGFONTW fontW )
172 memcpy(fontW, fontA, sizeof(LOGFONTA) - LF_FACESIZE);
173 MultiByteToWideChar(CP_ACP, 0, fontA->lfFaceName, -1, fontW->lfFaceName,
174 LF_FACESIZE);
175 fontW->lfFaceName[LF_FACESIZE-1] = 0;
178 static void FONT_LogFontWToA( const LOGFONTW *fontW, LPLOGFONTA fontA )
180 memcpy(fontA, fontW, sizeof(LOGFONTA) - LF_FACESIZE);
181 WideCharToMultiByte(CP_ACP, 0, fontW->lfFaceName, -1, fontA->lfFaceName,
182 LF_FACESIZE, NULL, NULL);
183 fontA->lfFaceName[LF_FACESIZE-1] = 0;
186 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEXA fontA )
188 FONT_LogFontWToA( &fontW->elfLogFont, &fontA->elfLogFont );
190 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
191 (LPSTR) fontA->elfFullName, LF_FULLFACESIZE, NULL, NULL );
192 fontA->elfFullName[LF_FULLFACESIZE-1] = '\0';
193 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
194 (LPSTR) fontA->elfStyle, LF_FACESIZE, NULL, NULL );
195 fontA->elfStyle[LF_FACESIZE-1] = '\0';
196 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
197 (LPSTR) fontA->elfScript, LF_FACESIZE, NULL, NULL );
198 fontA->elfScript[LF_FACESIZE-1] = '\0';
201 static void FONT_EnumLogFontExAToW( const ENUMLOGFONTEXA *fontA, LPENUMLOGFONTEXW fontW )
203 FONT_LogFontAToW( &fontA->elfLogFont, &fontW->elfLogFont );
205 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfFullName, -1,
206 fontW->elfFullName, LF_FULLFACESIZE );
207 fontW->elfFullName[LF_FULLFACESIZE-1] = '\0';
208 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfStyle, -1,
209 fontW->elfStyle, LF_FACESIZE );
210 fontW->elfStyle[LF_FACESIZE-1] = '\0';
211 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfScript, -1,
212 fontW->elfScript, LF_FACESIZE );
213 fontW->elfScript[LF_FACESIZE-1] = '\0';
216 /***********************************************************************
217 * TEXTMETRIC conversion functions.
219 static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
221 ptmA->tmHeight = ptmW->tmHeight;
222 ptmA->tmAscent = ptmW->tmAscent;
223 ptmA->tmDescent = ptmW->tmDescent;
224 ptmA->tmInternalLeading = ptmW->tmInternalLeading;
225 ptmA->tmExternalLeading = ptmW->tmExternalLeading;
226 ptmA->tmAveCharWidth = ptmW->tmAveCharWidth;
227 ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth;
228 ptmA->tmWeight = ptmW->tmWeight;
229 ptmA->tmOverhang = ptmW->tmOverhang;
230 ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX;
231 ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
232 ptmA->tmFirstChar = min(ptmW->tmFirstChar, 255);
233 if (ptmW->tmCharSet == SYMBOL_CHARSET)
235 ptmA->tmFirstChar = 0x1e;
236 ptmA->tmLastChar = 0xff; /* win9x behaviour - we need the OS2 table data to calculate correctly */
238 else if (ptmW->tmPitchAndFamily & TMPF_TRUETYPE)
240 ptmA->tmFirstChar = ptmW->tmDefaultChar - 1;
241 ptmA->tmLastChar = min(ptmW->tmLastChar, 0xff);
243 else
245 ptmA->tmFirstChar = min(ptmW->tmFirstChar, 0xff);
246 ptmA->tmLastChar = min(ptmW->tmLastChar, 0xff);
248 ptmA->tmDefaultChar = ptmW->tmDefaultChar;
249 ptmA->tmBreakChar = ptmW->tmBreakChar;
250 ptmA->tmItalic = ptmW->tmItalic;
251 ptmA->tmUnderlined = ptmW->tmUnderlined;
252 ptmA->tmStruckOut = ptmW->tmStruckOut;
253 ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
254 ptmA->tmCharSet = ptmW->tmCharSet;
258 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW *ptmW, NEWTEXTMETRICEXA *ptmA )
260 FONT_TextMetricWToA((const TEXTMETRICW *)ptmW, (LPTEXTMETRICA)ptmA);
261 ptmA->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
262 ptmA->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
263 ptmA->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
264 ptmA->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
265 memcpy(&ptmA->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
268 static DWORD get_font_ppem( HDC hdc )
270 TEXTMETRICW tm;
271 DWORD ppem;
272 DC *dc = get_dc_ptr( hdc );
274 if (!dc) return GDI_ERROR;
276 GetTextMetricsW( hdc, &tm );
277 ppem = abs( INTERNAL_YWSTODS( dc, tm.tmAscent + tm.tmDescent - tm.tmInternalLeading ) );
278 release_dc_ptr( dc );
279 return ppem;
282 #define GASP_GRIDFIT 0x01
283 #define GASP_DOGRAY 0x02
285 static BOOL get_gasp_flags( HDC hdc, WORD *flags )
287 DWORD size, gasp_tag = 0x70736167;
288 WORD buf[16]; /* Enough for seven ranges before we need to alloc */
289 WORD *alloced = NULL, *ptr = buf;
290 WORD num_recs, version;
291 DWORD ppem = get_font_ppem( hdc );
292 BOOL ret = FALSE;
294 *flags = 0;
295 if (ppem == GDI_ERROR) return FALSE;
297 size = GetFontData( hdc, gasp_tag, 0, NULL, 0 );
298 if (size == GDI_ERROR) return FALSE;
299 if (size < 4 * sizeof(WORD)) return FALSE;
300 if (size > sizeof(buf))
302 ptr = alloced = HeapAlloc( GetProcessHeap(), 0, size );
303 if (!ptr) return FALSE;
306 GetFontData( hdc, gasp_tag, 0, ptr, size );
308 version = get_be_word( *ptr++ );
309 num_recs = get_be_word( *ptr++ );
311 if (version > 1 || size < (num_recs * 2 + 2) * sizeof(WORD))
313 FIXME( "Unsupported gasp table: ver %d size %d recs %d\n", version, size, num_recs );
314 goto done;
317 while (num_recs--)
319 *flags = get_be_word( *(ptr + 1) );
320 if (ppem <= get_be_word( *ptr )) break;
321 ptr += 2;
323 TRACE( "got flags %04x for ppem %d\n", *flags, ppem );
324 ret = TRUE;
326 done:
327 HeapFree( GetProcessHeap(), 0, alloced );
328 return ret;
331 UINT get_font_aa_flags( HDC hdc )
333 LOGFONTW lf;
334 WORD gasp_flags;
336 if (GetObjectType( hdc ) == OBJ_MEMDC)
338 BITMAP bm;
339 GetObjectW( GetCurrentObject( hdc, OBJ_BITMAP ), sizeof(bm), &bm );
340 if (bm.bmBitsPixel <= 8) return GGO_BITMAP;
342 else if (GetDeviceCaps( hdc, BITSPIXEL ) <= 8) return GGO_BITMAP;
344 GetObjectW( GetCurrentObject( hdc, OBJ_FONT ), sizeof(lf), &lf );
345 if (lf.lfQuality == NONANTIALIASED_QUALITY) return GGO_BITMAP;
347 if (get_gasp_flags( hdc, &gasp_flags ) && !(gasp_flags & GASP_DOGRAY))
348 return GGO_BITMAP;
350 /* FIXME, check user prefs */
351 return GGO_GRAY4_BITMAP;
354 /***********************************************************************
355 * GdiGetCodePage (GDI32.@)
357 DWORD WINAPI GdiGetCodePage( HDC hdc )
359 UINT cp = CP_ACP;
360 DC *dc = get_dc_ptr( hdc );
362 if (dc)
364 cp = dc->font_code_page;
365 release_dc_ptr( dc );
367 return cp;
370 /***********************************************************************
371 * FONT_mbtowc
373 * Returns a Unicode translation of str using the charset of the
374 * currently selected font in hdc. If count is -1 then str is assumed
375 * to be '\0' terminated, otherwise it contains the number of bytes to
376 * convert. If plenW is non-NULL, on return it will point to the
377 * number of WCHARs that have been written. If pCP is non-NULL, on
378 * return it will point to the codepage used in the conversion. The
379 * caller should free the returned LPWSTR from the process heap
380 * itself.
382 static LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
384 UINT cp;
385 INT lenW;
386 LPWSTR strW;
388 cp = GdiGetCodePage( hdc );
390 if(count == -1) count = strlen(str);
391 lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
392 strW = HeapAlloc(GetProcessHeap(), 0, lenW*sizeof(WCHAR));
393 MultiByteToWideChar(cp, 0, str, count, strW, lenW);
394 TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW));
395 if(plenW) *plenW = lenW;
396 if(pCP) *pCP = cp;
397 return strW;
400 /***********************************************************************
401 * CreateFontIndirectExA (GDI32.@)
403 HFONT WINAPI CreateFontIndirectExA( const ENUMLOGFONTEXDVA *penumexA )
405 ENUMLOGFONTEXDVW enumexW;
407 if (!penumexA) return 0;
409 FONT_EnumLogFontExAToW( &penumexA->elfEnumLogfontEx, &enumexW.elfEnumLogfontEx );
410 enumexW.elfDesignVector = penumexA->elfDesignVector;
411 return CreateFontIndirectExW( &enumexW );
414 /***********************************************************************
415 * CreateFontIndirectExW (GDI32.@)
417 HFONT WINAPI CreateFontIndirectExW( const ENUMLOGFONTEXDVW *penumex )
419 HFONT hFont;
420 FONTOBJ *fontPtr;
421 const LOGFONTW *plf;
423 if (!penumex) return 0;
425 if (penumex->elfEnumLogfontEx.elfFullName[0] ||
426 penumex->elfEnumLogfontEx.elfStyle[0] ||
427 penumex->elfEnumLogfontEx.elfScript[0])
429 FIXME("some fields ignored. fullname=%s, style=%s, script=%s\n",
430 debugstr_w(penumex->elfEnumLogfontEx.elfFullName),
431 debugstr_w(penumex->elfEnumLogfontEx.elfStyle),
432 debugstr_w(penumex->elfEnumLogfontEx.elfScript));
435 plf = &penumex->elfEnumLogfontEx.elfLogFont;
436 if (!(fontPtr = HeapAlloc( GetProcessHeap(), 0, sizeof(*fontPtr) ))) return 0;
438 fontPtr->logfont = *plf;
440 if (plf->lfEscapement != plf->lfOrientation)
442 /* this should really depend on whether GM_ADVANCED is set */
443 fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
444 WARN("orientation angle %f set to "
445 "escapement angle %f for new font %p\n",
446 plf->lfOrientation/10., plf->lfEscapement/10., fontPtr);
449 if (!(hFont = alloc_gdi_handle( &fontPtr->header, OBJ_FONT, &font_funcs )))
451 HeapFree( GetProcessHeap(), 0, fontPtr );
452 return 0;
455 TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
456 plf->lfHeight, plf->lfWidth,
457 plf->lfEscapement, plf->lfOrientation,
458 plf->lfPitchAndFamily,
459 plf->lfOutPrecision, plf->lfClipPrecision,
460 plf->lfQuality, plf->lfCharSet,
461 debugstr_w(plf->lfFaceName),
462 plf->lfWeight > 400 ? "Bold" : "",
463 plf->lfItalic ? "Italic" : "",
464 plf->lfUnderline ? "Underline" : "", hFont);
466 return hFont;
469 /***********************************************************************
470 * CreateFontIndirectA (GDI32.@)
472 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *plfA )
474 LOGFONTW lfW;
476 if (!plfA) return 0;
478 FONT_LogFontAToW( plfA, &lfW );
479 return CreateFontIndirectW( &lfW );
482 /***********************************************************************
483 * CreateFontIndirectW (GDI32.@)
485 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
487 ENUMLOGFONTEXDVW exdv;
489 if (!plf) return 0;
491 exdv.elfEnumLogfontEx.elfLogFont = *plf;
492 exdv.elfEnumLogfontEx.elfFullName[0] = 0;
493 exdv.elfEnumLogfontEx.elfStyle[0] = 0;
494 exdv.elfEnumLogfontEx.elfScript[0] = 0;
495 return CreateFontIndirectExW( &exdv );
498 /*************************************************************************
499 * CreateFontA (GDI32.@)
501 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
502 INT orient, INT weight, DWORD italic,
503 DWORD underline, DWORD strikeout, DWORD charset,
504 DWORD outpres, DWORD clippres, DWORD quality,
505 DWORD pitch, LPCSTR name )
507 LOGFONTA logfont;
509 logfont.lfHeight = height;
510 logfont.lfWidth = width;
511 logfont.lfEscapement = esc;
512 logfont.lfOrientation = orient;
513 logfont.lfWeight = weight;
514 logfont.lfItalic = italic;
515 logfont.lfUnderline = underline;
516 logfont.lfStrikeOut = strikeout;
517 logfont.lfCharSet = charset;
518 logfont.lfOutPrecision = outpres;
519 logfont.lfClipPrecision = clippres;
520 logfont.lfQuality = quality;
521 logfont.lfPitchAndFamily = pitch;
523 if (name)
524 lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
525 else
526 logfont.lfFaceName[0] = '\0';
528 return CreateFontIndirectA( &logfont );
531 /*************************************************************************
532 * CreateFontW (GDI32.@)
534 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
535 INT orient, INT weight, DWORD italic,
536 DWORD underline, DWORD strikeout, DWORD charset,
537 DWORD outpres, DWORD clippres, DWORD quality,
538 DWORD pitch, LPCWSTR name )
540 LOGFONTW logfont;
542 logfont.lfHeight = height;
543 logfont.lfWidth = width;
544 logfont.lfEscapement = esc;
545 logfont.lfOrientation = orient;
546 logfont.lfWeight = weight;
547 logfont.lfItalic = italic;
548 logfont.lfUnderline = underline;
549 logfont.lfStrikeOut = strikeout;
550 logfont.lfCharSet = charset;
551 logfont.lfOutPrecision = outpres;
552 logfont.lfClipPrecision = clippres;
553 logfont.lfQuality = quality;
554 logfont.lfPitchAndFamily = pitch;
556 if (name)
557 lstrcpynW(logfont.lfFaceName, name,
558 sizeof(logfont.lfFaceName) / sizeof(WCHAR));
559 else
560 logfont.lfFaceName[0] = '\0';
562 return CreateFontIndirectW( &logfont );
565 static void update_font_code_page( DC *dc )
567 CHARSETINFO csi;
568 int charset = GetTextCharsetInfo( dc->hSelf, NULL, 0 );
570 /* Hmm, nicely designed api this one! */
571 if (TranslateCharsetInfo( ULongToPtr(charset), &csi, TCI_SRCCHARSET) )
572 dc->font_code_page = csi.ciACP;
573 else {
574 switch(charset) {
575 case OEM_CHARSET:
576 dc->font_code_page = GetOEMCP();
577 break;
578 case DEFAULT_CHARSET:
579 dc->font_code_page = GetACP();
580 break;
582 case VISCII_CHARSET:
583 case TCVN_CHARSET:
584 case KOI8_CHARSET:
585 case ISO3_CHARSET:
586 case ISO4_CHARSET:
587 case ISO10_CHARSET:
588 case CELTIC_CHARSET:
589 /* FIXME: These have no place here, but because x11drv
590 enumerates fonts with these (made up) charsets some apps
591 might use them and then the FIXME below would become
592 annoying. Now we could pick the intended codepage for
593 each of these, but since it's broken anyway we'll just
594 use CP_ACP and hope it'll go away...
596 dc->font_code_page = CP_ACP;
597 break;
599 default:
600 FIXME("Can't find codepage for charset %d\n", charset);
601 dc->font_code_page = CP_ACP;
602 break;
606 TRACE("charset %d => cp %d\n", charset, dc->font_code_page);
609 /***********************************************************************
610 * FONT_SelectObject
612 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc )
614 HGDIOBJ ret = 0;
615 DC *dc = get_dc_ptr( hdc );
616 PHYSDEV physdev;
618 if (!dc) return 0;
620 if (!GDI_inc_ref_count( handle ))
622 release_dc_ptr( dc );
623 return 0;
626 physdev = GET_DC_PHYSDEV( dc, pSelectFont );
627 if (physdev->funcs->pSelectFont( physdev, handle ))
629 ret = dc->hFont;
630 dc->hFont = handle;
631 update_font_code_page( dc );
632 GDI_dec_ref_count( ret );
634 else GDI_dec_ref_count( handle );
636 release_dc_ptr( dc );
637 return ret;
641 /***********************************************************************
642 * FONT_GetObjectA
644 static INT FONT_GetObjectA( HGDIOBJ handle, INT count, LPVOID buffer )
646 FONTOBJ *font = GDI_GetObjPtr( handle, OBJ_FONT );
647 LOGFONTA lfA;
649 if (!font) return 0;
650 if (buffer)
652 FONT_LogFontWToA( &font->logfont, &lfA );
653 if (count > sizeof(lfA)) count = sizeof(lfA);
654 memcpy( buffer, &lfA, count );
656 else count = sizeof(lfA);
657 GDI_ReleaseObj( handle );
658 return count;
661 /***********************************************************************
662 * FONT_GetObjectW
664 static INT FONT_GetObjectW( HGDIOBJ handle, INT count, LPVOID buffer )
666 FONTOBJ *font = GDI_GetObjPtr( handle, OBJ_FONT );
668 if (!font) return 0;
669 if (buffer)
671 if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
672 memcpy( buffer, &font->logfont, count );
674 else count = sizeof(LOGFONTW);
675 GDI_ReleaseObj( handle );
676 return count;
680 /***********************************************************************
681 * FONT_DeleteObject
683 static BOOL FONT_DeleteObject( HGDIOBJ handle )
685 FONTOBJ *obj;
687 WineEngDestroyFontInstance( handle );
689 if (!(obj = free_gdi_handle( handle ))) return FALSE;
690 return HeapFree( GetProcessHeap(), 0, obj );
694 /***********************************************************************
695 * FONT_EnumInstance
697 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
698 * We have to use other types because of the FONTENUMPROCW definition.
700 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
701 DWORD fType, LPARAM lp )
703 struct font_enum *pfe = (struct font_enum *)lp;
704 INT ret = 1;
706 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
707 if ((!pfe->lpLogFontParam ||
708 pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
709 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
710 (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
712 /* convert font metrics */
713 ENUMLOGFONTEXA logfont;
714 NEWTEXTMETRICEXA tmA;
716 if (!pfe->unicode)
718 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
719 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
720 plf = (LOGFONTW *)&logfont.elfLogFont;
721 ptm = (TEXTMETRICW *)&tmA;
723 ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
725 return ret;
728 /***********************************************************************
729 * FONT_EnumFontFamiliesEx
731 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf, FONTENUMPROCW efproc,
732 LPARAM lParam, BOOL unicode )
734 INT ret = 0;
735 DC *dc = get_dc_ptr( hDC );
736 struct font_enum fe;
738 if (dc)
740 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pEnumFonts );
742 if (plf) TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName), plf->lfCharSet);
743 fe.lpLogFontParam = plf;
744 fe.lpEnumFunc = efproc;
745 fe.lpData = lParam;
746 fe.unicode = unicode;
747 fe.hdc = hDC;
748 ret = physdev->funcs->pEnumFonts( physdev, plf, FONT_EnumInstance, (LPARAM)&fe );
749 release_dc_ptr( dc );
751 return ret;
754 /***********************************************************************
755 * EnumFontFamiliesExW (GDI32.@)
757 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
758 FONTENUMPROCW efproc,
759 LPARAM lParam, DWORD dwFlags )
761 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, TRUE );
764 /***********************************************************************
765 * EnumFontFamiliesExA (GDI32.@)
767 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
768 FONTENUMPROCA efproc,
769 LPARAM lParam, DWORD dwFlags)
771 LOGFONTW lfW, *plfW;
773 if (plf)
775 FONT_LogFontAToW( plf, &lfW );
776 plfW = &lfW;
778 else plfW = NULL;
780 return FONT_EnumFontFamiliesEx( hDC, plfW, (FONTENUMPROCW)efproc, lParam, FALSE );
783 /***********************************************************************
784 * EnumFontFamiliesA (GDI32.@)
786 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
787 FONTENUMPROCA efproc, LPARAM lpData )
789 LOGFONTA lf, *plf;
791 if (lpFamily)
793 if (!*lpFamily) return 1;
794 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
795 lf.lfCharSet = DEFAULT_CHARSET;
796 lf.lfPitchAndFamily = 0;
797 plf = &lf;
799 else plf = NULL;
801 return EnumFontFamiliesExA( hDC, plf, efproc, lpData, 0 );
804 /***********************************************************************
805 * EnumFontFamiliesW (GDI32.@)
807 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
808 FONTENUMPROCW efproc, LPARAM lpData )
810 LOGFONTW lf, *plf;
812 if (lpFamily)
814 if (!*lpFamily) return 1;
815 lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
816 lf.lfCharSet = DEFAULT_CHARSET;
817 lf.lfPitchAndFamily = 0;
818 plf = &lf;
820 else plf = NULL;
822 return EnumFontFamiliesExW( hDC, plf, efproc, lpData, 0 );
825 /***********************************************************************
826 * EnumFontsA (GDI32.@)
828 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
829 LPARAM lpData )
831 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
834 /***********************************************************************
835 * EnumFontsW (GDI32.@)
837 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
838 LPARAM lpData )
840 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
844 /***********************************************************************
845 * GetTextCharacterExtra (GDI32.@)
847 INT WINAPI GetTextCharacterExtra( HDC hdc )
849 INT ret;
850 DC *dc = get_dc_ptr( hdc );
851 if (!dc) return 0x80000000;
852 ret = dc->charExtra;
853 release_dc_ptr( dc );
854 return ret;
858 /***********************************************************************
859 * SetTextCharacterExtra (GDI32.@)
861 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
863 INT ret = 0x80000000;
864 DC * dc = get_dc_ptr( hdc );
866 if (dc)
868 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetTextCharacterExtra );
869 extra = physdev->funcs->pSetTextCharacterExtra( physdev, extra );
870 if (extra != 0x80000000)
872 ret = dc->charExtra;
873 dc->charExtra = extra;
875 release_dc_ptr( dc );
877 return ret;
881 /***********************************************************************
882 * SetTextJustification (GDI32.@)
884 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
886 BOOL ret;
887 PHYSDEV physdev;
888 DC * dc = get_dc_ptr( hdc );
890 if (!dc) return FALSE;
892 physdev = GET_DC_PHYSDEV( dc, pSetTextJustification );
893 ret = physdev->funcs->pSetTextJustification( physdev, extra, breaks );
894 if (ret)
896 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
897 if (!extra) breaks = 0;
898 if (breaks)
900 dc->breakExtra = extra / breaks;
901 dc->breakRem = extra - (breaks * dc->breakExtra);
903 else
905 dc->breakExtra = 0;
906 dc->breakRem = 0;
909 release_dc_ptr( dc );
910 return ret;
914 /***********************************************************************
915 * GetTextFaceA (GDI32.@)
917 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
919 INT res = GetTextFaceW(hdc, 0, NULL);
920 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
921 GetTextFaceW( hdc, res, nameW );
923 if (name)
925 if (count)
927 res = WideCharToMultiByte(CP_ACP, 0, nameW, -1, name, count, NULL, NULL);
928 if (res == 0)
929 res = count;
930 name[count-1] = 0;
931 /* GetTextFaceA does NOT include the nul byte in the return count. */
932 res--;
934 else
935 res = 0;
937 else
938 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
939 HeapFree( GetProcessHeap(), 0, nameW );
940 return res;
943 /***********************************************************************
944 * GetTextFaceW (GDI32.@)
946 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
948 PHYSDEV dev;
949 INT ret;
951 DC * dc = get_dc_ptr( hdc );
952 if (!dc) return 0;
954 dev = GET_DC_PHYSDEV( dc, pGetTextFace );
955 ret = dev->funcs->pGetTextFace( dev, count, name );
956 release_dc_ptr( dc );
957 return ret;
961 /***********************************************************************
962 * GetTextExtentPoint32A (GDI32.@)
964 * See GetTextExtentPoint32W.
966 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
967 LPSIZE size )
969 BOOL ret = FALSE;
970 INT wlen;
971 LPWSTR p;
973 if (count < 0) return FALSE;
975 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
977 if (p)
979 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
980 HeapFree( GetProcessHeap(), 0, p );
983 TRACE("(%p %s %d %p): returning %d x %d\n",
984 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
985 return ret;
989 /***********************************************************************
990 * GetTextExtentPoint32W [GDI32.@]
992 * Computes width/height for a string.
994 * Computes width and height of the specified string.
996 * RETURNS
997 * Success: TRUE
998 * Failure: FALSE
1000 BOOL WINAPI GetTextExtentPoint32W(
1001 HDC hdc, /* [in] Handle of device context */
1002 LPCWSTR str, /* [in] Address of text string */
1003 INT count, /* [in] Number of characters in string */
1004 LPSIZE size) /* [out] Address of structure for string size */
1006 return GetTextExtentExPointW(hdc, str, count, 0, NULL, NULL, size);
1009 /***********************************************************************
1010 * GetTextExtentExPointI [GDI32.@]
1012 * Computes width and height of the array of glyph indices.
1014 * PARAMS
1015 * hdc [I] Handle of device context.
1016 * indices [I] Glyph index array.
1017 * count [I] Number of glyphs in array.
1018 * max_ext [I] Maximum width in glyphs.
1019 * nfit [O] Maximum number of characters.
1020 * dxs [O] Partial string widths.
1021 * size [O] Returned string size.
1023 * RETURNS
1024 * Success: TRUE
1025 * Failure: FALSE
1027 BOOL WINAPI GetTextExtentExPointI( HDC hdc, const WORD *indices, INT count, INT max_ext,
1028 LPINT nfit, LPINT dxs, LPSIZE size )
1030 PHYSDEV dev;
1031 BOOL ret;
1032 DC *dc;
1034 if (count < 0) return FALSE;
1036 dc = get_dc_ptr( hdc );
1037 if (!dc) return FALSE;
1039 dev = GET_DC_PHYSDEV( dc, pGetTextExtentExPointI );
1040 ret = dev->funcs->pGetTextExtentExPointI( dev, indices, count, max_ext, nfit, dxs, size );
1041 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1042 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1043 size->cx += count * dc->charExtra;
1044 release_dc_ptr( dc );
1046 TRACE("(%p %p %d %p): returning %d x %d\n",
1047 hdc, indices, count, size, size->cx, size->cy );
1048 return ret;
1051 /***********************************************************************
1052 * GetTextExtentPointI [GDI32.@]
1054 * Computes width and height of the array of glyph indices.
1056 * PARAMS
1057 * hdc [I] Handle of device context.
1058 * indices [I] Glyph index array.
1059 * count [I] Number of glyphs in array.
1060 * size [O] Returned string size.
1062 * RETURNS
1063 * Success: TRUE
1064 * Failure: FALSE
1066 BOOL WINAPI GetTextExtentPointI( HDC hdc, const WORD *indices, INT count, LPSIZE size )
1068 return GetTextExtentExPointI( hdc, indices, count, 0, NULL, NULL, size );
1072 /***********************************************************************
1073 * GetTextExtentPointA (GDI32.@)
1075 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
1076 LPSIZE size )
1078 TRACE("not bug compatible.\n");
1079 return GetTextExtentPoint32A( hdc, str, count, size );
1082 /***********************************************************************
1083 * GetTextExtentPointW (GDI32.@)
1085 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1086 LPSIZE size )
1088 TRACE("not bug compatible.\n");
1089 return GetTextExtentPoint32W( hdc, str, count, size );
1093 /***********************************************************************
1094 * GetTextExtentExPointA (GDI32.@)
1096 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1097 INT maxExt, LPINT lpnFit,
1098 LPINT alpDx, LPSIZE size )
1100 BOOL ret;
1101 INT wlen;
1102 INT *walpDx = NULL;
1103 LPWSTR p = NULL;
1105 if (count < 0) return FALSE;
1107 if (alpDx)
1109 walpDx = HeapAlloc( GetProcessHeap(), 0, count * sizeof(INT) );
1110 if (!walpDx) return FALSE;
1113 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1114 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
1115 if (walpDx)
1117 INT n = lpnFit ? *lpnFit : wlen;
1118 INT i, j;
1119 for(i = 0, j = 0; i < n; i++, j++)
1121 alpDx[j] = walpDx[i];
1122 if (IsDBCSLeadByte(str[j])) alpDx[++j] = walpDx[i];
1125 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1126 HeapFree( GetProcessHeap(), 0, p );
1127 HeapFree( GetProcessHeap(), 0, walpDx );
1128 return ret;
1132 /***********************************************************************
1133 * GetTextExtentExPointW (GDI32.@)
1135 * Return the size of the string as it would be if it was output properly by
1136 * e.g. TextOut.
1138 * This should include
1139 * - Intercharacter spacing
1140 * - justification spacing (not yet done)
1141 * - kerning? see below
1143 * Kerning. Since kerning would be carried out by the rendering code it should
1144 * be done by the driver. However they don't support it yet. Also I am not
1145 * yet persuaded that (certainly under Win95) any kerning is actually done.
1147 * str: According to MSDN this should be null-terminated. That is not true; a
1148 * null will not terminate it early.
1149 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1150 * than count. I have seen it be either the size of the full string or
1151 * 1 less than the size of the full string. I have not seen it bear any
1152 * resemblance to the portion that would fit.
1153 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1154 * trailing intercharacter spacing and any trailing justification.
1156 * FIXME
1157 * Currently we do this by measuring each character etc. We should do it by
1158 * passing the request to the driver, perhaps by extending the
1159 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1160 * thinking about kerning issues and rounding issues in the justification.
1163 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1164 INT maxExt, LPINT lpnFit,
1165 LPINT alpDx, LPSIZE size )
1167 INT nFit = 0;
1168 LPINT dxs = NULL;
1169 DC *dc;
1170 BOOL ret = FALSE;
1171 TEXTMETRICW tm;
1172 PHYSDEV dev;
1174 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1176 if (count < 0) return FALSE;
1178 dc = get_dc_ptr(hdc);
1179 if (!dc) return FALSE;
1181 GetTextMetricsW(hdc, &tm);
1183 /* If we need to calculate nFit, then we need the partial extents even if
1184 the user hasn't provided us with an array. */
1185 if (lpnFit)
1187 dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]);
1188 if (! dxs)
1190 release_dc_ptr(dc);
1191 SetLastError(ERROR_OUTOFMEMORY);
1192 return FALSE;
1195 else
1196 dxs = alpDx;
1198 dev = GET_DC_PHYSDEV( dc, pGetTextExtentExPoint );
1199 ret = dev->funcs->pGetTextExtentExPoint(dev, str, count, 0, NULL, dxs, size);
1201 /* Perform device size to world size transformations. */
1202 if (ret)
1204 INT extra = dc->charExtra,
1205 breakExtra = dc->breakExtra,
1206 breakRem = dc->breakRem,
1209 if (dxs)
1211 for (i = 0; i < count; ++i)
1213 dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
1214 dxs[i] += (i+1) * extra;
1215 if (count > 1 && (breakExtra || breakRem) && str[i] == tm.tmBreakChar)
1217 dxs[i] += breakExtra;
1218 if (breakRem > 0)
1220 breakRem--;
1221 dxs[i]++;
1224 if (dxs[i] <= maxExt)
1225 ++nFit;
1227 breakRem = dc->breakRem;
1229 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1230 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1232 if (!dxs && count > 1 && (breakExtra || breakRem))
1234 for (i = 0; i < count; i++)
1236 if (str[i] == tm.tmBreakChar)
1238 size->cx += breakExtra;
1239 if (breakRem > 0)
1241 breakRem--;
1242 (size->cx)++;
1249 if (lpnFit)
1250 *lpnFit = nFit;
1252 if (! alpDx)
1253 HeapFree(GetProcessHeap(), 0, dxs);
1255 release_dc_ptr( dc );
1257 TRACE("returning %d %d x %d\n",nFit,size->cx,size->cy);
1258 return ret;
1261 /***********************************************************************
1262 * GetTextMetricsA (GDI32.@)
1264 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1266 TEXTMETRICW tm32;
1268 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1269 FONT_TextMetricWToA( &tm32, metrics );
1270 return TRUE;
1273 /***********************************************************************
1274 * GetTextMetricsW (GDI32.@)
1276 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1278 PHYSDEV physdev;
1279 BOOL ret = FALSE;
1280 DC * dc = get_dc_ptr( hdc );
1281 if (!dc) return FALSE;
1283 physdev = GET_DC_PHYSDEV( dc, pGetTextMetrics );
1284 ret = physdev->funcs->pGetTextMetrics( physdev, metrics );
1286 if (ret)
1288 /* device layer returns values in device units
1289 * therefore we have to convert them to logical */
1291 metrics->tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1292 metrics->tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1294 #define WDPTOLP(x) ((x<0)? \
1295 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1296 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1297 #define HDPTOLP(y) ((y<0)? \
1298 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1299 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1301 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1302 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1303 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1304 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1305 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1306 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1307 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1308 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1309 ret = TRUE;
1310 #undef WDPTOLP
1311 #undef HDPTOLP
1312 TRACE("text metrics:\n"
1313 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1314 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1315 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1316 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1317 " PitchAndFamily = %02x\n"
1318 " --------------------\n"
1319 " InternalLeading = %i\n"
1320 " Ascent = %i\n"
1321 " Descent = %i\n"
1322 " Height = %i\n",
1323 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1324 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1325 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1326 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1327 metrics->tmPitchAndFamily,
1328 metrics->tmInternalLeading,
1329 metrics->tmAscent,
1330 metrics->tmDescent,
1331 metrics->tmHeight );
1333 release_dc_ptr( dc );
1334 return ret;
1338 /***********************************************************************
1339 * GetOutlineTextMetricsA (GDI32.@)
1340 * Gets metrics for TrueType fonts.
1342 * NOTES
1343 * If the supplied buffer isn't big enough Windows partially fills it up to
1344 * its given length and returns that length.
1346 * RETURNS
1347 * Success: Non-zero or size of required buffer
1348 * Failure: 0
1350 UINT WINAPI GetOutlineTextMetricsA(
1351 HDC hdc, /* [in] Handle of device context */
1352 UINT cbData, /* [in] Size of metric data array */
1353 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1355 char buf[512], *ptr;
1356 UINT ret, needed;
1357 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1358 OUTLINETEXTMETRICA *output = lpOTM;
1359 INT left, len;
1361 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1362 return 0;
1363 if(ret > sizeof(buf))
1364 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1365 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1367 needed = sizeof(OUTLINETEXTMETRICA);
1368 if(lpOTMW->otmpFamilyName)
1369 needed += WideCharToMultiByte(CP_ACP, 0,
1370 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1371 NULL, 0, NULL, NULL);
1372 if(lpOTMW->otmpFaceName)
1373 needed += WideCharToMultiByte(CP_ACP, 0,
1374 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1375 NULL, 0, NULL, NULL);
1376 if(lpOTMW->otmpStyleName)
1377 needed += WideCharToMultiByte(CP_ACP, 0,
1378 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1379 NULL, 0, NULL, NULL);
1380 if(lpOTMW->otmpFullName)
1381 needed += WideCharToMultiByte(CP_ACP, 0,
1382 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1383 NULL, 0, NULL, NULL);
1385 if(!lpOTM) {
1386 ret = needed;
1387 goto end;
1390 TRACE("needed = %d\n", needed);
1391 if(needed > cbData)
1392 /* Since the supplied buffer isn't big enough, we'll alloc one
1393 that is and memcpy the first cbData bytes into the lpOTM at
1394 the end. */
1395 output = HeapAlloc(GetProcessHeap(), 0, needed);
1397 ret = output->otmSize = min(needed, cbData);
1398 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1399 output->otmFiller = 0;
1400 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1401 output->otmfsSelection = lpOTMW->otmfsSelection;
1402 output->otmfsType = lpOTMW->otmfsType;
1403 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1404 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1405 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1406 output->otmEMSquare = lpOTMW->otmEMSquare;
1407 output->otmAscent = lpOTMW->otmAscent;
1408 output->otmDescent = lpOTMW->otmDescent;
1409 output->otmLineGap = lpOTMW->otmLineGap;
1410 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1411 output->otmsXHeight = lpOTMW->otmsXHeight;
1412 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1413 output->otmMacAscent = lpOTMW->otmMacAscent;
1414 output->otmMacDescent = lpOTMW->otmMacDescent;
1415 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1416 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1417 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1418 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1419 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1420 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1421 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1422 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1423 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1424 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1427 ptr = (char*)(output + 1);
1428 left = needed - sizeof(*output);
1430 if(lpOTMW->otmpFamilyName) {
1431 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1432 len = WideCharToMultiByte(CP_ACP, 0,
1433 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1434 ptr, left, NULL, NULL);
1435 left -= len;
1436 ptr += len;
1437 } else
1438 output->otmpFamilyName = 0;
1440 if(lpOTMW->otmpFaceName) {
1441 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1442 len = WideCharToMultiByte(CP_ACP, 0,
1443 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1444 ptr, left, NULL, NULL);
1445 left -= len;
1446 ptr += len;
1447 } else
1448 output->otmpFaceName = 0;
1450 if(lpOTMW->otmpStyleName) {
1451 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1452 len = WideCharToMultiByte(CP_ACP, 0,
1453 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1454 ptr, left, NULL, NULL);
1455 left -= len;
1456 ptr += len;
1457 } else
1458 output->otmpStyleName = 0;
1460 if(lpOTMW->otmpFullName) {
1461 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1462 len = WideCharToMultiByte(CP_ACP, 0,
1463 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1464 ptr, left, NULL, NULL);
1465 left -= len;
1466 } else
1467 output->otmpFullName = 0;
1469 assert(left == 0);
1471 if(output != lpOTM) {
1472 memcpy(lpOTM, output, cbData);
1473 HeapFree(GetProcessHeap(), 0, output);
1475 /* check if the string offsets really fit into the provided size */
1476 /* FIXME: should we check string length as well? */
1477 /* make sure that we don't read/write beyond the provided buffer */
1478 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(LPSTR))
1480 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1481 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1484 /* make sure that we don't read/write beyond the provided buffer */
1485 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(LPSTR))
1487 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1488 lpOTM->otmpFaceName = 0; /* doesn't fit */
1491 /* make sure that we don't read/write beyond the provided buffer */
1492 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(LPSTR))
1494 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1495 lpOTM->otmpStyleName = 0; /* doesn't fit */
1498 /* make sure that we don't read/write beyond the provided buffer */
1499 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(LPSTR))
1501 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1502 lpOTM->otmpFullName = 0; /* doesn't fit */
1506 end:
1507 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1508 HeapFree(GetProcessHeap(), 0, lpOTMW);
1510 return ret;
1514 /***********************************************************************
1515 * GetOutlineTextMetricsW [GDI32.@]
1517 UINT WINAPI GetOutlineTextMetricsW(
1518 HDC hdc, /* [in] Handle of device context */
1519 UINT cbData, /* [in] Size of metric data array */
1520 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1522 DC *dc = get_dc_ptr( hdc );
1523 OUTLINETEXTMETRICW *output = lpOTM;
1524 PHYSDEV dev;
1525 UINT ret;
1527 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1528 if(!dc) return 0;
1530 dev = GET_DC_PHYSDEV( dc, pGetOutlineTextMetrics );
1531 ret = dev->funcs->pGetOutlineTextMetrics( dev, cbData, output );
1533 if (lpOTM && ret > cbData)
1535 output = HeapAlloc(GetProcessHeap(), 0, ret);
1536 ret = dev->funcs->pGetOutlineTextMetrics( dev, ret, output );
1539 if (lpOTM && ret)
1541 output->otmTextMetrics.tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1542 output->otmTextMetrics.tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1544 #define WDPTOLP(x) ((x<0)? \
1545 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1546 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1547 #define HDPTOLP(y) ((y<0)? \
1548 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1549 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1551 output->otmTextMetrics.tmHeight = HDPTOLP(output->otmTextMetrics.tmHeight);
1552 output->otmTextMetrics.tmAscent = HDPTOLP(output->otmTextMetrics.tmAscent);
1553 output->otmTextMetrics.tmDescent = HDPTOLP(output->otmTextMetrics.tmDescent);
1554 output->otmTextMetrics.tmInternalLeading = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1555 output->otmTextMetrics.tmExternalLeading = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1556 output->otmTextMetrics.tmAveCharWidth = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1557 output->otmTextMetrics.tmMaxCharWidth = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1558 output->otmTextMetrics.tmOverhang = WDPTOLP(output->otmTextMetrics.tmOverhang);
1559 output->otmAscent = HDPTOLP(output->otmAscent);
1560 output->otmDescent = HDPTOLP(output->otmDescent);
1561 output->otmLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmLineGap));
1562 output->otmsCapEmHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsCapEmHeight));
1563 output->otmsXHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsXHeight));
1564 output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1565 output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1566 output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1567 output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1568 output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1569 output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1570 output->otmMacLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmMacLineGap));
1571 output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1572 output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1573 output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1574 output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1575 output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1576 output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1577 output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1578 output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1579 output->otmsStrikeoutSize = abs(INTERNAL_YDSTOWS(dc,output->otmsStrikeoutSize));
1580 output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1581 output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1582 output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1583 #undef WDPTOLP
1584 #undef HDPTOLP
1585 if(output != lpOTM)
1587 memcpy(lpOTM, output, cbData);
1588 HeapFree(GetProcessHeap(), 0, output);
1589 ret = cbData;
1592 release_dc_ptr(dc);
1593 return ret;
1596 static LPSTR FONT_GetCharsByRangeA(HDC hdc, UINT firstChar, UINT lastChar, PINT pByteLen)
1598 INT i, count = lastChar - firstChar + 1;
1599 UINT mbcp;
1600 UINT c;
1601 LPSTR str;
1603 if (count <= 0)
1604 return NULL;
1606 mbcp = GdiGetCodePage(hdc);
1607 switch (mbcp)
1609 case 932:
1610 case 936:
1611 case 949:
1612 case 950:
1613 case 1361:
1614 if (lastChar > 0xffff)
1615 return NULL;
1616 if ((firstChar ^ lastChar) > 0xff)
1617 return NULL;
1618 break;
1619 default:
1620 if (lastChar > 0xff)
1621 return NULL;
1622 mbcp = 0;
1623 break;
1626 str = HeapAlloc(GetProcessHeap(), 0, count * 2 + 1);
1627 if (str == NULL)
1628 return NULL;
1630 for(i = 0, c = firstChar; c <= lastChar; i++, c++)
1632 if (mbcp) {
1633 if (c > 0xff)
1634 str[i++] = (BYTE)(c >> 8);
1635 if (c <= 0xff && IsDBCSLeadByteEx(mbcp, c))
1636 str[i] = 0x1f; /* FIXME: use default character */
1637 else
1638 str[i] = (BYTE)c;
1640 else
1641 str[i] = (BYTE)c;
1643 str[i] = '\0';
1645 *pByteLen = i;
1647 return str;
1650 /***********************************************************************
1651 * GetCharWidthW (GDI32.@)
1652 * GetCharWidth32W (GDI32.@)
1654 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1655 LPINT buffer )
1657 UINT i;
1658 BOOL ret;
1659 PHYSDEV dev;
1660 DC * dc = get_dc_ptr( hdc );
1662 if (!dc) return FALSE;
1664 dev = GET_DC_PHYSDEV( dc, pGetCharWidth );
1665 ret = dev->funcs->pGetCharWidth( dev, firstChar, lastChar, buffer );
1667 if (ret)
1669 /* convert device units to logical */
1670 for( i = firstChar; i <= lastChar; i++, buffer++ )
1671 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1673 release_dc_ptr( dc );
1674 return ret;
1678 /***********************************************************************
1679 * GetCharWidthA (GDI32.@)
1680 * GetCharWidth32A (GDI32.@)
1682 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1683 LPINT buffer )
1685 INT i, wlen;
1686 LPSTR str;
1687 LPWSTR wstr;
1688 BOOL ret = TRUE;
1690 str = FONT_GetCharsByRangeA(hdc, firstChar, lastChar, &i);
1691 if(str == NULL)
1692 return FALSE;
1694 wstr = FONT_mbtowc(hdc, str, i, &wlen, NULL);
1696 for(i = 0; i < wlen; i++)
1698 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1700 ret = FALSE;
1701 break;
1703 buffer++;
1706 HeapFree(GetProcessHeap(), 0, str);
1707 HeapFree(GetProcessHeap(), 0, wstr);
1709 return ret;
1713 /* helper for nulldrv_ExtTextOut */
1714 static DWORD get_glyph_bitmap( HDC hdc, UINT index, UINT aa_flags,
1715 GLYPHMETRICS *metrics, struct gdi_image_bits *image )
1717 UINT ggo_flags = aa_flags | GGO_GLYPH_INDEX;
1718 static const MAT2 identity = { {0,1}, {0,0}, {0,0}, {0,1} };
1719 UINT indices[3] = {0, 0, 0x20};
1720 int i;
1721 DWORD ret, size;
1722 int stride;
1724 indices[0] = index;
1726 for (i = 0; i < sizeof(indices) / sizeof(indices[0]); i++)
1728 index = indices[i];
1729 ret = GetGlyphOutlineW( hdc, index, ggo_flags, metrics, 0, NULL, &identity );
1730 if (ret != GDI_ERROR) break;
1733 if (ret == GDI_ERROR) return ERROR_NOT_FOUND;
1734 if (!image) return ERROR_SUCCESS;
1736 image->ptr = NULL;
1737 image->free = NULL;
1738 if (!ret) return ERROR_SUCCESS; /* empty glyph */
1740 stride = get_dib_stride( metrics->gmBlackBoxX, 1 );
1741 size = metrics->gmBlackBoxY * stride;
1743 if (!(image->ptr = HeapAlloc( GetProcessHeap(), 0, size ))) return ERROR_OUTOFMEMORY;
1744 image->is_copy = TRUE;
1745 image->free = free_heap_bits;
1747 ret = GetGlyphOutlineW( hdc, index, ggo_flags, metrics, size, image->ptr, &identity );
1748 if (ret == GDI_ERROR)
1750 HeapFree( GetProcessHeap(), 0, image->ptr );
1751 return ERROR_NOT_FOUND;
1753 return ERROR_SUCCESS;
1756 /* helper for nulldrv_ExtTextOut */
1757 static RECT get_total_extents( HDC hdc, INT x, INT y, UINT flags, UINT aa_flags,
1758 LPCWSTR str, UINT count, const INT *dx )
1760 int i;
1761 RECT rect;
1763 rect.left = rect.top = INT_MAX;
1764 rect.right = rect.bottom = INT_MIN;
1765 for (i = 0; i < count; i++)
1767 GLYPHMETRICS metrics;
1769 if (get_glyph_bitmap( hdc, (UINT)str[i], aa_flags, &metrics, NULL )) continue;
1771 rect.left = min( rect.left, x + metrics.gmptGlyphOrigin.x );
1772 rect.top = min( rect.top, y - metrics.gmptGlyphOrigin.y );
1773 rect.right = max( rect.right, x + metrics.gmptGlyphOrigin.x + (int)metrics.gmBlackBoxX );
1774 rect.bottom = max( rect.bottom, y - metrics.gmptGlyphOrigin.y + (int)metrics.gmBlackBoxY );
1776 if (dx)
1778 if (flags & ETO_PDY)
1780 x += dx[ i * 2 ];
1781 y += dx[ i * 2 + 1];
1783 else x += dx[ i ];
1785 else
1787 x += metrics.gmCellIncX;
1788 y += metrics.gmCellIncY;
1791 return rect;
1794 /* helper for nulldrv_ExtTextOut */
1795 static void draw_glyph( HDC hdc, INT origin_x, INT origin_y, const GLYPHMETRICS *metrics,
1796 const struct gdi_image_bits *image, const RECT *clip )
1798 static const BYTE masks[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
1799 UINT x, y, i, count;
1800 BYTE *ptr = image->ptr;
1801 int stride = get_dib_stride( metrics->gmBlackBoxX, 1 );
1802 POINT *pts;
1803 RECT rect, clipped_rect;
1805 rect.left = origin_x + metrics->gmptGlyphOrigin.x;
1806 rect.top = origin_y - metrics->gmptGlyphOrigin.y;
1807 rect.right = rect.left + metrics->gmBlackBoxX;
1808 rect.bottom = rect.top + metrics->gmBlackBoxY;
1809 if (!clip) clipped_rect = rect;
1810 else if (!intersect_rect( &clipped_rect, &rect, clip )) return;
1812 pts = HeapAlloc( GetProcessHeap(), 0,
1813 max(2,metrics->gmBlackBoxX) * metrics->gmBlackBoxY * sizeof(*pts) );
1814 if (!pts) return;
1816 count = 0;
1817 ptr += (clipped_rect.top - rect.top) * stride;
1818 for (y = clipped_rect.top; y < clipped_rect.bottom; y++, ptr += stride)
1820 for (x = clipped_rect.left - rect.left; x < clipped_rect.right - rect.left; x++)
1822 while (x < clipped_rect.right - rect.left && !(ptr[x / 8] & masks[x % 8])) x++;
1823 pts[count].x = rect.left + x;
1824 while (x < clipped_rect.right - rect.left && (ptr[x / 8] & masks[x % 8])) x++;
1825 pts[count + 1].x = rect.left + x;
1826 if (pts[count + 1].x > pts[count].x)
1828 pts[count].y = pts[count + 1].y = y;
1829 count += 2;
1833 DPtoLP( hdc, pts, count );
1834 for (i = 0; i < count; i += 2) Polyline( hdc, pts + i, 2 );
1835 HeapFree( GetProcessHeap(), 0, pts );
1838 /***********************************************************************
1839 * nulldrv_ExtTextOut
1841 BOOL nulldrv_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags, const RECT *rect,
1842 LPCWSTR str, UINT count, const INT *dx )
1844 DC *dc = get_nulldrv_dc( dev );
1845 UINT aa_flags, i;
1846 DWORD err;
1847 HGDIOBJ orig;
1848 HPEN pen;
1850 if (flags & ETO_OPAQUE)
1852 RECT rc = *rect;
1853 HBRUSH brush = CreateSolidBrush( GetNearestColor( dev->hdc, GetBkColor(dev->hdc) ));
1855 if (brush)
1857 orig = SelectObject( dev->hdc, brush );
1858 DPtoLP( dev->hdc, (POINT *)&rc, 2 );
1859 PatBlt( dev->hdc, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, PATCOPY );
1860 SelectObject( dev->hdc, orig );
1861 DeleteObject( brush );
1865 if (!count) return TRUE;
1867 aa_flags = get_font_aa_flags( dev->hdc );
1869 if (aa_flags != GGO_BITMAP)
1871 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1872 BITMAPINFO *info = (BITMAPINFO *)buffer;
1873 struct gdi_image_bits bits;
1874 struct bitblt_coords src, dst;
1875 PHYSDEV dst_dev;
1877 dst_dev = GET_DC_PHYSDEV( dc, pPutImage );
1878 src.visrect = get_total_extents( dev->hdc, x, y, flags, aa_flags, str, count, dx );
1879 if (flags & ETO_CLIPPED) intersect_rect( &src.visrect, &src.visrect, rect );
1880 if (!clip_visrect( dc, &src.visrect, &src.visrect )) return TRUE;
1882 /* FIXME: check for ETO_OPAQUE and avoid GetImage */
1883 src.x = src.visrect.left;
1884 src.y = src.visrect.top;
1885 src.width = src.visrect.right - src.visrect.left;
1886 src.height = src.visrect.bottom - src.visrect.top;
1887 dst = src;
1888 if ((flags & ETO_OPAQUE) && (src.visrect.left >= rect->left) && (src.visrect.top >= rect->top) &&
1889 (src.visrect.right <= rect->right) && (src.visrect.bottom <= rect->bottom))
1891 /* we can avoid the GetImage, just query the needed format */
1892 memset( &info->bmiHeader, 0, sizeof(info->bmiHeader) );
1893 info->bmiHeader.biSize = sizeof(info->bmiHeader);
1894 info->bmiHeader.biWidth = src.width;
1895 info->bmiHeader.biHeight = -src.height;
1896 err = dst_dev->funcs->pPutImage( dst_dev, 0, 0, info, NULL, NULL, NULL, 0 );
1897 if (!err || err == ERROR_BAD_FORMAT)
1899 /* make the source rectangle relative to the source bits */
1900 src.x = src.y = 0;
1901 src.visrect.left = src.visrect.top = 0;
1902 src.visrect.right = src.width;
1903 src.visrect.bottom = src.height;
1905 bits.ptr = HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( info ));
1906 if (!bits.ptr) return ERROR_OUTOFMEMORY;
1907 bits.is_copy = TRUE;
1908 bits.free = free_heap_bits;
1909 err = ERROR_SUCCESS;
1912 else
1914 PHYSDEV src_dev = GET_DC_PHYSDEV( dc, pGetImage );
1915 err = src_dev->funcs->pGetImage( src_dev, 0, info, &bits, &src );
1916 if (!err && !bits.is_copy)
1918 void *ptr = HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( info ));
1919 if (!ptr)
1921 if (bits.free) bits.free( &bits );
1922 return ERROR_OUTOFMEMORY;
1924 memcpy( ptr, bits.ptr, get_dib_image_size( info ));
1925 if (bits.free) bits.free( &bits );
1926 bits.ptr = ptr;
1927 bits.is_copy = TRUE;
1928 bits.free = free_heap_bits;
1931 if (!err)
1933 /* make x,y relative to the image bits */
1934 x += src.visrect.left - dst.visrect.left;
1935 y += src.visrect.top - dst.visrect.top;
1936 render_aa_text_bitmapinfo( dev->hdc, info, &bits, &src, x, y, flags,
1937 aa_flags, str, count, dx );
1938 err = dst_dev->funcs->pPutImage( dst_dev, 0, 0, info, &bits, &src, &dst, SRCCOPY );
1939 if (bits.free) bits.free( &bits );
1940 return !err;
1944 pen = CreatePen( PS_SOLID, 1, GetTextColor(dev->hdc) );
1945 orig = SelectObject( dev->hdc, pen );
1947 for (i = 0; i < count; i++)
1949 GLYPHMETRICS metrics;
1950 struct gdi_image_bits image;
1952 err = get_glyph_bitmap( dev->hdc, (UINT)str[i], GGO_BITMAP, &metrics, &image );
1953 if (err) continue;
1955 if (image.ptr) draw_glyph( dev->hdc, x, y, &metrics, &image, (flags & ETO_CLIPPED) ? rect : NULL );
1956 if (image.free) image.free( &image );
1958 if (dx)
1960 if (flags & ETO_PDY)
1962 x += dx[ i * 2 ];
1963 y += dx[ i * 2 + 1];
1965 else x += dx[ i ];
1967 else
1969 x += metrics.gmCellIncX;
1970 y += metrics.gmCellIncY;
1974 SelectObject( dev->hdc, orig );
1975 DeleteObject( pen );
1976 return TRUE;
1980 /***********************************************************************
1981 * ExtTextOutA (GDI32.@)
1983 * See ExtTextOutW.
1985 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1986 const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1988 INT wlen;
1989 UINT codepage;
1990 LPWSTR p;
1991 BOOL ret;
1992 LPINT lpDxW = NULL;
1994 if (flags & ETO_GLYPH_INDEX)
1995 return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
1997 p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
1999 if (lpDx) {
2000 unsigned int i = 0, j = 0;
2002 /* allocate enough for a ETO_PDY */
2003 lpDxW = HeapAlloc( GetProcessHeap(), 0, 2*wlen*sizeof(INT));
2004 while(i < count) {
2005 if(IsDBCSLeadByteEx(codepage, str[i]))
2007 if(flags & ETO_PDY)
2009 lpDxW[j++] = lpDx[i * 2] + lpDx[(i + 1) * 2];
2010 lpDxW[j++] = lpDx[i * 2 + 1] + lpDx[(i + 1) * 2 + 1];
2012 else
2013 lpDxW[j++] = lpDx[i] + lpDx[i + 1];
2014 i = i + 2;
2016 else
2018 if(flags & ETO_PDY)
2020 lpDxW[j++] = lpDx[i * 2];
2021 lpDxW[j++] = lpDx[i * 2 + 1];
2023 else
2024 lpDxW[j++] = lpDx[i];
2025 i = i + 1;
2030 ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
2032 HeapFree( GetProcessHeap(), 0, p );
2033 HeapFree( GetProcessHeap(), 0, lpDxW );
2034 return ret;
2038 /***********************************************************************
2039 * ExtTextOutW (GDI32.@)
2041 * Draws text using the currently selected font, background color, and text color.
2044 * PARAMS
2045 * x,y [I] coordinates of string
2046 * flags [I]
2047 * ETO_GRAYED - undocumented on MSDN
2048 * ETO_OPAQUE - use background color for fill the rectangle
2049 * ETO_CLIPPED - clipping text to the rectangle
2050 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
2051 * than encoded characters. Implies ETO_IGNORELANGUAGE
2052 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
2053 * Affects BiDi ordering
2054 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
2055 * ETO_PDY - unimplemented
2056 * ETO_NUMERICSLATIN - unimplemented always assumed -
2057 * do not translate numbers into locale representations
2058 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
2059 * lprect [I] dimensions for clipping or/and opaquing
2060 * str [I] text string
2061 * count [I] number of symbols in string
2062 * lpDx [I] optional parameter with distance between drawing characters
2064 * RETURNS
2065 * Success: TRUE
2066 * Failure: FALSE
2068 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
2069 const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
2071 BOOL ret = FALSE;
2072 LPWSTR reordered_str = (LPWSTR)str;
2073 WORD *glyphs = NULL;
2074 UINT align = GetTextAlign( hdc );
2075 DWORD layout = GetLayout( hdc );
2076 POINT pt;
2077 TEXTMETRICW tm;
2078 LOGFONTW lf;
2079 double cosEsc, sinEsc;
2080 INT char_extra;
2081 SIZE sz;
2082 RECT rc;
2083 BOOL done_extents = FALSE;
2084 POINT *deltas = NULL, width = {0, 0};
2085 DWORD type;
2086 DC * dc = get_dc_ptr( hdc );
2087 PHYSDEV physdev;
2088 INT breakRem;
2089 static int quietfixme = 0;
2091 if (!dc) return FALSE;
2093 breakRem = dc->breakRem;
2095 if (quietfixme == 0 && flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN))
2097 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN unimplemented\n");
2098 quietfixme = 1;
2101 update_dc( dc );
2102 physdev = GET_DC_PHYSDEV( dc, pExtTextOut );
2103 type = GetObjectType(hdc);
2104 if(type == OBJ_METADC || type == OBJ_ENHMETADC)
2106 ret = physdev->funcs->pExtTextOut( physdev, x, y, flags, lprect, str, count, lpDx );
2107 release_dc_ptr( dc );
2108 return ret;
2111 if (!lprect)
2112 flags &= ~ETO_CLIPPED;
2114 if (flags & ETO_RTLREADING) align |= TA_RTLREADING;
2115 if (layout & LAYOUT_RTL)
2117 if ((align & TA_CENTER) != TA_CENTER) align ^= TA_RIGHT;
2118 align ^= TA_RTLREADING;
2121 if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && count > 0 )
2123 INT cGlyphs;
2124 reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
2126 BIDI_Reorder( hdc, str, count, GCP_REORDER,
2127 (align & TA_RTLREADING) ? WINE_GCPW_FORCE_RTL : WINE_GCPW_FORCE_LTR,
2128 reordered_str, count, NULL, &glyphs, &cGlyphs);
2130 flags |= ETO_IGNORELANGUAGE;
2131 if (glyphs)
2133 flags |= ETO_GLYPH_INDEX;
2134 if (cGlyphs != count)
2135 count = cGlyphs;
2138 else if(flags & ETO_GLYPH_INDEX)
2139 glyphs = reordered_str;
2141 TRACE("%p, %d, %d, %08x, %s, %s, %d, %p)\n", hdc, x, y, flags,
2142 wine_dbgstr_rect(lprect), debugstr_wn(str, count), count, lpDx);
2143 TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
2145 if(align & TA_UPDATECP)
2147 GetCurrentPositionEx( hdc, &pt );
2148 x = pt.x;
2149 y = pt.y;
2152 GetTextMetricsW(hdc, &tm);
2153 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
2155 if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
2156 lf.lfEscapement = 0;
2158 if ((dc->GraphicsMode == GM_COMPATIBLE) &&
2159 (dc->vport2WorldValid && dc->xformWorld2Vport.eM11 * dc->xformWorld2Vport.eM22 < 0))
2161 lf.lfEscapement = -lf.lfEscapement;
2164 if(lf.lfEscapement != 0)
2166 cosEsc = cos(lf.lfEscapement * M_PI / 1800);
2167 sinEsc = sin(lf.lfEscapement * M_PI / 1800);
2169 else
2171 cosEsc = 1;
2172 sinEsc = 0;
2175 if(flags & (ETO_CLIPPED | ETO_OPAQUE))
2177 if(!lprect)
2179 if(flags & ETO_GLYPH_INDEX)
2180 GetTextExtentPointI(hdc, glyphs, count, &sz);
2181 else
2182 GetTextExtentPointW(hdc, reordered_str, count, &sz);
2184 done_extents = TRUE;
2185 rc.left = x;
2186 rc.top = y;
2187 rc.right = x + sz.cx;
2188 rc.bottom = y + sz.cy;
2190 else
2192 rc = *lprect;
2195 LPtoDP(hdc, (POINT*)&rc, 2);
2197 if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
2198 if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
2201 if (lprect && (flags & ETO_OPAQUE))
2202 physdev->funcs->pExtTextOut( physdev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL );
2204 if(count == 0)
2206 ret = TRUE;
2207 goto done;
2210 pt.x = x;
2211 pt.y = y;
2212 LPtoDP(hdc, &pt, 1);
2213 x = pt.x;
2214 y = pt.y;
2216 char_extra = GetTextCharacterExtra(hdc);
2217 if(char_extra || dc->breakExtra || breakRem || lpDx || lf.lfEscapement != 0)
2219 UINT i;
2220 SIZE tmpsz;
2221 POINT total = {0, 0}, desired[2];
2223 deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
2224 for(i = 0; i < count; i++)
2226 if(lpDx)
2228 if(flags & ETO_PDY)
2230 deltas[i].x = lpDx[i * 2] + char_extra;
2231 deltas[i].y = -lpDx[i * 2 + 1];
2233 else
2235 deltas[i].x = lpDx[i] + char_extra;
2236 deltas[i].y = 0;
2240 else
2242 if(flags & ETO_GLYPH_INDEX)
2243 GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
2244 else
2245 GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
2247 deltas[i].x = tmpsz.cx;
2248 deltas[i].y = 0;
2251 if (!(flags & ETO_GLYPH_INDEX) && (dc->breakExtra || breakRem) && reordered_str[i] == tm.tmBreakChar)
2253 deltas[i].x = deltas[i].x + dc->breakExtra;
2254 if (breakRem > 0)
2256 breakRem--;
2257 deltas[i].x++;
2260 total.x += deltas[i].x;
2261 total.y += deltas[i].y;
2263 desired[0].x = desired[0].y = 0;
2265 desired[1].x = cosEsc * total.x + sinEsc * total.y;
2266 desired[1].y = -sinEsc * total.x + cosEsc * total.y;
2268 LPtoDP(hdc, desired, 2);
2269 desired[1].x -= desired[0].x;
2270 desired[1].y -= desired[0].y;
2272 if (dc->GraphicsMode == GM_COMPATIBLE)
2274 if (dc->vport2WorldValid && dc->xformWorld2Vport.eM11 < 0)
2275 desired[1].x = -desired[1].x;
2276 if (dc->vport2WorldValid && dc->xformWorld2Vport.eM22 < 0)
2277 desired[1].y = -desired[1].y;
2279 else
2281 if (layout & LAYOUT_RTL) desired[1].x = -desired[1].x;
2284 deltas[i].x = desired[1].x - width.x;
2285 deltas[i].y = desired[1].y - width.y;
2287 width = desired[1];
2289 flags |= ETO_PDY;
2291 else
2293 if(!done_extents)
2295 if(flags & ETO_GLYPH_INDEX)
2296 GetTextExtentPointI(hdc, glyphs, count, &sz);
2297 else
2298 GetTextExtentPointW(hdc, reordered_str, count, &sz);
2299 done_extents = TRUE;
2301 width.x = abs(INTERNAL_XWSTODS(dc, sz.cx));
2302 width.y = 0;
2305 tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
2306 tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
2307 switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
2309 case TA_LEFT:
2310 if (align & TA_UPDATECP)
2312 pt.x = x + width.x;
2313 pt.y = y + width.y;
2314 DPtoLP(hdc, &pt, 1);
2315 MoveToEx(hdc, pt.x, pt.y, NULL);
2317 break;
2319 case TA_CENTER:
2320 x -= width.x / 2;
2321 y -= width.y / 2;
2322 break;
2324 case TA_RIGHT:
2325 x -= width.x;
2326 y -= width.y;
2327 if (align & TA_UPDATECP)
2329 pt.x = x;
2330 pt.y = y;
2331 DPtoLP(hdc, &pt, 1);
2332 MoveToEx(hdc, pt.x, pt.y, NULL);
2334 break;
2337 switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
2339 case TA_TOP:
2340 y += tm.tmAscent * cosEsc;
2341 x += tm.tmAscent * sinEsc;
2342 break;
2344 case TA_BOTTOM:
2345 y -= tm.tmDescent * cosEsc;
2346 x -= tm.tmDescent * sinEsc;
2347 break;
2349 case TA_BASELINE:
2350 break;
2353 if (GetBkMode(hdc) != TRANSPARENT)
2355 if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
2357 if(!(flags & ETO_OPAQUE) || !lprect ||
2358 x < rc.left || x + width.x >= rc.right ||
2359 y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
2361 RECT text_box;
2362 text_box.left = x;
2363 text_box.right = x + width.x;
2364 text_box.top = y - tm.tmAscent;
2365 text_box.bottom = y + tm.tmDescent;
2367 if (flags & ETO_CLIPPED) intersect_rect( &text_box, &text_box, &rc );
2368 if (!is_rect_empty( &text_box ))
2369 physdev->funcs->pExtTextOut( physdev, 0, 0, ETO_OPAQUE, &text_box, NULL, 0, NULL );
2374 if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
2376 HFONT orig_font = dc->hFont, cur_font;
2377 UINT glyph;
2378 INT span = 0;
2379 POINT *offsets = NULL;
2380 unsigned int i;
2382 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2383 for(i = 0; i < count; i++)
2385 WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
2386 if(cur_font != dc->hFont)
2388 if(!offsets)
2390 unsigned int j;
2391 offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
2392 offsets[0].x = offsets[0].y = 0;
2394 if(!deltas)
2396 SIZE tmpsz;
2397 for(j = 1; j < count; j++)
2399 GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
2400 offsets[j].x = offsets[j - 1].x + abs(INTERNAL_XWSTODS(dc, tmpsz.cx));
2401 offsets[j].y = 0;
2404 else
2406 for(j = 1; j < count; j++)
2408 offsets[j].x = offsets[j - 1].x + deltas[j].x;
2409 offsets[j].y = offsets[j - 1].y + deltas[j].y;
2413 if(span)
2415 physdev->funcs->pExtTextOut( physdev, x + offsets[i - span].x,
2416 y + offsets[i - span].y,
2417 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc, glyphs,
2418 span, deltas ? (INT*)(deltas + (i - span)) : NULL);
2419 span = 0;
2421 SelectObject(hdc, cur_font);
2423 glyphs[span++] = glyph;
2425 if(i == count - 1)
2427 ret = physdev->funcs->pExtTextOut(physdev, x + (offsets ? offsets[count - span].x : 0),
2428 y + (offsets ? offsets[count - span].y : 0),
2429 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc, glyphs,
2430 span, deltas ? (INT*)(deltas + (count - span)) : NULL);
2431 SelectObject(hdc, orig_font);
2432 HeapFree(GetProcessHeap(), 0, offsets);
2436 else
2438 if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
2440 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2441 GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
2442 flags |= ETO_GLYPH_INDEX;
2444 ret = physdev->funcs->pExtTextOut( physdev, x, y, (flags & ~ETO_OPAQUE), &rc,
2445 glyphs ? glyphs : reordered_str, count, (INT*)deltas );
2448 done:
2449 HeapFree(GetProcessHeap(), 0, deltas);
2450 if(glyphs != reordered_str)
2451 HeapFree(GetProcessHeap(), 0, glyphs);
2452 if(reordered_str != str)
2453 HeapFree(GetProcessHeap(), 0, reordered_str);
2455 release_dc_ptr( dc );
2457 if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2459 int underlinePos, strikeoutPos;
2460 int underlineWidth, strikeoutWidth;
2461 UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2462 OUTLINETEXTMETRICW* otm = NULL;
2463 POINT pts[5];
2464 HPEN hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2465 HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2467 hbrush = SelectObject(hdc, hbrush);
2469 if(!size)
2471 underlinePos = 0;
2472 underlineWidth = tm.tmAscent / 20 + 1;
2473 strikeoutPos = tm.tmAscent / 2;
2474 strikeoutWidth = underlineWidth;
2476 else
2478 otm = HeapAlloc(GetProcessHeap(), 0, size);
2479 GetOutlineTextMetricsW(hdc, size, otm);
2480 underlinePos = abs( INTERNAL_YWSTODS( dc, otm->otmsUnderscorePosition ));
2481 if (otm->otmsUnderscorePosition < 0) underlinePos = -underlinePos;
2482 underlineWidth = abs( INTERNAL_YWSTODS( dc, otm->otmsUnderscoreSize ));
2483 if (otm->otmsUnderscoreSize < 0) underlineWidth = -underlineWidth;
2484 strikeoutPos = abs( INTERNAL_YWSTODS( dc, otm->otmsStrikeoutPosition ));
2485 if (otm->otmsStrikeoutPosition < 0) strikeoutPos = -strikeoutPos;
2486 strikeoutWidth = abs( INTERNAL_YWSTODS( dc, otm->otmsStrikeoutSize ));
2487 HeapFree(GetProcessHeap(), 0, otm);
2491 if (lf.lfUnderline)
2493 pts[0].x = x - (underlinePos + underlineWidth / 2) * sinEsc;
2494 pts[0].y = y - (underlinePos + underlineWidth / 2) * cosEsc;
2495 pts[1].x = x + width.x - (underlinePos + underlineWidth / 2) * sinEsc;
2496 pts[1].y = y + width.y - (underlinePos + underlineWidth / 2) * cosEsc;
2497 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2498 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2499 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2500 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2501 pts[4].x = pts[0].x;
2502 pts[4].y = pts[0].y;
2503 DPtoLP(hdc, pts, 5);
2504 Polygon(hdc, pts, 5);
2507 if (lf.lfStrikeOut)
2509 pts[0].x = x - (strikeoutPos + strikeoutWidth / 2) * sinEsc;
2510 pts[0].y = y - (strikeoutPos + strikeoutWidth / 2) * cosEsc;
2511 pts[1].x = x + width.x - (strikeoutPos + strikeoutWidth / 2) * sinEsc;
2512 pts[1].y = y + width.y - (strikeoutPos + strikeoutWidth / 2) * cosEsc;
2513 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2514 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2515 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2516 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2517 pts[4].x = pts[0].x;
2518 pts[4].y = pts[0].y;
2519 DPtoLP(hdc, pts, 5);
2520 Polygon(hdc, pts, 5);
2523 SelectObject(hdc, hpen);
2524 hbrush = SelectObject(hdc, hbrush);
2525 DeleteObject(hbrush);
2528 return ret;
2532 /***********************************************************************
2533 * TextOutA (GDI32.@)
2535 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2537 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2541 /***********************************************************************
2542 * TextOutW (GDI32.@)
2544 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2546 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2550 /***********************************************************************
2551 * PolyTextOutA (GDI32.@)
2553 * See PolyTextOutW.
2555 BOOL WINAPI PolyTextOutA( HDC hdc, const POLYTEXTA *pptxt, INT cStrings )
2557 for (; cStrings>0; cStrings--, pptxt++)
2558 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2559 return FALSE;
2560 return TRUE;
2565 /***********************************************************************
2566 * PolyTextOutW (GDI32.@)
2568 * Draw several Strings
2570 * RETURNS
2571 * TRUE: Success.
2572 * FALSE: Failure.
2574 BOOL WINAPI PolyTextOutW( HDC hdc, const POLYTEXTW *pptxt, INT cStrings )
2576 for (; cStrings>0; cStrings--, pptxt++)
2577 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2578 return FALSE;
2579 return TRUE;
2583 /***********************************************************************
2584 * SetMapperFlags (GDI32.@)
2586 DWORD WINAPI SetMapperFlags( HDC hdc, DWORD flags )
2588 DC *dc = get_dc_ptr( hdc );
2589 DWORD ret = GDI_ERROR;
2591 if (dc)
2593 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetMapperFlags );
2594 flags = physdev->funcs->pSetMapperFlags( physdev, flags );
2595 if (flags != GDI_ERROR)
2597 ret = dc->mapperFlags;
2598 dc->mapperFlags = flags;
2600 release_dc_ptr( dc );
2602 return ret;
2605 /***********************************************************************
2606 * GetAspectRatioFilterEx (GDI32.@)
2608 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2610 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2611 return FALSE;
2615 /***********************************************************************
2616 * GetCharABCWidthsA (GDI32.@)
2618 * See GetCharABCWidthsW.
2620 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2621 LPABC abc )
2623 INT i, wlen;
2624 LPSTR str;
2625 LPWSTR wstr;
2626 BOOL ret = TRUE;
2628 str = FONT_GetCharsByRangeA(hdc, firstChar, lastChar, &i);
2629 if (str == NULL)
2630 return FALSE;
2632 wstr = FONT_mbtowc(hdc, str, i, &wlen, NULL);
2633 if (wstr == NULL)
2635 HeapFree(GetProcessHeap(), 0, str);
2636 return FALSE;
2639 for(i = 0; i < wlen; i++)
2641 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2643 ret = FALSE;
2644 break;
2646 abc++;
2649 HeapFree(GetProcessHeap(), 0, str);
2650 HeapFree(GetProcessHeap(), 0, wstr);
2652 return ret;
2656 /******************************************************************************
2657 * GetCharABCWidthsW [GDI32.@]
2659 * Retrieves widths of characters in range.
2661 * PARAMS
2662 * hdc [I] Handle of device context
2663 * firstChar [I] First character in range to query
2664 * lastChar [I] Last character in range to query
2665 * abc [O] Address of character-width structure
2667 * NOTES
2668 * Only works with TrueType fonts
2670 * RETURNS
2671 * Success: TRUE
2672 * Failure: FALSE
2674 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2675 LPABC abc )
2677 DC *dc = get_dc_ptr(hdc);
2678 PHYSDEV dev;
2679 unsigned int i;
2680 BOOL ret;
2681 TEXTMETRICW tm;
2683 if (!dc) return FALSE;
2685 if (!abc)
2687 release_dc_ptr( dc );
2688 return FALSE;
2691 /* unlike GetCharABCWidthsFloatW, this one is supposed to fail on non-TrueType fonts */
2692 dev = GET_DC_PHYSDEV( dc, pGetTextMetrics );
2693 if (!dev->funcs->pGetTextMetrics( dev, &tm ) || !(tm.tmPitchAndFamily & TMPF_TRUETYPE))
2695 release_dc_ptr( dc );
2696 return FALSE;
2699 dev = GET_DC_PHYSDEV( dc, pGetCharABCWidths );
2700 ret = dev->funcs->pGetCharABCWidths( dev, firstChar, lastChar, abc );
2701 if (ret)
2703 /* convert device units to logical */
2704 for( i = firstChar; i <= lastChar; i++, abc++ ) {
2705 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2706 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2707 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2711 release_dc_ptr( dc );
2712 return ret;
2716 /******************************************************************************
2717 * GetCharABCWidthsI [GDI32.@]
2719 * Retrieves widths of characters in range.
2721 * PARAMS
2722 * hdc [I] Handle of device context
2723 * firstChar [I] First glyphs in range to query
2724 * count [I] Last glyphs in range to query
2725 * pgi [i] Array of glyphs to query
2726 * abc [O] Address of character-width structure
2728 * NOTES
2729 * Only works with TrueType fonts
2731 * RETURNS
2732 * Success: TRUE
2733 * Failure: FALSE
2735 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2736 LPWORD pgi, LPABC abc)
2738 DC *dc = get_dc_ptr(hdc);
2739 PHYSDEV dev;
2740 unsigned int i;
2741 BOOL ret;
2743 if (!dc) return FALSE;
2745 if (!abc)
2747 release_dc_ptr( dc );
2748 return FALSE;
2751 dev = GET_DC_PHYSDEV( dc, pGetCharABCWidthsI );
2752 ret = dev->funcs->pGetCharABCWidthsI( dev, firstChar, count, pgi, abc );
2753 if (ret)
2755 /* convert device units to logical */
2756 for( i = 0; i < count; i++, abc++ ) {
2757 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2758 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2759 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2763 release_dc_ptr( dc );
2764 return ret;
2768 /***********************************************************************
2769 * GetGlyphOutlineA (GDI32.@)
2771 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2772 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2773 LPVOID lpBuffer, const MAT2 *lpmat2 )
2775 if (!lpmat2) return GDI_ERROR;
2777 if(!(fuFormat & GGO_GLYPH_INDEX)) {
2778 UINT cp;
2779 int len;
2780 char mbchs[2];
2782 cp = GdiGetCodePage(hdc);
2783 if (IsDBCSLeadByteEx(cp, uChar >> 8)) {
2784 len = 2;
2785 mbchs[0] = (uChar & 0xff00) >> 8;
2786 mbchs[1] = (uChar & 0xff);
2787 } else {
2788 len = 1;
2789 mbchs[0] = (uChar & 0xff);
2791 uChar = 0;
2792 MultiByteToWideChar(cp, 0, mbchs, len, (LPWSTR)&uChar, 1);
2795 return GetGlyphOutlineW(hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer,
2796 lpmat2);
2799 /***********************************************************************
2800 * GetGlyphOutlineW (GDI32.@)
2802 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2803 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2804 LPVOID lpBuffer, const MAT2 *lpmat2 )
2806 DC *dc;
2807 DWORD ret;
2808 PHYSDEV dev;
2810 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2811 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2813 if (!lpmat2) return GDI_ERROR;
2815 dc = get_dc_ptr(hdc);
2816 if(!dc) return GDI_ERROR;
2818 dev = GET_DC_PHYSDEV( dc, pGetGlyphOutline );
2819 ret = dev->funcs->pGetGlyphOutline( dev, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2820 release_dc_ptr( dc );
2821 return ret;
2825 /***********************************************************************
2826 * CreateScalableFontResourceA (GDI32.@)
2828 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2829 LPCSTR lpszResourceFile,
2830 LPCSTR lpszFontFile,
2831 LPCSTR lpszCurrentPath )
2833 LPWSTR lpszResourceFileW = NULL;
2834 LPWSTR lpszFontFileW = NULL;
2835 LPWSTR lpszCurrentPathW = NULL;
2836 int len;
2837 BOOL ret;
2839 if (lpszResourceFile)
2841 len = MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, NULL, 0);
2842 lpszResourceFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2843 MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, lpszResourceFileW, len);
2846 if (lpszFontFile)
2848 len = MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, NULL, 0);
2849 lpszFontFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2850 MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, lpszFontFileW, len);
2853 if (lpszCurrentPath)
2855 len = MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, NULL, 0);
2856 lpszCurrentPathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2857 MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, lpszCurrentPathW, len);
2860 ret = CreateScalableFontResourceW(fHidden, lpszResourceFileW,
2861 lpszFontFileW, lpszCurrentPathW);
2863 HeapFree(GetProcessHeap(), 0, lpszResourceFileW);
2864 HeapFree(GetProcessHeap(), 0, lpszFontFileW);
2865 HeapFree(GetProcessHeap(), 0, lpszCurrentPathW);
2867 return ret;
2870 /***********************************************************************
2871 * CreateScalableFontResourceW (GDI32.@)
2873 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2874 LPCWSTR lpszResourceFile,
2875 LPCWSTR lpszFontFile,
2876 LPCWSTR lpszCurrentPath )
2878 HANDLE f;
2879 FIXME("(%d,%s,%s,%s): stub\n",
2880 fHidden, debugstr_w(lpszResourceFile), debugstr_w(lpszFontFile),
2881 debugstr_w(lpszCurrentPath) );
2883 /* fHidden=1 - only visible for the calling app, read-only, not
2884 * enumerated with EnumFonts/EnumFontFamilies
2885 * lpszCurrentPath can be NULL
2888 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2889 if ((f = CreateFileW(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2890 CloseHandle(f);
2891 SetLastError(ERROR_FILE_EXISTS);
2892 return FALSE;
2894 return FALSE; /* create failed */
2897 /*************************************************************************
2898 * GetKerningPairsA (GDI32.@)
2900 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2901 LPKERNINGPAIR kern_pairA )
2903 UINT cp;
2904 CPINFO cpi;
2905 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2906 KERNINGPAIR *kern_pairW;
2908 if (!cPairs && kern_pairA)
2910 SetLastError(ERROR_INVALID_PARAMETER);
2911 return 0;
2914 cp = GdiGetCodePage(hDC);
2916 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2917 * to fail on an invalid character for CP_SYMBOL.
2919 cpi.DefaultChar[0] = 0;
2920 if (cp != CP_SYMBOL && !GetCPInfo(cp, &cpi))
2922 FIXME("Can't find codepage %u info\n", cp);
2923 return 0;
2926 total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2927 if (!total_kern_pairs) return 0;
2929 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2930 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2932 for (i = 0; i < total_kern_pairs; i++)
2934 char first, second;
2936 if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2937 continue;
2939 if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2940 continue;
2942 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2943 continue;
2945 if (kern_pairA)
2947 if (kern_pairs_copied >= cPairs) break;
2949 kern_pairA->wFirst = (BYTE)first;
2950 kern_pairA->wSecond = (BYTE)second;
2951 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2952 kern_pairA++;
2954 kern_pairs_copied++;
2957 HeapFree(GetProcessHeap(), 0, kern_pairW);
2959 return kern_pairs_copied;
2962 /*************************************************************************
2963 * GetKerningPairsW (GDI32.@)
2965 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2966 LPKERNINGPAIR lpKerningPairs )
2968 DC *dc;
2969 DWORD ret;
2970 PHYSDEV dev;
2972 TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2974 if (!cPairs && lpKerningPairs)
2976 SetLastError(ERROR_INVALID_PARAMETER);
2977 return 0;
2980 dc = get_dc_ptr(hDC);
2981 if (!dc) return 0;
2983 dev = GET_DC_PHYSDEV( dc, pGetKerningPairs );
2984 ret = dev->funcs->pGetKerningPairs( dev, cPairs, lpKerningPairs );
2985 release_dc_ptr( dc );
2986 return ret;
2989 /*************************************************************************
2990 * TranslateCharsetInfo [GDI32.@]
2992 * Fills a CHARSETINFO structure for a character set, code page, or
2993 * font. This allows making the correspondence between different labels
2994 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2995 * of the same encoding.
2997 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2998 * only one codepage should be set in *lpSrc.
3000 * RETURNS
3001 * TRUE on success, FALSE on failure.
3004 BOOL WINAPI TranslateCharsetInfo(
3005 LPDWORD lpSrc, /* [in]
3006 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
3007 if flags == TCI_SRCCHARSET: a character set value
3008 if flags == TCI_SRCCODEPAGE: a code page value
3010 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
3011 DWORD flags /* [in] determines interpretation of lpSrc */)
3013 int index = 0;
3014 switch (flags) {
3015 case TCI_SRCFONTSIG:
3016 while (index < MAXTCIINDEX && !(*lpSrc>>index & 0x0001)) index++;
3017 break;
3018 case TCI_SRCCODEPAGE:
3019 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciACP) index++;
3020 break;
3021 case TCI_SRCCHARSET:
3022 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciCharset) index++;
3023 break;
3024 default:
3025 return FALSE;
3027 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
3028 *lpCs = FONT_tci[index];
3029 return TRUE;
3032 /*************************************************************************
3033 * GetFontLanguageInfo (GDI32.@)
3035 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
3037 FONTSIGNATURE fontsig;
3038 static const DWORD GCP_DBCS_MASK=0x003F0000,
3039 GCP_DIACRITIC_MASK=0x00000000,
3040 FLI_GLYPHS_MASK=0x00000000,
3041 GCP_GLYPHSHAPE_MASK=0x00000040,
3042 GCP_KASHIDA_MASK=0x00000000,
3043 GCP_LIGATE_MASK=0x00000000,
3044 GCP_USEKERNING_MASK=0x00000000,
3045 GCP_REORDER_MASK=0x00000060;
3047 DWORD result=0;
3049 GetTextCharsetInfo( hdc, &fontsig, 0 );
3050 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
3052 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
3053 result|=GCP_DBCS;
3055 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
3056 result|=GCP_DIACRITIC;
3058 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
3059 result|=FLI_GLYPHS;
3061 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
3062 result|=GCP_GLYPHSHAPE;
3064 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
3065 result|=GCP_KASHIDA;
3067 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
3068 result|=GCP_LIGATE;
3070 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
3071 result|=GCP_USEKERNING;
3073 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
3074 if( GetTextAlign( hdc) & TA_RTLREADING )
3075 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
3076 result|=GCP_REORDER;
3078 return result;
3082 /*************************************************************************
3083 * GetFontData [GDI32.@]
3085 * Retrieve data for TrueType font.
3087 * RETURNS
3089 * success: Number of bytes returned
3090 * failure: GDI_ERROR
3092 * NOTES
3094 * Calls SetLastError()
3097 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
3098 LPVOID buffer, DWORD length)
3100 DC *dc = get_dc_ptr(hdc);
3101 PHYSDEV dev;
3102 DWORD ret;
3104 if(!dc) return GDI_ERROR;
3106 dev = GET_DC_PHYSDEV( dc, pGetFontData );
3107 ret = dev->funcs->pGetFontData( dev, table, offset, buffer, length );
3108 release_dc_ptr( dc );
3109 return ret;
3112 /*************************************************************************
3113 * GetGlyphIndicesA [GDI32.@]
3115 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
3116 LPWORD pgi, DWORD flags)
3118 DWORD ret;
3119 WCHAR *lpstrW;
3120 INT countW;
3122 TRACE("(%p, %s, %d, %p, 0x%x)\n",
3123 hdc, debugstr_an(lpstr, count), count, pgi, flags);
3125 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
3126 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
3127 HeapFree(GetProcessHeap(), 0, lpstrW);
3129 return ret;
3132 /*************************************************************************
3133 * GetGlyphIndicesW [GDI32.@]
3135 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
3136 LPWORD pgi, DWORD flags)
3138 DC *dc = get_dc_ptr(hdc);
3139 PHYSDEV dev;
3140 DWORD ret;
3142 TRACE("(%p, %s, %d, %p, 0x%x)\n",
3143 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
3145 if(!dc) return GDI_ERROR;
3147 dev = GET_DC_PHYSDEV( dc, pGetGlyphIndices );
3148 ret = dev->funcs->pGetGlyphIndices( dev, lpstr, count, pgi, flags );
3149 release_dc_ptr( dc );
3150 return ret;
3153 /*************************************************************************
3154 * GetCharacterPlacementA [GDI32.@]
3156 * See GetCharacterPlacementW.
3158 * NOTES:
3159 * the web browser control of ie4 calls this with dwFlags=0
3161 DWORD WINAPI
3162 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
3163 INT nMaxExtent, GCP_RESULTSA *lpResults,
3164 DWORD dwFlags)
3166 WCHAR *lpStringW;
3167 INT uCountW;
3168 GCP_RESULTSW resultsW;
3169 DWORD ret;
3170 UINT font_cp;
3172 TRACE("%s, %d, %d, 0x%08x\n",
3173 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
3175 /* both structs are equal in size */
3176 memcpy(&resultsW, lpResults, sizeof(resultsW));
3178 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
3179 if(lpResults->lpOutString)
3180 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
3182 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
3184 lpResults->nGlyphs = resultsW.nGlyphs;
3185 lpResults->nMaxFit = resultsW.nMaxFit;
3187 if(lpResults->lpOutString) {
3188 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
3189 lpResults->lpOutString, uCount, NULL, NULL );
3192 HeapFree(GetProcessHeap(), 0, lpStringW);
3193 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
3195 return ret;
3198 /*************************************************************************
3199 * GetCharacterPlacementW [GDI32.@]
3201 * Retrieve information about a string. This includes the width, reordering,
3202 * Glyphing and so on.
3204 * RETURNS
3206 * The width and height of the string if successful, 0 if failed.
3208 * BUGS
3210 * All flags except GCP_REORDER are not yet implemented.
3211 * Reordering is not 100% compliant to the Windows BiDi method.
3212 * Caret positioning is not yet implemented for BiDi.
3213 * Classes are not yet implemented.
3216 DWORD WINAPI
3217 GetCharacterPlacementW(
3218 HDC hdc, /* [in] Device context for which the rendering is to be done */
3219 LPCWSTR lpString, /* [in] The string for which information is to be returned */
3220 INT uCount, /* [in] Number of WORDS in string. */
3221 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
3222 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
3223 DWORD dwFlags /* [in] Flags specifying how to process the string */
3226 DWORD ret=0;
3227 SIZE size;
3228 UINT i, nSet;
3230 TRACE("%s, %d, %d, 0x%08x\n",
3231 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
3233 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
3234 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
3235 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
3236 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
3237 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
3239 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08x ignored\n", dwFlags);
3240 if(lpResults->lpClass) FIXME("classes not implemented\n");
3241 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
3242 FIXME("Caret positions for complex scripts not implemented\n");
3244 nSet = (UINT)uCount;
3245 if(nSet > lpResults->nGlyphs)
3246 nSet = lpResults->nGlyphs;
3248 /* return number of initialized fields */
3249 lpResults->nGlyphs = nSet;
3251 if((dwFlags&GCP_REORDER)==0 )
3253 /* Treat the case where no special handling was requested in a fastpath way */
3254 /* copy will do if the GCP_REORDER flag is not set */
3255 if(lpResults->lpOutString)
3256 memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
3258 if(lpResults->lpOrder)
3260 for(i = 0; i < nSet; i++)
3261 lpResults->lpOrder[i] = i;
3263 } else
3265 BIDI_Reorder(NULL, lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
3266 nSet, lpResults->lpOrder, NULL, NULL );
3269 /* FIXME: Will use the placement chars */
3270 if (lpResults->lpDx)
3272 int c;
3273 for (i = 0; i < nSet; i++)
3275 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
3276 lpResults->lpDx[i]= c;
3280 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
3282 int pos = 0;
3284 lpResults->lpCaretPos[0] = 0;
3285 for (i = 1; i < nSet; i++)
3286 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
3287 lpResults->lpCaretPos[i] = (pos += size.cx);
3290 if(lpResults->lpGlyphs)
3291 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
3293 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
3294 ret = MAKELONG(size.cx, size.cy);
3296 return ret;
3299 /*************************************************************************
3300 * GetCharABCWidthsFloatA [GDI32.@]
3302 * See GetCharABCWidthsFloatW.
3304 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3306 INT i, wlen;
3307 LPSTR str;
3308 LPWSTR wstr;
3309 BOOL ret = TRUE;
3311 str = FONT_GetCharsByRangeA(hdc, first, last, &i);
3312 if (str == NULL)
3313 return FALSE;
3315 wstr = FONT_mbtowc( hdc, str, i, &wlen, NULL );
3317 for (i = 0; i < wlen; i++)
3319 if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
3321 ret = FALSE;
3322 break;
3324 abcf++;
3327 HeapFree( GetProcessHeap(), 0, str );
3328 HeapFree( GetProcessHeap(), 0, wstr );
3330 return ret;
3333 /*************************************************************************
3334 * GetCharABCWidthsFloatW [GDI32.@]
3336 * Retrieves widths of a range of characters.
3338 * PARAMS
3339 * hdc [I] Handle to device context.
3340 * first [I] First character in range to query.
3341 * last [I] Last character in range to query.
3342 * abcf [O] Array of LPABCFLOAT structures.
3344 * RETURNS
3345 * Success: TRUE
3346 * Failure: FALSE
3348 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3350 UINT i;
3351 ABC *abc;
3352 PHYSDEV dev;
3353 BOOL ret = FALSE;
3354 DC *dc = get_dc_ptr( hdc );
3356 TRACE("%p, %d, %d, %p\n", hdc, first, last, abcf);
3358 if (!dc) return FALSE;
3360 if (!abcf) goto done;
3361 if (!(abc = HeapAlloc( GetProcessHeap(), 0, (last - first + 1) * sizeof(*abc) ))) goto done;
3363 dev = GET_DC_PHYSDEV( dc, pGetCharABCWidths );
3364 ret = dev->funcs->pGetCharABCWidths( dev, first, last, abc );
3365 if (ret)
3367 /* convert device units to logical */
3368 for (i = first; i <= last; i++, abcf++)
3370 abcf->abcfA = abc[i - first].abcA * dc->xformVport2World.eM11;
3371 abcf->abcfB = abc[i - first].abcB * dc->xformVport2World.eM11;
3372 abcf->abcfC = abc[i - first].abcC * dc->xformVport2World.eM11;
3375 HeapFree( GetProcessHeap(), 0, abc );
3377 done:
3378 release_dc_ptr( dc );
3379 return ret;
3382 /*************************************************************************
3383 * GetCharWidthFloatA [GDI32.@]
3385 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
3386 UINT iLastChar, PFLOAT pxBuffer)
3388 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3389 return 0;
3392 /*************************************************************************
3393 * GetCharWidthFloatW [GDI32.@]
3395 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
3396 UINT iLastChar, PFLOAT pxBuffer)
3398 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3399 return 0;
3403 /***********************************************************************
3405 * Font Resource API *
3407 ***********************************************************************/
3409 /***********************************************************************
3410 * AddFontResourceA (GDI32.@)
3412 INT WINAPI AddFontResourceA( LPCSTR str )
3414 return AddFontResourceExA( str, 0, NULL);
3417 /***********************************************************************
3418 * AddFontResourceW (GDI32.@)
3420 INT WINAPI AddFontResourceW( LPCWSTR str )
3422 return AddFontResourceExW(str, 0, NULL);
3426 /***********************************************************************
3427 * AddFontResourceExA (GDI32.@)
3429 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3431 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3432 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3433 INT ret;
3435 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3436 ret = AddFontResourceExW(strW, fl, pdv);
3437 HeapFree(GetProcessHeap(), 0, strW);
3438 return ret;
3441 static BOOL CALLBACK load_enumed_resource(HMODULE hModule, LPCWSTR type, LPWSTR name, LONG_PTR lParam)
3443 HRSRC rsrc = FindResourceW(hModule, name, type);
3444 HGLOBAL hMem = LoadResource(hModule, rsrc);
3445 LPVOID *pMem = LockResource(hMem);
3446 int *num_total = (int *)lParam;
3447 DWORD num_in_res;
3449 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type));
3450 if (!AddFontMemResourceEx(pMem, SizeofResource(hModule, rsrc), NULL, &num_in_res))
3452 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule, hMem);
3453 return FALSE;
3456 *num_total += num_in_res;
3457 return TRUE;
3460 /***********************************************************************
3461 * AddFontResourceExW (GDI32.@)
3463 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3465 int ret = WineEngAddFontResourceEx(str, fl, pdv);
3466 if (ret == 0)
3468 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3469 HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
3470 if (hModule != NULL)
3472 int num_resources = 0;
3473 LPWSTR rt_font = (LPWSTR)((ULONG_PTR)8); /* we don't want to include winuser.h */
3475 TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3476 wine_dbgstr_w(str));
3477 if (EnumResourceNamesW(hModule, rt_font, load_enumed_resource, (LONG_PTR)&num_resources))
3478 ret = num_resources;
3479 FreeLibrary(hModule);
3482 return ret;
3485 /***********************************************************************
3486 * RemoveFontResourceA (GDI32.@)
3488 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3490 return RemoveFontResourceExA(str, 0, 0);
3493 /***********************************************************************
3494 * RemoveFontResourceW (GDI32.@)
3496 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3498 return RemoveFontResourceExW(str, 0, 0);
3501 /***********************************************************************
3502 * AddFontMemResourceEx (GDI32.@)
3504 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3506 HANDLE ret;
3507 DWORD num_fonts;
3509 if (!pbFont || !cbFont || !pcFonts)
3511 SetLastError(ERROR_INVALID_PARAMETER);
3512 return NULL;
3515 ret = WineEngAddFontMemResourceEx(pbFont, cbFont, pdv, &num_fonts);
3516 if (ret)
3518 __TRY
3520 *pcFonts = num_fonts;
3522 __EXCEPT_PAGE_FAULT
3524 WARN("page fault while writing to *pcFonts (%p)\n", pcFonts);
3525 RemoveFontMemResourceEx(ret);
3526 ret = 0;
3528 __ENDTRY
3530 return ret;
3533 /***********************************************************************
3534 * RemoveFontMemResourceEx (GDI32.@)
3536 BOOL WINAPI RemoveFontMemResourceEx( HANDLE fh )
3538 FIXME("(%p) stub\n", fh);
3539 return TRUE;
3542 /***********************************************************************
3543 * RemoveFontResourceExA (GDI32.@)
3545 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3547 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3548 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3549 INT ret;
3551 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3552 ret = RemoveFontResourceExW(strW, fl, pdv);
3553 HeapFree(GetProcessHeap(), 0, strW);
3554 return ret;
3557 /***********************************************************************
3558 * RemoveFontResourceExW (GDI32.@)
3560 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3562 return WineEngRemoveFontResourceEx(str, fl, pdv);
3565 /***********************************************************************
3566 * GetTextCharset (GDI32.@)
3568 UINT WINAPI GetTextCharset(HDC hdc)
3570 /* MSDN docs say this is equivalent */
3571 return GetTextCharsetInfo(hdc, NULL, 0);
3574 /***********************************************************************
3575 * GetTextCharsetInfo (GDI32.@)
3577 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3579 UINT ret = DEFAULT_CHARSET;
3580 DC *dc = get_dc_ptr(hdc);
3581 PHYSDEV dev;
3583 if (dc)
3585 dev = GET_DC_PHYSDEV( dc, pGetTextCharsetInfo );
3586 ret = dev->funcs->pGetTextCharsetInfo( dev, fs, flags );
3587 release_dc_ptr( dc );
3590 if (ret == DEFAULT_CHARSET && fs)
3591 memset(fs, 0, sizeof(FONTSIGNATURE));
3592 return ret;
3595 /***********************************************************************
3596 * GdiGetCharDimensions (GDI32.@)
3598 * Gets the average width of the characters in the English alphabet.
3600 * PARAMS
3601 * hdc [I] Handle to the device context to measure on.
3602 * lptm [O] Pointer to memory to store the text metrics into.
3603 * height [O] On exit, the maximum height of characters in the English alphabet.
3605 * RETURNS
3606 * The average width of characters in the English alphabet.
3608 * NOTES
3609 * This function is used by the dialog manager to get the size of a dialog
3610 * unit. It should also be used by other pieces of code that need to know
3611 * the size of a dialog unit in logical units without having access to the
3612 * window handle of the dialog.
3613 * Windows caches the font metrics from this function, but we don't and
3614 * there doesn't appear to be an immediate advantage to do so.
3616 * SEE ALSO
3617 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3619 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3621 SIZE sz;
3622 static const WCHAR alphabet[] = {
3623 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3624 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3625 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3627 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3629 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3631 if (height) *height = sz.cy;
3632 return (sz.cx / 26 + 1) / 2;
3635 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3637 FIXME("(%d): stub\n", fEnableEUDC);
3638 return FALSE;
3641 /***********************************************************************
3642 * GetCharWidthI (GDI32.@)
3644 * Retrieve widths of characters.
3646 * PARAMS
3647 * hdc [I] Handle to a device context.
3648 * first [I] First glyph in range to query.
3649 * count [I] Number of glyph indices to query.
3650 * glyphs [I] Array of glyphs to query.
3651 * buffer [O] Buffer to receive character widths.
3653 * NOTES
3654 * Only works with TrueType fonts.
3656 * RETURNS
3657 * Success: TRUE
3658 * Failure: FALSE
3660 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3662 ABC *abc;
3663 unsigned int i;
3665 TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3667 if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3668 return FALSE;
3670 if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3672 HeapFree(GetProcessHeap(), 0, abc);
3673 return FALSE;
3676 for (i = 0; i < count; i++)
3677 buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3679 HeapFree(GetProcessHeap(), 0, abc);
3680 return TRUE;
3683 /***********************************************************************
3684 * GetFontUnicodeRanges (GDI32.@)
3686 * Retrieve a list of supported Unicode characters in a font.
3688 * PARAMS
3689 * hdc [I] Handle to a device context.
3690 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3692 * RETURNS
3693 * Success: Number of bytes written to the buffer pointed to by lpgs.
3694 * Failure: 0
3697 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3699 DWORD ret;
3700 PHYSDEV dev;
3701 DC *dc = get_dc_ptr(hdc);
3703 TRACE("(%p, %p)\n", hdc, lpgs);
3705 if (!dc) return 0;
3707 dev = GET_DC_PHYSDEV( dc, pGetFontUnicodeRanges );
3708 ret = dev->funcs->pGetFontUnicodeRanges( dev, lpgs );
3709 release_dc_ptr(dc);
3710 return ret;
3714 /*************************************************************
3715 * FontIsLinked (GDI32.@)
3717 BOOL WINAPI FontIsLinked(HDC hdc)
3719 DC *dc = get_dc_ptr(hdc);
3720 PHYSDEV dev;
3721 BOOL ret;
3723 if (!dc) return FALSE;
3724 dev = GET_DC_PHYSDEV( dc, pFontIsLinked );
3725 ret = dev->funcs->pFontIsLinked( dev );
3726 release_dc_ptr(dc);
3727 TRACE("returning %d\n", ret);
3728 return ret;
3731 /*************************************************************
3732 * GdiRealizationInfo (GDI32.@)
3734 * Returns a structure that contains some font information.
3736 BOOL WINAPI GdiRealizationInfo(HDC hdc, realization_info_t *info)
3738 DC *dc = get_dc_ptr(hdc);
3739 PHYSDEV dev;
3740 BOOL ret;
3742 if (!dc) return FALSE;
3743 dev = GET_DC_PHYSDEV( dc, pGdiRealizationInfo );
3744 ret = dev->funcs->pGdiRealizationInfo( dev, info );
3745 release_dc_ptr(dc);
3746 return ret;