msi: Stub Migrate10CachedPackagesW.
[wine/multimedia.git] / dlls / gdi32 / font.c
blob5fefa2fab88e96e7a3fb67363a12bfafd2e5a08a
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;
124 INT retval;
128 * For TranslateCharsetInfo
130 #define MAXTCIINDEX 32
131 static const CHARSETINFO FONT_tci[MAXTCIINDEX] = {
132 /* ANSI */
133 { ANSI_CHARSET, 1252, {{0,0,0,0},{FS_LATIN1,0}} },
134 { EASTEUROPE_CHARSET, 1250, {{0,0,0,0},{FS_LATIN2,0}} },
135 { RUSSIAN_CHARSET, 1251, {{0,0,0,0},{FS_CYRILLIC,0}} },
136 { GREEK_CHARSET, 1253, {{0,0,0,0},{FS_GREEK,0}} },
137 { TURKISH_CHARSET, 1254, {{0,0,0,0},{FS_TURKISH,0}} },
138 { HEBREW_CHARSET, 1255, {{0,0,0,0},{FS_HEBREW,0}} },
139 { ARABIC_CHARSET, 1256, {{0,0,0,0},{FS_ARABIC,0}} },
140 { BALTIC_CHARSET, 1257, {{0,0,0,0},{FS_BALTIC,0}} },
141 { VIETNAMESE_CHARSET, 1258, {{0,0,0,0},{FS_VIETNAMESE,0}} },
142 /* reserved by ANSI */
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 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
150 /* ANSI and OEM */
151 { THAI_CHARSET, 874, {{0,0,0,0},{FS_THAI,0}} },
152 { SHIFTJIS_CHARSET, 932, {{0,0,0,0},{FS_JISJAPAN,0}} },
153 { GB2312_CHARSET, 936, {{0,0,0,0},{FS_CHINESESIMP,0}} },
154 { HANGEUL_CHARSET, 949, {{0,0,0,0},{FS_WANSUNG,0}} },
155 { CHINESEBIG5_CHARSET, 950, {{0,0,0,0},{FS_CHINESETRAD,0}} },
156 { JOHAB_CHARSET, 1361, {{0,0,0,0},{FS_JOHAB,0}} },
157 /* reserved for alternate ANSI and OEM */
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 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
166 /* reserved for system */
167 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
168 { SYMBOL_CHARSET, CP_SYMBOL, {{0,0,0,0},{FS_SYMBOL,0}} }
171 static void FONT_LogFontAToW( const LOGFONTA *fontA, LPLOGFONTW fontW )
173 memcpy(fontW, fontA, sizeof(LOGFONTA) - LF_FACESIZE);
174 MultiByteToWideChar(CP_ACP, 0, fontA->lfFaceName, -1, fontW->lfFaceName,
175 LF_FACESIZE);
176 fontW->lfFaceName[LF_FACESIZE-1] = 0;
179 static void FONT_LogFontWToA( const LOGFONTW *fontW, LPLOGFONTA fontA )
181 memcpy(fontA, fontW, sizeof(LOGFONTA) - LF_FACESIZE);
182 WideCharToMultiByte(CP_ACP, 0, fontW->lfFaceName, -1, fontA->lfFaceName,
183 LF_FACESIZE, NULL, NULL);
184 fontA->lfFaceName[LF_FACESIZE-1] = 0;
187 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEXA fontA )
189 FONT_LogFontWToA( &fontW->elfLogFont, &fontA->elfLogFont );
191 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
192 (LPSTR) fontA->elfFullName, LF_FULLFACESIZE, NULL, NULL );
193 fontA->elfFullName[LF_FULLFACESIZE-1] = '\0';
194 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
195 (LPSTR) fontA->elfStyle, LF_FACESIZE, NULL, NULL );
196 fontA->elfStyle[LF_FACESIZE-1] = '\0';
197 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
198 (LPSTR) fontA->elfScript, LF_FACESIZE, NULL, NULL );
199 fontA->elfScript[LF_FACESIZE-1] = '\0';
202 static void FONT_EnumLogFontExAToW( const ENUMLOGFONTEXA *fontA, LPENUMLOGFONTEXW fontW )
204 FONT_LogFontAToW( &fontA->elfLogFont, &fontW->elfLogFont );
206 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfFullName, -1,
207 fontW->elfFullName, LF_FULLFACESIZE );
208 fontW->elfFullName[LF_FULLFACESIZE-1] = '\0';
209 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfStyle, -1,
210 fontW->elfStyle, LF_FACESIZE );
211 fontW->elfStyle[LF_FACESIZE-1] = '\0';
212 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfScript, -1,
213 fontW->elfScript, LF_FACESIZE );
214 fontW->elfScript[LF_FACESIZE-1] = '\0';
217 /***********************************************************************
218 * TEXTMETRIC conversion functions.
220 static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
222 ptmA->tmHeight = ptmW->tmHeight;
223 ptmA->tmAscent = ptmW->tmAscent;
224 ptmA->tmDescent = ptmW->tmDescent;
225 ptmA->tmInternalLeading = ptmW->tmInternalLeading;
226 ptmA->tmExternalLeading = ptmW->tmExternalLeading;
227 ptmA->tmAveCharWidth = ptmW->tmAveCharWidth;
228 ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth;
229 ptmA->tmWeight = ptmW->tmWeight;
230 ptmA->tmOverhang = ptmW->tmOverhang;
231 ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX;
232 ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
233 ptmA->tmFirstChar = min(ptmW->tmFirstChar, 255);
234 if (ptmW->tmCharSet == SYMBOL_CHARSET)
236 ptmA->tmFirstChar = 0x1e;
237 ptmA->tmLastChar = 0xff; /* win9x behaviour - we need the OS2 table data to calculate correctly */
239 else if (ptmW->tmPitchAndFamily & TMPF_TRUETYPE)
241 ptmA->tmFirstChar = ptmW->tmDefaultChar - 1;
242 ptmA->tmLastChar = min(ptmW->tmLastChar, 0xff);
244 else
246 ptmA->tmFirstChar = min(ptmW->tmFirstChar, 0xff);
247 ptmA->tmLastChar = min(ptmW->tmLastChar, 0xff);
249 ptmA->tmDefaultChar = ptmW->tmDefaultChar;
250 ptmA->tmBreakChar = ptmW->tmBreakChar;
251 ptmA->tmItalic = ptmW->tmItalic;
252 ptmA->tmUnderlined = ptmW->tmUnderlined;
253 ptmA->tmStruckOut = ptmW->tmStruckOut;
254 ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
255 ptmA->tmCharSet = ptmW->tmCharSet;
259 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW *ptmW, NEWTEXTMETRICEXA *ptmA )
261 FONT_TextMetricWToA((const TEXTMETRICW *)ptmW, (LPTEXTMETRICA)ptmA);
262 ptmA->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
263 ptmA->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
264 ptmA->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
265 ptmA->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
266 memcpy(&ptmA->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
269 static DWORD get_font_ppem( HDC hdc )
271 TEXTMETRICW tm;
272 DWORD ppem;
273 DC *dc = get_dc_ptr( hdc );
275 if (!dc) return GDI_ERROR;
277 GetTextMetricsW( hdc, &tm );
278 ppem = abs( INTERNAL_YWSTODS( dc, tm.tmAscent + tm.tmDescent - tm.tmInternalLeading ) );
279 release_dc_ptr( dc );
280 return ppem;
283 #define GASP_GRIDFIT 0x01
284 #define GASP_DOGRAY 0x02
286 static BOOL get_gasp_flags( HDC hdc, WORD *flags )
288 DWORD size, gasp_tag = 0x70736167;
289 WORD buf[16]; /* Enough for seven ranges before we need to alloc */
290 WORD *alloced = NULL, *ptr = buf;
291 WORD num_recs, version;
292 DWORD ppem = get_font_ppem( hdc );
293 BOOL ret = FALSE;
295 *flags = 0;
296 if (ppem == GDI_ERROR) return FALSE;
298 size = GetFontData( hdc, gasp_tag, 0, NULL, 0 );
299 if (size == GDI_ERROR) return FALSE;
300 if (size < 4 * sizeof(WORD)) return FALSE;
301 if (size > sizeof(buf))
303 ptr = alloced = HeapAlloc( GetProcessHeap(), 0, size );
304 if (!ptr) return FALSE;
307 GetFontData( hdc, gasp_tag, 0, ptr, size );
309 version = get_be_word( *ptr++ );
310 num_recs = get_be_word( *ptr++ );
312 if (version > 1 || size < (num_recs * 2 + 2) * sizeof(WORD))
314 FIXME( "Unsupported gasp table: ver %d size %d recs %d\n", version, size, num_recs );
315 goto done;
318 while (num_recs--)
320 *flags = get_be_word( *(ptr + 1) );
321 if (ppem <= get_be_word( *ptr )) break;
322 ptr += 2;
324 TRACE( "got flags %04x for ppem %d\n", *flags, ppem );
325 ret = TRUE;
327 done:
328 HeapFree( GetProcessHeap(), 0, alloced );
329 return ret;
332 UINT get_font_aa_flags( HDC hdc )
334 LOGFONTW lf;
335 WORD gasp_flags;
337 if (GetObjectType( hdc ) == OBJ_MEMDC)
339 BITMAP bm;
340 GetObjectW( GetCurrentObject( hdc, OBJ_BITMAP ), sizeof(bm), &bm );
341 if (bm.bmBitsPixel <= 8) return GGO_BITMAP;
343 else if (GetDeviceCaps( hdc, BITSPIXEL ) <= 8) return GGO_BITMAP;
345 GetObjectW( GetCurrentObject( hdc, OBJ_FONT ), sizeof(lf), &lf );
346 if (lf.lfQuality == NONANTIALIASED_QUALITY) return GGO_BITMAP;
348 if (get_gasp_flags( hdc, &gasp_flags ) && !(gasp_flags & GASP_DOGRAY))
349 return GGO_BITMAP;
351 /* FIXME, check user prefs */
352 return GGO_GRAY4_BITMAP;
355 /***********************************************************************
356 * GdiGetCodePage (GDI32.@)
358 DWORD WINAPI GdiGetCodePage( HDC hdc )
360 UINT cp = CP_ACP;
361 DC *dc = get_dc_ptr( hdc );
363 if (dc)
365 cp = dc->font_code_page;
366 release_dc_ptr( dc );
368 return cp;
371 /***********************************************************************
372 * FONT_mbtowc
374 * Returns a Unicode translation of str using the charset of the
375 * currently selected font in hdc. If count is -1 then str is assumed
376 * to be '\0' terminated, otherwise it contains the number of bytes to
377 * convert. If plenW is non-NULL, on return it will point to the
378 * number of WCHARs that have been written. If pCP is non-NULL, on
379 * return it will point to the codepage used in the conversion. The
380 * caller should free the returned LPWSTR from the process heap
381 * itself.
383 static LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
385 UINT cp;
386 INT lenW;
387 LPWSTR strW;
389 cp = GdiGetCodePage( hdc );
391 if(count == -1) count = strlen(str);
392 lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
393 strW = HeapAlloc(GetProcessHeap(), 0, lenW*sizeof(WCHAR));
394 MultiByteToWideChar(cp, 0, str, count, strW, lenW);
395 TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW));
396 if(plenW) *plenW = lenW;
397 if(pCP) *pCP = cp;
398 return strW;
401 /***********************************************************************
402 * CreateFontIndirectExA (GDI32.@)
404 HFONT WINAPI CreateFontIndirectExA( const ENUMLOGFONTEXDVA *penumexA )
406 ENUMLOGFONTEXDVW enumexW;
408 if (!penumexA) return 0;
410 FONT_EnumLogFontExAToW( &penumexA->elfEnumLogfontEx, &enumexW.elfEnumLogfontEx );
411 enumexW.elfDesignVector = penumexA->elfDesignVector;
412 return CreateFontIndirectExW( &enumexW );
415 /***********************************************************************
416 * CreateFontIndirectExW (GDI32.@)
418 HFONT WINAPI CreateFontIndirectExW( const ENUMLOGFONTEXDVW *penumex )
420 HFONT hFont;
421 FONTOBJ *fontPtr;
422 const LOGFONTW *plf;
424 if (!penumex) return 0;
426 if (penumex->elfEnumLogfontEx.elfFullName[0] ||
427 penumex->elfEnumLogfontEx.elfStyle[0] ||
428 penumex->elfEnumLogfontEx.elfScript[0])
430 FIXME("some fields ignored. fullname=%s, style=%s, script=%s\n",
431 debugstr_w(penumex->elfEnumLogfontEx.elfFullName),
432 debugstr_w(penumex->elfEnumLogfontEx.elfStyle),
433 debugstr_w(penumex->elfEnumLogfontEx.elfScript));
436 plf = &penumex->elfEnumLogfontEx.elfLogFont;
437 if (!(fontPtr = HeapAlloc( GetProcessHeap(), 0, sizeof(*fontPtr) ))) return 0;
439 fontPtr->logfont = *plf;
441 if (plf->lfEscapement != plf->lfOrientation)
443 /* this should really depend on whether GM_ADVANCED is set */
444 fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
445 WARN("orientation angle %f set to "
446 "escapement angle %f for new font %p\n",
447 plf->lfOrientation/10., plf->lfEscapement/10., fontPtr);
450 if (!(hFont = alloc_gdi_handle( &fontPtr->header, OBJ_FONT, &font_funcs )))
452 HeapFree( GetProcessHeap(), 0, fontPtr );
453 return 0;
456 TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
457 plf->lfHeight, plf->lfWidth,
458 plf->lfEscapement, plf->lfOrientation,
459 plf->lfPitchAndFamily,
460 plf->lfOutPrecision, plf->lfClipPrecision,
461 plf->lfQuality, plf->lfCharSet,
462 debugstr_w(plf->lfFaceName),
463 plf->lfWeight > 400 ? "Bold" : "",
464 plf->lfItalic ? "Italic" : "",
465 plf->lfUnderline ? "Underline" : "", hFont);
467 return hFont;
470 /***********************************************************************
471 * CreateFontIndirectA (GDI32.@)
473 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *plfA )
475 LOGFONTW lfW;
477 if (!plfA) return 0;
479 FONT_LogFontAToW( plfA, &lfW );
480 return CreateFontIndirectW( &lfW );
483 /***********************************************************************
484 * CreateFontIndirectW (GDI32.@)
486 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
488 ENUMLOGFONTEXDVW exdv;
490 if (!plf) return 0;
492 exdv.elfEnumLogfontEx.elfLogFont = *plf;
493 exdv.elfEnumLogfontEx.elfFullName[0] = 0;
494 exdv.elfEnumLogfontEx.elfStyle[0] = 0;
495 exdv.elfEnumLogfontEx.elfScript[0] = 0;
496 return CreateFontIndirectExW( &exdv );
499 /*************************************************************************
500 * CreateFontA (GDI32.@)
502 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
503 INT orient, INT weight, DWORD italic,
504 DWORD underline, DWORD strikeout, DWORD charset,
505 DWORD outpres, DWORD clippres, DWORD quality,
506 DWORD pitch, LPCSTR name )
508 LOGFONTA logfont;
510 logfont.lfHeight = height;
511 logfont.lfWidth = width;
512 logfont.lfEscapement = esc;
513 logfont.lfOrientation = orient;
514 logfont.lfWeight = weight;
515 logfont.lfItalic = italic;
516 logfont.lfUnderline = underline;
517 logfont.lfStrikeOut = strikeout;
518 logfont.lfCharSet = charset;
519 logfont.lfOutPrecision = outpres;
520 logfont.lfClipPrecision = clippres;
521 logfont.lfQuality = quality;
522 logfont.lfPitchAndFamily = pitch;
524 if (name)
525 lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
526 else
527 logfont.lfFaceName[0] = '\0';
529 return CreateFontIndirectA( &logfont );
532 /*************************************************************************
533 * CreateFontW (GDI32.@)
535 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
536 INT orient, INT weight, DWORD italic,
537 DWORD underline, DWORD strikeout, DWORD charset,
538 DWORD outpres, DWORD clippres, DWORD quality,
539 DWORD pitch, LPCWSTR name )
541 LOGFONTW logfont;
543 logfont.lfHeight = height;
544 logfont.lfWidth = width;
545 logfont.lfEscapement = esc;
546 logfont.lfOrientation = orient;
547 logfont.lfWeight = weight;
548 logfont.lfItalic = italic;
549 logfont.lfUnderline = underline;
550 logfont.lfStrikeOut = strikeout;
551 logfont.lfCharSet = charset;
552 logfont.lfOutPrecision = outpres;
553 logfont.lfClipPrecision = clippres;
554 logfont.lfQuality = quality;
555 logfont.lfPitchAndFamily = pitch;
557 if (name)
558 lstrcpynW(logfont.lfFaceName, name,
559 sizeof(logfont.lfFaceName) / sizeof(WCHAR));
560 else
561 logfont.lfFaceName[0] = '\0';
563 return CreateFontIndirectW( &logfont );
566 static void update_font_code_page( DC *dc )
568 CHARSETINFO csi;
569 int charset = GetTextCharsetInfo( dc->hSelf, NULL, 0 );
571 /* Hmm, nicely designed api this one! */
572 if (TranslateCharsetInfo( ULongToPtr(charset), &csi, TCI_SRCCHARSET) )
573 dc->font_code_page = csi.ciACP;
574 else {
575 switch(charset) {
576 case OEM_CHARSET:
577 dc->font_code_page = GetOEMCP();
578 break;
579 case DEFAULT_CHARSET:
580 dc->font_code_page = GetACP();
581 break;
583 case VISCII_CHARSET:
584 case TCVN_CHARSET:
585 case KOI8_CHARSET:
586 case ISO3_CHARSET:
587 case ISO4_CHARSET:
588 case ISO10_CHARSET:
589 case CELTIC_CHARSET:
590 /* FIXME: These have no place here, but because x11drv
591 enumerates fonts with these (made up) charsets some apps
592 might use them and then the FIXME below would become
593 annoying. Now we could pick the intended codepage for
594 each of these, but since it's broken anyway we'll just
595 use CP_ACP and hope it'll go away...
597 dc->font_code_page = CP_ACP;
598 break;
600 default:
601 FIXME("Can't find codepage for charset %d\n", charset);
602 dc->font_code_page = CP_ACP;
603 break;
607 TRACE("charset %d => cp %d\n", charset, dc->font_code_page);
610 /***********************************************************************
611 * FONT_SelectObject
613 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc )
615 HGDIOBJ ret = 0;
616 DC *dc = get_dc_ptr( hdc );
617 PHYSDEV physdev;
619 if (!dc) return 0;
621 if (!GDI_inc_ref_count( handle ))
623 release_dc_ptr( dc );
624 return 0;
627 physdev = GET_DC_PHYSDEV( dc, pSelectFont );
628 if (physdev->funcs->pSelectFont( physdev, handle ))
630 ret = dc->hFont;
631 dc->hFont = handle;
632 update_font_code_page( dc );
633 GDI_dec_ref_count( ret );
635 else GDI_dec_ref_count( handle );
637 release_dc_ptr( dc );
638 return ret;
642 /***********************************************************************
643 * FONT_GetObjectA
645 static INT FONT_GetObjectA( HGDIOBJ handle, INT count, LPVOID buffer )
647 FONTOBJ *font = GDI_GetObjPtr( handle, OBJ_FONT );
648 LOGFONTA lfA;
650 if (!font) return 0;
651 if (buffer)
653 FONT_LogFontWToA( &font->logfont, &lfA );
654 if (count > sizeof(lfA)) count = sizeof(lfA);
655 memcpy( buffer, &lfA, count );
657 else count = sizeof(lfA);
658 GDI_ReleaseObj( handle );
659 return count;
662 /***********************************************************************
663 * FONT_GetObjectW
665 static INT FONT_GetObjectW( HGDIOBJ handle, INT count, LPVOID buffer )
667 FONTOBJ *font = GDI_GetObjPtr( handle, OBJ_FONT );
669 if (!font) return 0;
670 if (buffer)
672 if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
673 memcpy( buffer, &font->logfont, count );
675 else count = sizeof(LOGFONTW);
676 GDI_ReleaseObj( handle );
677 return count;
681 /***********************************************************************
682 * FONT_DeleteObject
684 static BOOL FONT_DeleteObject( HGDIOBJ handle )
686 FONTOBJ *obj;
688 WineEngDestroyFontInstance( handle );
690 if (!(obj = free_gdi_handle( handle ))) return FALSE;
691 return HeapFree( GetProcessHeap(), 0, obj );
695 /***********************************************************************
696 * FONT_EnumInstance
698 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
699 * We have to use other types because of the FONTENUMPROCW definition.
701 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
702 DWORD fType, LPARAM lp )
704 struct font_enum *pfe = (struct font_enum *)lp;
705 INT ret = 1;
707 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
708 if ((!pfe->lpLogFontParam ||
709 pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
710 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
711 (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
713 /* convert font metrics */
714 ENUMLOGFONTEXA logfont;
715 NEWTEXTMETRICEXA tmA;
717 if (!pfe->unicode)
719 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
720 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
721 plf = (LOGFONTW *)&logfont.elfLogFont;
722 ptm = (TEXTMETRICW *)&tmA;
724 ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
725 pfe->retval = ret;
727 return ret;
730 /***********************************************************************
731 * FONT_EnumFontFamiliesEx
733 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf, FONTENUMPROCW efproc,
734 LPARAM lParam, BOOL unicode )
736 INT ret = 0;
737 DC *dc = get_dc_ptr( hDC );
738 struct font_enum fe;
740 if (dc)
742 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pEnumFonts );
744 if (plf) TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName), plf->lfCharSet);
745 fe.lpLogFontParam = plf;
746 fe.lpEnumFunc = efproc;
747 fe.lpData = lParam;
748 fe.unicode = unicode;
749 fe.hdc = hDC;
750 fe.retval = 1;
751 ret = physdev->funcs->pEnumFonts( physdev, plf, FONT_EnumInstance, (LPARAM)&fe );
752 release_dc_ptr( dc );
754 return ret ? fe.retval : 0;
757 /***********************************************************************
758 * EnumFontFamiliesExW (GDI32.@)
760 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
761 FONTENUMPROCW efproc,
762 LPARAM lParam, DWORD dwFlags )
764 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, TRUE );
767 /***********************************************************************
768 * EnumFontFamiliesExA (GDI32.@)
770 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
771 FONTENUMPROCA efproc,
772 LPARAM lParam, DWORD dwFlags)
774 LOGFONTW lfW, *plfW;
776 if (plf)
778 FONT_LogFontAToW( plf, &lfW );
779 plfW = &lfW;
781 else plfW = NULL;
783 return FONT_EnumFontFamiliesEx( hDC, plfW, (FONTENUMPROCW)efproc, lParam, FALSE );
786 /***********************************************************************
787 * EnumFontFamiliesA (GDI32.@)
789 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
790 FONTENUMPROCA efproc, LPARAM lpData )
792 LOGFONTA lf, *plf;
794 if (lpFamily)
796 if (!*lpFamily) return 1;
797 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
798 lf.lfCharSet = DEFAULT_CHARSET;
799 lf.lfPitchAndFamily = 0;
800 plf = &lf;
802 else plf = NULL;
804 return EnumFontFamiliesExA( hDC, plf, efproc, lpData, 0 );
807 /***********************************************************************
808 * EnumFontFamiliesW (GDI32.@)
810 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
811 FONTENUMPROCW efproc, LPARAM lpData )
813 LOGFONTW lf, *plf;
815 if (lpFamily)
817 if (!*lpFamily) return 1;
818 lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
819 lf.lfCharSet = DEFAULT_CHARSET;
820 lf.lfPitchAndFamily = 0;
821 plf = &lf;
823 else plf = NULL;
825 return EnumFontFamiliesExW( hDC, plf, efproc, lpData, 0 );
828 /***********************************************************************
829 * EnumFontsA (GDI32.@)
831 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
832 LPARAM lpData )
834 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
837 /***********************************************************************
838 * EnumFontsW (GDI32.@)
840 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
841 LPARAM lpData )
843 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
847 /***********************************************************************
848 * GetTextCharacterExtra (GDI32.@)
850 INT WINAPI GetTextCharacterExtra( HDC hdc )
852 INT ret;
853 DC *dc = get_dc_ptr( hdc );
854 if (!dc) return 0x80000000;
855 ret = dc->charExtra;
856 release_dc_ptr( dc );
857 return ret;
861 /***********************************************************************
862 * SetTextCharacterExtra (GDI32.@)
864 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
866 INT ret = 0x80000000;
867 DC * dc = get_dc_ptr( hdc );
869 if (dc)
871 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetTextCharacterExtra );
872 extra = physdev->funcs->pSetTextCharacterExtra( physdev, extra );
873 if (extra != 0x80000000)
875 ret = dc->charExtra;
876 dc->charExtra = extra;
878 release_dc_ptr( dc );
880 return ret;
884 /***********************************************************************
885 * SetTextJustification (GDI32.@)
887 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
889 BOOL ret;
890 PHYSDEV physdev;
891 DC * dc = get_dc_ptr( hdc );
893 if (!dc) return FALSE;
895 physdev = GET_DC_PHYSDEV( dc, pSetTextJustification );
896 ret = physdev->funcs->pSetTextJustification( physdev, extra, breaks );
897 if (ret)
899 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
900 if (!extra) breaks = 0;
901 if (breaks)
903 dc->breakExtra = extra / breaks;
904 dc->breakRem = extra - (breaks * dc->breakExtra);
906 else
908 dc->breakExtra = 0;
909 dc->breakRem = 0;
912 release_dc_ptr( dc );
913 return ret;
917 /***********************************************************************
918 * GetTextFaceA (GDI32.@)
920 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
922 INT res = GetTextFaceW(hdc, 0, NULL);
923 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
924 GetTextFaceW( hdc, res, nameW );
926 if (name)
928 if (count)
930 res = WideCharToMultiByte(CP_ACP, 0, nameW, -1, name, count, NULL, NULL);
931 if (res == 0)
932 res = count;
933 name[count-1] = 0;
934 /* GetTextFaceA does NOT include the nul byte in the return count. */
935 res--;
937 else
938 res = 0;
940 else
941 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
942 HeapFree( GetProcessHeap(), 0, nameW );
943 return res;
946 /***********************************************************************
947 * GetTextFaceW (GDI32.@)
949 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
951 PHYSDEV dev;
952 INT ret;
954 DC * dc = get_dc_ptr( hdc );
955 if (!dc) return 0;
957 dev = GET_DC_PHYSDEV( dc, pGetTextFace );
958 ret = dev->funcs->pGetTextFace( dev, count, name );
959 release_dc_ptr( dc );
960 return ret;
964 /***********************************************************************
965 * GetTextExtentPoint32A (GDI32.@)
967 * See GetTextExtentPoint32W.
969 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
970 LPSIZE size )
972 BOOL ret = FALSE;
973 INT wlen;
974 LPWSTR p;
976 if (count < 0) return FALSE;
978 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
980 if (p)
982 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
983 HeapFree( GetProcessHeap(), 0, p );
986 TRACE("(%p %s %d %p): returning %d x %d\n",
987 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
988 return ret;
992 /***********************************************************************
993 * GetTextExtentPoint32W [GDI32.@]
995 * Computes width/height for a string.
997 * Computes width and height of the specified string.
999 * RETURNS
1000 * Success: TRUE
1001 * Failure: FALSE
1003 BOOL WINAPI GetTextExtentPoint32W(
1004 HDC hdc, /* [in] Handle of device context */
1005 LPCWSTR str, /* [in] Address of text string */
1006 INT count, /* [in] Number of characters in string */
1007 LPSIZE size) /* [out] Address of structure for string size */
1009 return GetTextExtentExPointW(hdc, str, count, 0, NULL, NULL, size);
1012 /***********************************************************************
1013 * GetTextExtentExPointI [GDI32.@]
1015 * Computes width and height of the array of glyph indices.
1017 * PARAMS
1018 * hdc [I] Handle of device context.
1019 * indices [I] Glyph index array.
1020 * count [I] Number of glyphs in array.
1021 * max_ext [I] Maximum width in glyphs.
1022 * nfit [O] Maximum number of characters.
1023 * dxs [O] Partial string widths.
1024 * size [O] Returned string size.
1026 * RETURNS
1027 * Success: TRUE
1028 * Failure: FALSE
1030 BOOL WINAPI GetTextExtentExPointI( HDC hdc, const WORD *indices, INT count, INT max_ext,
1031 LPINT nfit, LPINT dxs, LPSIZE size )
1033 PHYSDEV dev;
1034 BOOL ret;
1035 DC *dc;
1037 if (count < 0) return FALSE;
1039 dc = get_dc_ptr( hdc );
1040 if (!dc) return FALSE;
1042 dev = GET_DC_PHYSDEV( dc, pGetTextExtentExPointI );
1043 ret = dev->funcs->pGetTextExtentExPointI( dev, indices, count, max_ext, nfit, dxs, size );
1044 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1045 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1046 size->cx += count * dc->charExtra;
1047 release_dc_ptr( dc );
1049 TRACE("(%p %p %d %p): returning %d x %d\n",
1050 hdc, indices, count, size, size->cx, size->cy );
1051 return ret;
1054 /***********************************************************************
1055 * GetTextExtentPointI [GDI32.@]
1057 * Computes width and height of the array of glyph indices.
1059 * PARAMS
1060 * hdc [I] Handle of device context.
1061 * indices [I] Glyph index array.
1062 * count [I] Number of glyphs in array.
1063 * size [O] Returned string size.
1065 * RETURNS
1066 * Success: TRUE
1067 * Failure: FALSE
1069 BOOL WINAPI GetTextExtentPointI( HDC hdc, const WORD *indices, INT count, LPSIZE size )
1071 return GetTextExtentExPointI( hdc, indices, count, 0, NULL, NULL, size );
1075 /***********************************************************************
1076 * GetTextExtentPointA (GDI32.@)
1078 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
1079 LPSIZE size )
1081 TRACE("not bug compatible.\n");
1082 return GetTextExtentPoint32A( hdc, str, count, size );
1085 /***********************************************************************
1086 * GetTextExtentPointW (GDI32.@)
1088 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1089 LPSIZE size )
1091 TRACE("not bug compatible.\n");
1092 return GetTextExtentPoint32W( hdc, str, count, size );
1096 /***********************************************************************
1097 * GetTextExtentExPointA (GDI32.@)
1099 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1100 INT maxExt, LPINT lpnFit,
1101 LPINT alpDx, LPSIZE size )
1103 BOOL ret;
1104 INT wlen;
1105 INT *walpDx = NULL;
1106 LPWSTR p = NULL;
1108 if (count < 0) return FALSE;
1110 if (alpDx)
1112 walpDx = HeapAlloc( GetProcessHeap(), 0, count * sizeof(INT) );
1113 if (!walpDx) return FALSE;
1116 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1117 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
1118 if (walpDx)
1120 INT n = lpnFit ? *lpnFit : wlen;
1121 INT i, j;
1122 for(i = 0, j = 0; i < n; i++, j++)
1124 alpDx[j] = walpDx[i];
1125 if (IsDBCSLeadByte(str[j])) alpDx[++j] = walpDx[i];
1128 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1129 HeapFree( GetProcessHeap(), 0, p );
1130 HeapFree( GetProcessHeap(), 0, walpDx );
1131 return ret;
1135 /***********************************************************************
1136 * GetTextExtentExPointW (GDI32.@)
1138 * Return the size of the string as it would be if it was output properly by
1139 * e.g. TextOut.
1141 * This should include
1142 * - Intercharacter spacing
1143 * - justification spacing (not yet done)
1144 * - kerning? see below
1146 * Kerning. Since kerning would be carried out by the rendering code it should
1147 * be done by the driver. However they don't support it yet. Also I am not
1148 * yet persuaded that (certainly under Win95) any kerning is actually done.
1150 * str: According to MSDN this should be null-terminated. That is not true; a
1151 * null will not terminate it early.
1152 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1153 * than count. I have seen it be either the size of the full string or
1154 * 1 less than the size of the full string. I have not seen it bear any
1155 * resemblance to the portion that would fit.
1156 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1157 * trailing intercharacter spacing and any trailing justification.
1159 * FIXME
1160 * Currently we do this by measuring each character etc. We should do it by
1161 * passing the request to the driver, perhaps by extending the
1162 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1163 * thinking about kerning issues and rounding issues in the justification.
1166 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1167 INT maxExt, LPINT lpnFit,
1168 LPINT alpDx, LPSIZE size )
1170 INT nFit = 0;
1171 LPINT dxs = NULL;
1172 DC *dc;
1173 BOOL ret = FALSE;
1174 TEXTMETRICW tm;
1175 PHYSDEV dev;
1177 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1179 if (count < 0) return FALSE;
1181 dc = get_dc_ptr(hdc);
1182 if (!dc) return FALSE;
1184 GetTextMetricsW(hdc, &tm);
1186 /* If we need to calculate nFit, then we need the partial extents even if
1187 the user hasn't provided us with an array. */
1188 if (lpnFit)
1190 dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]);
1191 if (! dxs)
1193 release_dc_ptr(dc);
1194 SetLastError(ERROR_OUTOFMEMORY);
1195 return FALSE;
1198 else
1199 dxs = alpDx;
1201 dev = GET_DC_PHYSDEV( dc, pGetTextExtentExPoint );
1202 ret = dev->funcs->pGetTextExtentExPoint(dev, str, count, 0, NULL, dxs, size);
1204 /* Perform device size to world size transformations. */
1205 if (ret)
1207 INT extra = dc->charExtra,
1208 breakExtra = dc->breakExtra,
1209 breakRem = dc->breakRem,
1212 if (dxs)
1214 for (i = 0; i < count; ++i)
1216 dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
1217 dxs[i] += (i+1) * extra;
1218 if (count > 1 && (breakExtra || breakRem) && str[i] == tm.tmBreakChar)
1220 dxs[i] += breakExtra;
1221 if (breakRem > 0)
1223 breakRem--;
1224 dxs[i]++;
1227 if (dxs[i] <= maxExt)
1228 ++nFit;
1230 breakRem = dc->breakRem;
1232 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1233 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1235 if (!dxs && count > 1 && (breakExtra || breakRem))
1237 for (i = 0; i < count; i++)
1239 if (str[i] == tm.tmBreakChar)
1241 size->cx += breakExtra;
1242 if (breakRem > 0)
1244 breakRem--;
1245 (size->cx)++;
1252 if (lpnFit)
1253 *lpnFit = nFit;
1255 if (! alpDx)
1256 HeapFree(GetProcessHeap(), 0, dxs);
1258 release_dc_ptr( dc );
1260 TRACE("returning %d %d x %d\n",nFit,size->cx,size->cy);
1261 return ret;
1264 /***********************************************************************
1265 * GetTextMetricsA (GDI32.@)
1267 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1269 TEXTMETRICW tm32;
1271 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1272 FONT_TextMetricWToA( &tm32, metrics );
1273 return TRUE;
1276 /***********************************************************************
1277 * GetTextMetricsW (GDI32.@)
1279 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1281 PHYSDEV physdev;
1282 BOOL ret = FALSE;
1283 DC * dc = get_dc_ptr( hdc );
1284 if (!dc) return FALSE;
1286 physdev = GET_DC_PHYSDEV( dc, pGetTextMetrics );
1287 ret = physdev->funcs->pGetTextMetrics( physdev, metrics );
1289 if (ret)
1291 /* device layer returns values in device units
1292 * therefore we have to convert them to logical */
1294 metrics->tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1295 metrics->tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1297 #define WDPTOLP(x) ((x<0)? \
1298 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1299 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1300 #define HDPTOLP(y) ((y<0)? \
1301 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1302 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1304 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1305 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1306 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1307 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1308 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1309 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1310 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1311 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1312 ret = TRUE;
1313 #undef WDPTOLP
1314 #undef HDPTOLP
1315 TRACE("text metrics:\n"
1316 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1317 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1318 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1319 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1320 " PitchAndFamily = %02x\n"
1321 " --------------------\n"
1322 " InternalLeading = %i\n"
1323 " Ascent = %i\n"
1324 " Descent = %i\n"
1325 " Height = %i\n",
1326 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1327 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1328 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1329 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1330 metrics->tmPitchAndFamily,
1331 metrics->tmInternalLeading,
1332 metrics->tmAscent,
1333 metrics->tmDescent,
1334 metrics->tmHeight );
1336 release_dc_ptr( dc );
1337 return ret;
1341 /***********************************************************************
1342 * GetOutlineTextMetricsA (GDI32.@)
1343 * Gets metrics for TrueType fonts.
1345 * NOTES
1346 * If the supplied buffer isn't big enough Windows partially fills it up to
1347 * its given length and returns that length.
1349 * RETURNS
1350 * Success: Non-zero or size of required buffer
1351 * Failure: 0
1353 UINT WINAPI GetOutlineTextMetricsA(
1354 HDC hdc, /* [in] Handle of device context */
1355 UINT cbData, /* [in] Size of metric data array */
1356 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1358 char buf[512], *ptr;
1359 UINT ret, needed;
1360 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1361 OUTLINETEXTMETRICA *output = lpOTM;
1362 INT left, len;
1364 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1365 return 0;
1366 if(ret > sizeof(buf))
1367 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1368 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1370 needed = sizeof(OUTLINETEXTMETRICA);
1371 if(lpOTMW->otmpFamilyName)
1372 needed += WideCharToMultiByte(CP_ACP, 0,
1373 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1374 NULL, 0, NULL, NULL);
1375 if(lpOTMW->otmpFaceName)
1376 needed += WideCharToMultiByte(CP_ACP, 0,
1377 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1378 NULL, 0, NULL, NULL);
1379 if(lpOTMW->otmpStyleName)
1380 needed += WideCharToMultiByte(CP_ACP, 0,
1381 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1382 NULL, 0, NULL, NULL);
1383 if(lpOTMW->otmpFullName)
1384 needed += WideCharToMultiByte(CP_ACP, 0,
1385 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1386 NULL, 0, NULL, NULL);
1388 if(!lpOTM) {
1389 ret = needed;
1390 goto end;
1393 TRACE("needed = %d\n", needed);
1394 if(needed > cbData)
1395 /* Since the supplied buffer isn't big enough, we'll alloc one
1396 that is and memcpy the first cbData bytes into the lpOTM at
1397 the end. */
1398 output = HeapAlloc(GetProcessHeap(), 0, needed);
1400 ret = output->otmSize = min(needed, cbData);
1401 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1402 output->otmFiller = 0;
1403 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1404 output->otmfsSelection = lpOTMW->otmfsSelection;
1405 output->otmfsType = lpOTMW->otmfsType;
1406 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1407 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1408 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1409 output->otmEMSquare = lpOTMW->otmEMSquare;
1410 output->otmAscent = lpOTMW->otmAscent;
1411 output->otmDescent = lpOTMW->otmDescent;
1412 output->otmLineGap = lpOTMW->otmLineGap;
1413 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1414 output->otmsXHeight = lpOTMW->otmsXHeight;
1415 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1416 output->otmMacAscent = lpOTMW->otmMacAscent;
1417 output->otmMacDescent = lpOTMW->otmMacDescent;
1418 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1419 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1420 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1421 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1422 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1423 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1424 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1425 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1426 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1427 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1430 ptr = (char*)(output + 1);
1431 left = needed - sizeof(*output);
1433 if(lpOTMW->otmpFamilyName) {
1434 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1435 len = WideCharToMultiByte(CP_ACP, 0,
1436 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1437 ptr, left, NULL, NULL);
1438 left -= len;
1439 ptr += len;
1440 } else
1441 output->otmpFamilyName = 0;
1443 if(lpOTMW->otmpFaceName) {
1444 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1445 len = WideCharToMultiByte(CP_ACP, 0,
1446 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1447 ptr, left, NULL, NULL);
1448 left -= len;
1449 ptr += len;
1450 } else
1451 output->otmpFaceName = 0;
1453 if(lpOTMW->otmpStyleName) {
1454 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1455 len = WideCharToMultiByte(CP_ACP, 0,
1456 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1457 ptr, left, NULL, NULL);
1458 left -= len;
1459 ptr += len;
1460 } else
1461 output->otmpStyleName = 0;
1463 if(lpOTMW->otmpFullName) {
1464 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1465 len = WideCharToMultiByte(CP_ACP, 0,
1466 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1467 ptr, left, NULL, NULL);
1468 left -= len;
1469 } else
1470 output->otmpFullName = 0;
1472 assert(left == 0);
1474 if(output != lpOTM) {
1475 memcpy(lpOTM, output, cbData);
1476 HeapFree(GetProcessHeap(), 0, output);
1478 /* check if the string offsets really fit into the provided size */
1479 /* FIXME: should we check string length as well? */
1480 /* make sure that we don't read/write beyond the provided buffer */
1481 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(LPSTR))
1483 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1484 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1487 /* make sure that we don't read/write beyond the provided buffer */
1488 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(LPSTR))
1490 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1491 lpOTM->otmpFaceName = 0; /* doesn't fit */
1494 /* make sure that we don't read/write beyond the provided buffer */
1495 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(LPSTR))
1497 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1498 lpOTM->otmpStyleName = 0; /* doesn't fit */
1501 /* make sure that we don't read/write beyond the provided buffer */
1502 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(LPSTR))
1504 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1505 lpOTM->otmpFullName = 0; /* doesn't fit */
1509 end:
1510 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1511 HeapFree(GetProcessHeap(), 0, lpOTMW);
1513 return ret;
1517 /***********************************************************************
1518 * GetOutlineTextMetricsW [GDI32.@]
1520 UINT WINAPI GetOutlineTextMetricsW(
1521 HDC hdc, /* [in] Handle of device context */
1522 UINT cbData, /* [in] Size of metric data array */
1523 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1525 DC *dc = get_dc_ptr( hdc );
1526 OUTLINETEXTMETRICW *output = lpOTM;
1527 PHYSDEV dev;
1528 UINT ret;
1530 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1531 if(!dc) return 0;
1533 dev = GET_DC_PHYSDEV( dc, pGetOutlineTextMetrics );
1534 ret = dev->funcs->pGetOutlineTextMetrics( dev, cbData, output );
1536 if (lpOTM && ret > cbData)
1538 output = HeapAlloc(GetProcessHeap(), 0, ret);
1539 ret = dev->funcs->pGetOutlineTextMetrics( dev, ret, output );
1542 if (lpOTM && ret)
1544 output->otmTextMetrics.tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1545 output->otmTextMetrics.tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1547 #define WDPTOLP(x) ((x<0)? \
1548 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1549 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1550 #define HDPTOLP(y) ((y<0)? \
1551 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1552 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1554 output->otmTextMetrics.tmHeight = HDPTOLP(output->otmTextMetrics.tmHeight);
1555 output->otmTextMetrics.tmAscent = HDPTOLP(output->otmTextMetrics.tmAscent);
1556 output->otmTextMetrics.tmDescent = HDPTOLP(output->otmTextMetrics.tmDescent);
1557 output->otmTextMetrics.tmInternalLeading = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1558 output->otmTextMetrics.tmExternalLeading = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1559 output->otmTextMetrics.tmAveCharWidth = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1560 output->otmTextMetrics.tmMaxCharWidth = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1561 output->otmTextMetrics.tmOverhang = WDPTOLP(output->otmTextMetrics.tmOverhang);
1562 output->otmAscent = HDPTOLP(output->otmAscent);
1563 output->otmDescent = HDPTOLP(output->otmDescent);
1564 output->otmLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmLineGap));
1565 output->otmsCapEmHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsCapEmHeight));
1566 output->otmsXHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsXHeight));
1567 output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1568 output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1569 output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1570 output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1571 output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1572 output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1573 output->otmMacLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmMacLineGap));
1574 output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1575 output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1576 output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1577 output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1578 output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1579 output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1580 output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1581 output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1582 output->otmsStrikeoutSize = abs(INTERNAL_YDSTOWS(dc,output->otmsStrikeoutSize));
1583 output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1584 output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1585 output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1586 #undef WDPTOLP
1587 #undef HDPTOLP
1588 if(output != lpOTM)
1590 memcpy(lpOTM, output, cbData);
1591 HeapFree(GetProcessHeap(), 0, output);
1592 ret = cbData;
1595 release_dc_ptr(dc);
1596 return ret;
1599 static LPSTR FONT_GetCharsByRangeA(HDC hdc, UINT firstChar, UINT lastChar, PINT pByteLen)
1601 INT i, count = lastChar - firstChar + 1;
1602 UINT mbcp;
1603 UINT c;
1604 LPSTR str;
1606 if (count <= 0)
1607 return NULL;
1609 mbcp = GdiGetCodePage(hdc);
1610 switch (mbcp)
1612 case 932:
1613 case 936:
1614 case 949:
1615 case 950:
1616 case 1361:
1617 if (lastChar > 0xffff)
1618 return NULL;
1619 if ((firstChar ^ lastChar) > 0xff)
1620 return NULL;
1621 break;
1622 default:
1623 if (lastChar > 0xff)
1624 return NULL;
1625 mbcp = 0;
1626 break;
1629 str = HeapAlloc(GetProcessHeap(), 0, count * 2 + 1);
1630 if (str == NULL)
1631 return NULL;
1633 for(i = 0, c = firstChar; c <= lastChar; i++, c++)
1635 if (mbcp) {
1636 if (c > 0xff)
1637 str[i++] = (BYTE)(c >> 8);
1638 if (c <= 0xff && IsDBCSLeadByteEx(mbcp, c))
1639 str[i] = 0x1f; /* FIXME: use default character */
1640 else
1641 str[i] = (BYTE)c;
1643 else
1644 str[i] = (BYTE)c;
1646 str[i] = '\0';
1648 *pByteLen = i;
1650 return str;
1653 /***********************************************************************
1654 * GetCharWidthW (GDI32.@)
1655 * GetCharWidth32W (GDI32.@)
1657 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1658 LPINT buffer )
1660 UINT i;
1661 BOOL ret;
1662 PHYSDEV dev;
1663 DC * dc = get_dc_ptr( hdc );
1665 if (!dc) return FALSE;
1667 dev = GET_DC_PHYSDEV( dc, pGetCharWidth );
1668 ret = dev->funcs->pGetCharWidth( dev, firstChar, lastChar, buffer );
1670 if (ret)
1672 /* convert device units to logical */
1673 for( i = firstChar; i <= lastChar; i++, buffer++ )
1674 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1676 release_dc_ptr( dc );
1677 return ret;
1681 /***********************************************************************
1682 * GetCharWidthA (GDI32.@)
1683 * GetCharWidth32A (GDI32.@)
1685 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1686 LPINT buffer )
1688 INT i, wlen;
1689 LPSTR str;
1690 LPWSTR wstr;
1691 BOOL ret = TRUE;
1693 str = FONT_GetCharsByRangeA(hdc, firstChar, lastChar, &i);
1694 if(str == NULL)
1695 return FALSE;
1697 wstr = FONT_mbtowc(hdc, str, i, &wlen, NULL);
1699 for(i = 0; i < wlen; i++)
1701 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1703 ret = FALSE;
1704 break;
1706 buffer++;
1709 HeapFree(GetProcessHeap(), 0, str);
1710 HeapFree(GetProcessHeap(), 0, wstr);
1712 return ret;
1716 /* helper for nulldrv_ExtTextOut */
1717 static DWORD get_glyph_bitmap( HDC hdc, UINT index, UINT aa_flags,
1718 GLYPHMETRICS *metrics, struct gdi_image_bits *image )
1720 UINT ggo_flags = aa_flags | GGO_GLYPH_INDEX;
1721 static const MAT2 identity = { {0,1}, {0,0}, {0,0}, {0,1} };
1722 UINT indices[3] = {0, 0, 0x20};
1723 int i;
1724 DWORD ret, size;
1725 int stride;
1727 indices[0] = index;
1729 for (i = 0; i < sizeof(indices) / sizeof(indices[0]); i++)
1731 index = indices[i];
1732 ret = GetGlyphOutlineW( hdc, index, ggo_flags, metrics, 0, NULL, &identity );
1733 if (ret != GDI_ERROR) break;
1736 if (ret == GDI_ERROR) return ERROR_NOT_FOUND;
1737 if (!image) return ERROR_SUCCESS;
1739 image->ptr = NULL;
1740 image->free = NULL;
1741 if (!ret) return ERROR_SUCCESS; /* empty glyph */
1743 stride = get_dib_stride( metrics->gmBlackBoxX, 1 );
1744 size = metrics->gmBlackBoxY * stride;
1746 if (!(image->ptr = HeapAlloc( GetProcessHeap(), 0, size ))) return ERROR_OUTOFMEMORY;
1747 image->is_copy = TRUE;
1748 image->free = free_heap_bits;
1750 ret = GetGlyphOutlineW( hdc, index, ggo_flags, metrics, size, image->ptr, &identity );
1751 if (ret == GDI_ERROR)
1753 HeapFree( GetProcessHeap(), 0, image->ptr );
1754 return ERROR_NOT_FOUND;
1756 return ERROR_SUCCESS;
1759 /* helper for nulldrv_ExtTextOut */
1760 static RECT get_total_extents( HDC hdc, INT x, INT y, UINT flags, UINT aa_flags,
1761 LPCWSTR str, UINT count, const INT *dx )
1763 int i;
1764 RECT rect, bounds;
1766 reset_bounds( &bounds );
1767 for (i = 0; i < count; i++)
1769 GLYPHMETRICS metrics;
1771 if (get_glyph_bitmap( hdc, (UINT)str[i], aa_flags, &metrics, NULL )) continue;
1773 rect.left = x + metrics.gmptGlyphOrigin.x;
1774 rect.top = y - metrics.gmptGlyphOrigin.y;
1775 rect.right = rect.left + metrics.gmBlackBoxX;
1776 rect.bottom = rect.top + metrics.gmBlackBoxY;
1777 add_bounds_rect( &bounds, &rect );
1779 if (dx)
1781 if (flags & ETO_PDY)
1783 x += dx[ i * 2 ];
1784 y += dx[ i * 2 + 1];
1786 else x += dx[ i ];
1788 else
1790 x += metrics.gmCellIncX;
1791 y += metrics.gmCellIncY;
1794 return bounds;
1797 /* helper for nulldrv_ExtTextOut */
1798 static void draw_glyph( HDC hdc, INT origin_x, INT origin_y, const GLYPHMETRICS *metrics,
1799 const struct gdi_image_bits *image, const RECT *clip )
1801 static const BYTE masks[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
1802 UINT x, y, i, count, max_count;
1803 BYTE *ptr = image->ptr;
1804 int stride = get_dib_stride( metrics->gmBlackBoxX, 1 );
1805 POINT *pts;
1806 RECT rect, clipped_rect;
1808 rect.left = origin_x + metrics->gmptGlyphOrigin.x;
1809 rect.top = origin_y - metrics->gmptGlyphOrigin.y;
1810 rect.right = rect.left + metrics->gmBlackBoxX;
1811 rect.bottom = rect.top + metrics->gmBlackBoxY;
1812 if (!clip) clipped_rect = rect;
1813 else if (!intersect_rect( &clipped_rect, &rect, clip )) return;
1815 max_count = (metrics->gmBlackBoxX + 1) * metrics->gmBlackBoxY;
1816 pts = HeapAlloc( GetProcessHeap(), 0, max_count * sizeof(*pts) );
1817 if (!pts) return;
1819 count = 0;
1820 ptr += (clipped_rect.top - rect.top) * stride;
1821 for (y = clipped_rect.top; y < clipped_rect.bottom; y++, ptr += stride)
1823 for (x = clipped_rect.left - rect.left; x < clipped_rect.right - rect.left; x++)
1825 while (x < clipped_rect.right - rect.left && !(ptr[x / 8] & masks[x % 8])) x++;
1826 pts[count].x = rect.left + x;
1827 while (x < clipped_rect.right - rect.left && (ptr[x / 8] & masks[x % 8])) x++;
1828 pts[count + 1].x = rect.left + x;
1829 if (pts[count + 1].x > pts[count].x)
1831 pts[count].y = pts[count + 1].y = y;
1832 count += 2;
1836 assert( count <= max_count );
1837 DPtoLP( hdc, pts, count );
1838 for (i = 0; i < count; i += 2) Polyline( hdc, pts + i, 2 );
1839 HeapFree( GetProcessHeap(), 0, pts );
1842 /***********************************************************************
1843 * nulldrv_ExtTextOut
1845 BOOL nulldrv_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags, const RECT *rect,
1846 LPCWSTR str, UINT count, const INT *dx )
1848 DC *dc = get_nulldrv_dc( dev );
1849 UINT aa_flags, i;
1850 DWORD err;
1851 HGDIOBJ orig;
1852 HPEN pen;
1854 if (flags & ETO_OPAQUE)
1856 RECT rc = *rect;
1857 HBRUSH brush = CreateSolidBrush( GetNearestColor( dev->hdc, GetBkColor(dev->hdc) ));
1859 if (brush)
1861 orig = SelectObject( dev->hdc, brush );
1862 DPtoLP( dev->hdc, (POINT *)&rc, 2 );
1863 PatBlt( dev->hdc, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, PATCOPY );
1864 SelectObject( dev->hdc, orig );
1865 DeleteObject( brush );
1869 if (!count) return TRUE;
1871 aa_flags = get_font_aa_flags( dev->hdc );
1873 if (aa_flags != GGO_BITMAP)
1875 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1876 BITMAPINFO *info = (BITMAPINFO *)buffer;
1877 struct gdi_image_bits bits;
1878 struct bitblt_coords src, dst;
1879 PHYSDEV dst_dev;
1881 dst_dev = GET_DC_PHYSDEV( dc, pPutImage );
1882 src.visrect = get_total_extents( dev->hdc, x, y, flags, aa_flags, str, count, dx );
1883 if (flags & ETO_CLIPPED) intersect_rect( &src.visrect, &src.visrect, rect );
1884 if (!clip_visrect( dc, &src.visrect, &src.visrect )) return TRUE;
1886 /* FIXME: check for ETO_OPAQUE and avoid GetImage */
1887 src.x = src.visrect.left;
1888 src.y = src.visrect.top;
1889 src.width = src.visrect.right - src.visrect.left;
1890 src.height = src.visrect.bottom - src.visrect.top;
1891 dst = src;
1892 if ((flags & ETO_OPAQUE) && (src.visrect.left >= rect->left) && (src.visrect.top >= rect->top) &&
1893 (src.visrect.right <= rect->right) && (src.visrect.bottom <= rect->bottom))
1895 /* we can avoid the GetImage, just query the needed format */
1896 memset( &info->bmiHeader, 0, sizeof(info->bmiHeader) );
1897 info->bmiHeader.biSize = sizeof(info->bmiHeader);
1898 info->bmiHeader.biWidth = src.width;
1899 info->bmiHeader.biHeight = -src.height;
1900 err = dst_dev->funcs->pPutImage( dst_dev, 0, info, NULL, NULL, NULL, 0 );
1901 if (!err || err == ERROR_BAD_FORMAT)
1903 /* make the source rectangle relative to the source bits */
1904 src.x = src.y = 0;
1905 src.visrect.left = src.visrect.top = 0;
1906 src.visrect.right = src.width;
1907 src.visrect.bottom = src.height;
1909 bits.ptr = HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( info ));
1910 if (!bits.ptr) return ERROR_OUTOFMEMORY;
1911 bits.is_copy = TRUE;
1912 bits.free = free_heap_bits;
1913 err = ERROR_SUCCESS;
1916 else
1918 PHYSDEV src_dev = GET_DC_PHYSDEV( dc, pGetImage );
1919 err = src_dev->funcs->pGetImage( src_dev, info, &bits, &src );
1920 if (!err && !bits.is_copy)
1922 void *ptr = HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( info ));
1923 if (!ptr)
1925 if (bits.free) bits.free( &bits );
1926 return ERROR_OUTOFMEMORY;
1928 memcpy( ptr, bits.ptr, get_dib_image_size( info ));
1929 if (bits.free) bits.free( &bits );
1930 bits.ptr = ptr;
1931 bits.is_copy = TRUE;
1932 bits.free = free_heap_bits;
1935 if (!err)
1937 /* make x,y relative to the image bits */
1938 x += src.visrect.left - dst.visrect.left;
1939 y += src.visrect.top - dst.visrect.top;
1940 render_aa_text_bitmapinfo( dev->hdc, info, &bits, &src, x, y, flags,
1941 aa_flags, str, count, dx );
1942 err = dst_dev->funcs->pPutImage( dst_dev, 0, info, &bits, &src, &dst, SRCCOPY );
1943 if (bits.free) bits.free( &bits );
1944 return !err;
1948 pen = CreatePen( PS_SOLID, 1, GetTextColor(dev->hdc) );
1949 orig = SelectObject( dev->hdc, pen );
1951 for (i = 0; i < count; i++)
1953 GLYPHMETRICS metrics;
1954 struct gdi_image_bits image;
1956 err = get_glyph_bitmap( dev->hdc, (UINT)str[i], GGO_BITMAP, &metrics, &image );
1957 if (err) continue;
1959 if (image.ptr) draw_glyph( dev->hdc, x, y, &metrics, &image, (flags & ETO_CLIPPED) ? rect : NULL );
1960 if (image.free) image.free( &image );
1962 if (dx)
1964 if (flags & ETO_PDY)
1966 x += dx[ i * 2 ];
1967 y += dx[ i * 2 + 1];
1969 else x += dx[ i ];
1971 else
1973 x += metrics.gmCellIncX;
1974 y += metrics.gmCellIncY;
1978 SelectObject( dev->hdc, orig );
1979 DeleteObject( pen );
1980 return TRUE;
1984 /***********************************************************************
1985 * ExtTextOutA (GDI32.@)
1987 * See ExtTextOutW.
1989 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1990 const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1992 INT wlen;
1993 UINT codepage;
1994 LPWSTR p;
1995 BOOL ret;
1996 LPINT lpDxW = NULL;
1998 if (flags & ETO_GLYPH_INDEX)
1999 return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
2001 p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
2003 if (lpDx) {
2004 unsigned int i = 0, j = 0;
2006 /* allocate enough for a ETO_PDY */
2007 lpDxW = HeapAlloc( GetProcessHeap(), 0, 2*wlen*sizeof(INT));
2008 while(i < count) {
2009 if(IsDBCSLeadByteEx(codepage, str[i]))
2011 if(flags & ETO_PDY)
2013 lpDxW[j++] = lpDx[i * 2] + lpDx[(i + 1) * 2];
2014 lpDxW[j++] = lpDx[i * 2 + 1] + lpDx[(i + 1) * 2 + 1];
2016 else
2017 lpDxW[j++] = lpDx[i] + lpDx[i + 1];
2018 i = i + 2;
2020 else
2022 if(flags & ETO_PDY)
2024 lpDxW[j++] = lpDx[i * 2];
2025 lpDxW[j++] = lpDx[i * 2 + 1];
2027 else
2028 lpDxW[j++] = lpDx[i];
2029 i = i + 1;
2034 ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
2036 HeapFree( GetProcessHeap(), 0, p );
2037 HeapFree( GetProcessHeap(), 0, lpDxW );
2038 return ret;
2042 /***********************************************************************
2043 * ExtTextOutW (GDI32.@)
2045 * Draws text using the currently selected font, background color, and text color.
2048 * PARAMS
2049 * x,y [I] coordinates of string
2050 * flags [I]
2051 * ETO_GRAYED - undocumented on MSDN
2052 * ETO_OPAQUE - use background color for fill the rectangle
2053 * ETO_CLIPPED - clipping text to the rectangle
2054 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
2055 * than encoded characters. Implies ETO_IGNORELANGUAGE
2056 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
2057 * Affects BiDi ordering
2058 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
2059 * ETO_PDY - unimplemented
2060 * ETO_NUMERICSLATIN - unimplemented always assumed -
2061 * do not translate numbers into locale representations
2062 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
2063 * lprect [I] dimensions for clipping or/and opaquing
2064 * str [I] text string
2065 * count [I] number of symbols in string
2066 * lpDx [I] optional parameter with distance between drawing characters
2068 * RETURNS
2069 * Success: TRUE
2070 * Failure: FALSE
2072 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
2073 const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
2075 BOOL ret = FALSE;
2076 LPWSTR reordered_str = (LPWSTR)str;
2077 WORD *glyphs = NULL;
2078 UINT align = GetTextAlign( hdc );
2079 DWORD layout = GetLayout( hdc );
2080 POINT pt;
2081 TEXTMETRICW tm;
2082 LOGFONTW lf;
2083 double cosEsc, sinEsc;
2084 INT char_extra;
2085 SIZE sz;
2086 RECT rc;
2087 BOOL done_extents = FALSE;
2088 POINT *deltas = NULL, width = {0, 0};
2089 DWORD type;
2090 DC * dc = get_dc_ptr( hdc );
2091 PHYSDEV physdev;
2092 INT breakRem;
2093 static int quietfixme = 0;
2095 if (!dc) return FALSE;
2097 breakRem = dc->breakRem;
2099 if (quietfixme == 0 && flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN))
2101 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN unimplemented\n");
2102 quietfixme = 1;
2105 update_dc( dc );
2106 physdev = GET_DC_PHYSDEV( dc, pExtTextOut );
2107 type = GetObjectType(hdc);
2108 if(type == OBJ_METADC || type == OBJ_ENHMETADC)
2110 ret = physdev->funcs->pExtTextOut( physdev, x, y, flags, lprect, str, count, lpDx );
2111 release_dc_ptr( dc );
2112 return ret;
2115 if (!lprect)
2116 flags &= ~ETO_CLIPPED;
2118 if (flags & ETO_RTLREADING) align |= TA_RTLREADING;
2119 if (layout & LAYOUT_RTL)
2121 if ((align & TA_CENTER) != TA_CENTER) align ^= TA_RIGHT;
2122 align ^= TA_RTLREADING;
2125 if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && count > 0 )
2127 INT cGlyphs;
2128 reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
2130 BIDI_Reorder( hdc, str, count, GCP_REORDER,
2131 (align & TA_RTLREADING) ? WINE_GCPW_FORCE_RTL : WINE_GCPW_FORCE_LTR,
2132 reordered_str, count, NULL, &glyphs, &cGlyphs);
2134 flags |= ETO_IGNORELANGUAGE;
2135 if (glyphs)
2137 flags |= ETO_GLYPH_INDEX;
2138 if (cGlyphs != count)
2139 count = cGlyphs;
2142 else if(flags & ETO_GLYPH_INDEX)
2143 glyphs = reordered_str;
2145 TRACE("%p, %d, %d, %08x, %s, %s, %d, %p)\n", hdc, x, y, flags,
2146 wine_dbgstr_rect(lprect), debugstr_wn(str, count), count, lpDx);
2147 TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
2149 if(align & TA_UPDATECP)
2151 GetCurrentPositionEx( hdc, &pt );
2152 x = pt.x;
2153 y = pt.y;
2156 GetTextMetricsW(hdc, &tm);
2157 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
2159 if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
2160 lf.lfEscapement = 0;
2162 if ((dc->GraphicsMode == GM_COMPATIBLE) &&
2163 (dc->vport2WorldValid && dc->xformWorld2Vport.eM11 * dc->xformWorld2Vport.eM22 < 0))
2165 lf.lfEscapement = -lf.lfEscapement;
2168 if(lf.lfEscapement != 0)
2170 cosEsc = cos(lf.lfEscapement * M_PI / 1800);
2171 sinEsc = sin(lf.lfEscapement * M_PI / 1800);
2173 else
2175 cosEsc = 1;
2176 sinEsc = 0;
2179 if(flags & (ETO_CLIPPED | ETO_OPAQUE))
2181 if(!lprect)
2183 if(flags & ETO_GLYPH_INDEX)
2184 GetTextExtentPointI(hdc, glyphs, count, &sz);
2185 else
2186 GetTextExtentPointW(hdc, reordered_str, count, &sz);
2188 done_extents = TRUE;
2189 rc.left = x;
2190 rc.top = y;
2191 rc.right = x + sz.cx;
2192 rc.bottom = y + sz.cy;
2194 else
2196 rc = *lprect;
2199 LPtoDP(hdc, (POINT*)&rc, 2);
2201 if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
2202 if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
2205 if (lprect && (flags & ETO_OPAQUE))
2206 physdev->funcs->pExtTextOut( physdev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL );
2208 if(count == 0)
2210 ret = TRUE;
2211 goto done;
2214 pt.x = x;
2215 pt.y = y;
2216 LPtoDP(hdc, &pt, 1);
2217 x = pt.x;
2218 y = pt.y;
2220 char_extra = GetTextCharacterExtra(hdc);
2221 if(char_extra || dc->breakExtra || breakRem || lpDx || lf.lfEscapement != 0)
2223 UINT i;
2224 SIZE tmpsz;
2225 POINT total = {0, 0}, desired[2];
2227 deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
2228 for(i = 0; i < count; i++)
2230 if(lpDx)
2232 if(flags & ETO_PDY)
2234 deltas[i].x = lpDx[i * 2] + char_extra;
2235 deltas[i].y = -lpDx[i * 2 + 1];
2237 else
2239 deltas[i].x = lpDx[i] + char_extra;
2240 deltas[i].y = 0;
2244 else
2246 if(flags & ETO_GLYPH_INDEX)
2247 GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
2248 else
2249 GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
2251 deltas[i].x = tmpsz.cx;
2252 deltas[i].y = 0;
2255 if (!(flags & ETO_GLYPH_INDEX) && (dc->breakExtra || breakRem) && reordered_str[i] == tm.tmBreakChar)
2257 deltas[i].x = deltas[i].x + dc->breakExtra;
2258 if (breakRem > 0)
2260 breakRem--;
2261 deltas[i].x++;
2264 total.x += deltas[i].x;
2265 total.y += deltas[i].y;
2267 desired[0].x = desired[0].y = 0;
2269 desired[1].x = cosEsc * total.x + sinEsc * total.y;
2270 desired[1].y = -sinEsc * total.x + cosEsc * total.y;
2272 LPtoDP(hdc, desired, 2);
2273 desired[1].x -= desired[0].x;
2274 desired[1].y -= desired[0].y;
2276 if (dc->GraphicsMode == GM_COMPATIBLE)
2278 if (dc->vport2WorldValid && dc->xformWorld2Vport.eM11 < 0)
2279 desired[1].x = -desired[1].x;
2280 if (dc->vport2WorldValid && dc->xformWorld2Vport.eM22 < 0)
2281 desired[1].y = -desired[1].y;
2283 else
2285 if (layout & LAYOUT_RTL) desired[1].x = -desired[1].x;
2288 deltas[i].x = desired[1].x - width.x;
2289 deltas[i].y = desired[1].y - width.y;
2291 width = desired[1];
2293 flags |= ETO_PDY;
2295 else
2297 if(!done_extents)
2299 if(flags & ETO_GLYPH_INDEX)
2300 GetTextExtentPointI(hdc, glyphs, count, &sz);
2301 else
2302 GetTextExtentPointW(hdc, reordered_str, count, &sz);
2303 done_extents = TRUE;
2305 width.x = abs(INTERNAL_XWSTODS(dc, sz.cx));
2306 width.y = 0;
2309 tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
2310 tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
2311 switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
2313 case TA_LEFT:
2314 if (align & TA_UPDATECP)
2316 pt.x = x + width.x;
2317 pt.y = y + width.y;
2318 DPtoLP(hdc, &pt, 1);
2319 MoveToEx(hdc, pt.x, pt.y, NULL);
2321 break;
2323 case TA_CENTER:
2324 x -= width.x / 2;
2325 y -= width.y / 2;
2326 break;
2328 case TA_RIGHT:
2329 x -= width.x;
2330 y -= width.y;
2331 if (align & TA_UPDATECP)
2333 pt.x = x;
2334 pt.y = y;
2335 DPtoLP(hdc, &pt, 1);
2336 MoveToEx(hdc, pt.x, pt.y, NULL);
2338 break;
2341 switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
2343 case TA_TOP:
2344 y += tm.tmAscent * cosEsc;
2345 x += tm.tmAscent * sinEsc;
2346 break;
2348 case TA_BOTTOM:
2349 y -= tm.tmDescent * cosEsc;
2350 x -= tm.tmDescent * sinEsc;
2351 break;
2353 case TA_BASELINE:
2354 break;
2357 if (GetBkMode(hdc) != TRANSPARENT)
2359 if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
2361 if(!(flags & ETO_OPAQUE) || !lprect ||
2362 x < rc.left || x + width.x >= rc.right ||
2363 y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
2365 RECT text_box;
2366 text_box.left = x;
2367 text_box.right = x + width.x;
2368 text_box.top = y - tm.tmAscent;
2369 text_box.bottom = y + tm.tmDescent;
2371 if (flags & ETO_CLIPPED) intersect_rect( &text_box, &text_box, &rc );
2372 if (!is_rect_empty( &text_box ))
2373 physdev->funcs->pExtTextOut( physdev, 0, 0, ETO_OPAQUE, &text_box, NULL, 0, NULL );
2378 if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
2380 HFONT orig_font = dc->hFont, cur_font;
2381 UINT glyph;
2382 INT span = 0;
2383 POINT *offsets = NULL;
2384 unsigned int i;
2386 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2387 for(i = 0; i < count; i++)
2389 WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
2390 if(cur_font != dc->hFont)
2392 if(!offsets)
2394 unsigned int j;
2395 offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
2396 offsets[0].x = offsets[0].y = 0;
2398 if(!deltas)
2400 SIZE tmpsz;
2401 for(j = 1; j < count; j++)
2403 GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
2404 offsets[j].x = offsets[j - 1].x + abs(INTERNAL_XWSTODS(dc, tmpsz.cx));
2405 offsets[j].y = 0;
2408 else
2410 for(j = 1; j < count; j++)
2412 offsets[j].x = offsets[j - 1].x + deltas[j].x;
2413 offsets[j].y = offsets[j - 1].y + deltas[j].y;
2417 if(span)
2419 physdev->funcs->pExtTextOut( physdev, x + offsets[i - span].x,
2420 y + offsets[i - span].y,
2421 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc, glyphs,
2422 span, deltas ? (INT*)(deltas + (i - span)) : NULL);
2423 span = 0;
2425 SelectObject(hdc, cur_font);
2427 glyphs[span++] = glyph;
2429 if(i == count - 1)
2431 ret = physdev->funcs->pExtTextOut(physdev, x + (offsets ? offsets[count - span].x : 0),
2432 y + (offsets ? offsets[count - span].y : 0),
2433 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc, glyphs,
2434 span, deltas ? (INT*)(deltas + (count - span)) : NULL);
2435 SelectObject(hdc, orig_font);
2436 HeapFree(GetProcessHeap(), 0, offsets);
2440 else
2442 if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
2444 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2445 GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
2446 flags |= ETO_GLYPH_INDEX;
2448 ret = physdev->funcs->pExtTextOut( physdev, x, y, (flags & ~ETO_OPAQUE), &rc,
2449 glyphs ? glyphs : reordered_str, count, (INT*)deltas );
2452 done:
2453 HeapFree(GetProcessHeap(), 0, deltas);
2454 if(glyphs != reordered_str)
2455 HeapFree(GetProcessHeap(), 0, glyphs);
2456 if(reordered_str != str)
2457 HeapFree(GetProcessHeap(), 0, reordered_str);
2459 release_dc_ptr( dc );
2461 if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2463 int underlinePos, strikeoutPos;
2464 int underlineWidth, strikeoutWidth;
2465 UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2466 OUTLINETEXTMETRICW* otm = NULL;
2467 POINT pts[5];
2468 HPEN hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2469 HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2471 hbrush = SelectObject(hdc, hbrush);
2473 if(!size)
2475 underlinePos = 0;
2476 underlineWidth = tm.tmAscent / 20 + 1;
2477 strikeoutPos = tm.tmAscent / 2;
2478 strikeoutWidth = underlineWidth;
2480 else
2482 otm = HeapAlloc(GetProcessHeap(), 0, size);
2483 GetOutlineTextMetricsW(hdc, size, otm);
2484 underlinePos = abs( INTERNAL_YWSTODS( dc, otm->otmsUnderscorePosition ));
2485 if (otm->otmsUnderscorePosition < 0) underlinePos = -underlinePos;
2486 underlineWidth = abs( INTERNAL_YWSTODS( dc, otm->otmsUnderscoreSize ));
2487 if (otm->otmsUnderscoreSize < 0) underlineWidth = -underlineWidth;
2488 strikeoutPos = abs( INTERNAL_YWSTODS( dc, otm->otmsStrikeoutPosition ));
2489 if (otm->otmsStrikeoutPosition < 0) strikeoutPos = -strikeoutPos;
2490 strikeoutWidth = abs( INTERNAL_YWSTODS( dc, otm->otmsStrikeoutSize ));
2491 HeapFree(GetProcessHeap(), 0, otm);
2495 if (lf.lfUnderline)
2497 pts[0].x = x - (underlinePos + underlineWidth / 2) * sinEsc;
2498 pts[0].y = y - (underlinePos + underlineWidth / 2) * cosEsc;
2499 pts[1].x = x + width.x - (underlinePos + underlineWidth / 2) * sinEsc;
2500 pts[1].y = y + width.y - (underlinePos + underlineWidth / 2) * cosEsc;
2501 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2502 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2503 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2504 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2505 pts[4].x = pts[0].x;
2506 pts[4].y = pts[0].y;
2507 DPtoLP(hdc, pts, 5);
2508 Polygon(hdc, pts, 5);
2511 if (lf.lfStrikeOut)
2513 pts[0].x = x - (strikeoutPos + strikeoutWidth / 2) * sinEsc;
2514 pts[0].y = y - (strikeoutPos + strikeoutWidth / 2) * cosEsc;
2515 pts[1].x = x + width.x - (strikeoutPos + strikeoutWidth / 2) * sinEsc;
2516 pts[1].y = y + width.y - (strikeoutPos + strikeoutWidth / 2) * cosEsc;
2517 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2518 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2519 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2520 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2521 pts[4].x = pts[0].x;
2522 pts[4].y = pts[0].y;
2523 DPtoLP(hdc, pts, 5);
2524 Polygon(hdc, pts, 5);
2527 SelectObject(hdc, hpen);
2528 hbrush = SelectObject(hdc, hbrush);
2529 DeleteObject(hbrush);
2532 return ret;
2536 /***********************************************************************
2537 * TextOutA (GDI32.@)
2539 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2541 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2545 /***********************************************************************
2546 * TextOutW (GDI32.@)
2548 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2550 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2554 /***********************************************************************
2555 * PolyTextOutA (GDI32.@)
2557 * See PolyTextOutW.
2559 BOOL WINAPI PolyTextOutA( HDC hdc, const POLYTEXTA *pptxt, INT cStrings )
2561 for (; cStrings>0; cStrings--, pptxt++)
2562 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2563 return FALSE;
2564 return TRUE;
2569 /***********************************************************************
2570 * PolyTextOutW (GDI32.@)
2572 * Draw several Strings
2574 * RETURNS
2575 * TRUE: Success.
2576 * FALSE: Failure.
2578 BOOL WINAPI PolyTextOutW( HDC hdc, const POLYTEXTW *pptxt, INT cStrings )
2580 for (; cStrings>0; cStrings--, pptxt++)
2581 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2582 return FALSE;
2583 return TRUE;
2587 /***********************************************************************
2588 * SetMapperFlags (GDI32.@)
2590 DWORD WINAPI SetMapperFlags( HDC hdc, DWORD flags )
2592 DC *dc = get_dc_ptr( hdc );
2593 DWORD ret = GDI_ERROR;
2595 if (dc)
2597 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetMapperFlags );
2598 flags = physdev->funcs->pSetMapperFlags( physdev, flags );
2599 if (flags != GDI_ERROR)
2601 ret = dc->mapperFlags;
2602 dc->mapperFlags = flags;
2604 release_dc_ptr( dc );
2606 return ret;
2609 /***********************************************************************
2610 * GetAspectRatioFilterEx (GDI32.@)
2612 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2614 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2615 return FALSE;
2619 /***********************************************************************
2620 * GetCharABCWidthsA (GDI32.@)
2622 * See GetCharABCWidthsW.
2624 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2625 LPABC abc )
2627 INT i, wlen;
2628 LPSTR str;
2629 LPWSTR wstr;
2630 BOOL ret = TRUE;
2632 str = FONT_GetCharsByRangeA(hdc, firstChar, lastChar, &i);
2633 if (str == NULL)
2634 return FALSE;
2636 wstr = FONT_mbtowc(hdc, str, i, &wlen, NULL);
2637 if (wstr == NULL)
2639 HeapFree(GetProcessHeap(), 0, str);
2640 return FALSE;
2643 for(i = 0; i < wlen; i++)
2645 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2647 ret = FALSE;
2648 break;
2650 abc++;
2653 HeapFree(GetProcessHeap(), 0, str);
2654 HeapFree(GetProcessHeap(), 0, wstr);
2656 return ret;
2660 /******************************************************************************
2661 * GetCharABCWidthsW [GDI32.@]
2663 * Retrieves widths of characters in range.
2665 * PARAMS
2666 * hdc [I] Handle of device context
2667 * firstChar [I] First character in range to query
2668 * lastChar [I] Last character in range to query
2669 * abc [O] Address of character-width structure
2671 * NOTES
2672 * Only works with TrueType fonts
2674 * RETURNS
2675 * Success: TRUE
2676 * Failure: FALSE
2678 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2679 LPABC abc )
2681 DC *dc = get_dc_ptr(hdc);
2682 PHYSDEV dev;
2683 unsigned int i;
2684 BOOL ret;
2685 TEXTMETRICW tm;
2687 if (!dc) return FALSE;
2689 if (!abc)
2691 release_dc_ptr( dc );
2692 return FALSE;
2695 /* unlike GetCharABCWidthsFloatW, this one is supposed to fail on non-TrueType fonts */
2696 dev = GET_DC_PHYSDEV( dc, pGetTextMetrics );
2697 if (!dev->funcs->pGetTextMetrics( dev, &tm ) || !(tm.tmPitchAndFamily & TMPF_TRUETYPE))
2699 release_dc_ptr( dc );
2700 return FALSE;
2703 dev = GET_DC_PHYSDEV( dc, pGetCharABCWidths );
2704 ret = dev->funcs->pGetCharABCWidths( dev, firstChar, lastChar, abc );
2705 if (ret)
2707 /* convert device units to logical */
2708 for( i = firstChar; i <= lastChar; i++, abc++ ) {
2709 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2710 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2711 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2715 release_dc_ptr( dc );
2716 return ret;
2720 /******************************************************************************
2721 * GetCharABCWidthsI [GDI32.@]
2723 * Retrieves widths of characters in range.
2725 * PARAMS
2726 * hdc [I] Handle of device context
2727 * firstChar [I] First glyphs in range to query
2728 * count [I] Last glyphs in range to query
2729 * pgi [i] Array of glyphs to query
2730 * abc [O] Address of character-width structure
2732 * NOTES
2733 * Only works with TrueType fonts
2735 * RETURNS
2736 * Success: TRUE
2737 * Failure: FALSE
2739 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2740 LPWORD pgi, LPABC abc)
2742 DC *dc = get_dc_ptr(hdc);
2743 PHYSDEV dev;
2744 unsigned int i;
2745 BOOL ret;
2747 if (!dc) return FALSE;
2749 if (!abc)
2751 release_dc_ptr( dc );
2752 return FALSE;
2755 dev = GET_DC_PHYSDEV( dc, pGetCharABCWidthsI );
2756 ret = dev->funcs->pGetCharABCWidthsI( dev, firstChar, count, pgi, abc );
2757 if (ret)
2759 /* convert device units to logical */
2760 for( i = 0; i < count; i++, abc++ ) {
2761 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2762 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2763 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2767 release_dc_ptr( dc );
2768 return ret;
2772 /***********************************************************************
2773 * GetGlyphOutlineA (GDI32.@)
2775 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2776 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2777 LPVOID lpBuffer, const MAT2 *lpmat2 )
2779 if (!lpmat2) return GDI_ERROR;
2781 if(!(fuFormat & GGO_GLYPH_INDEX)) {
2782 UINT cp;
2783 int len;
2784 char mbchs[2];
2786 cp = GdiGetCodePage(hdc);
2787 if (IsDBCSLeadByteEx(cp, uChar >> 8)) {
2788 len = 2;
2789 mbchs[0] = (uChar & 0xff00) >> 8;
2790 mbchs[1] = (uChar & 0xff);
2791 } else {
2792 len = 1;
2793 mbchs[0] = (uChar & 0xff);
2795 uChar = 0;
2796 MultiByteToWideChar(cp, 0, mbchs, len, (LPWSTR)&uChar, 1);
2799 return GetGlyphOutlineW(hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer,
2800 lpmat2);
2803 /***********************************************************************
2804 * GetGlyphOutlineW (GDI32.@)
2806 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2807 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2808 LPVOID lpBuffer, const MAT2 *lpmat2 )
2810 DC *dc;
2811 DWORD ret;
2812 PHYSDEV dev;
2814 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2815 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2817 if (!lpmat2) return GDI_ERROR;
2819 dc = get_dc_ptr(hdc);
2820 if(!dc) return GDI_ERROR;
2822 dev = GET_DC_PHYSDEV( dc, pGetGlyphOutline );
2823 ret = dev->funcs->pGetGlyphOutline( dev, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2824 release_dc_ptr( dc );
2825 return ret;
2829 /***********************************************************************
2830 * CreateScalableFontResourceA (GDI32.@)
2832 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2833 LPCSTR lpszResourceFile,
2834 LPCSTR lpszFontFile,
2835 LPCSTR lpszCurrentPath )
2837 LPWSTR lpszResourceFileW = NULL;
2838 LPWSTR lpszFontFileW = NULL;
2839 LPWSTR lpszCurrentPathW = NULL;
2840 int len;
2841 BOOL ret;
2843 if (lpszResourceFile)
2845 len = MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, NULL, 0);
2846 lpszResourceFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2847 MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, lpszResourceFileW, len);
2850 if (lpszFontFile)
2852 len = MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, NULL, 0);
2853 lpszFontFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2854 MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, lpszFontFileW, len);
2857 if (lpszCurrentPath)
2859 len = MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, NULL, 0);
2860 lpszCurrentPathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2861 MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, lpszCurrentPathW, len);
2864 ret = CreateScalableFontResourceW(fHidden, lpszResourceFileW,
2865 lpszFontFileW, lpszCurrentPathW);
2867 HeapFree(GetProcessHeap(), 0, lpszResourceFileW);
2868 HeapFree(GetProcessHeap(), 0, lpszFontFileW);
2869 HeapFree(GetProcessHeap(), 0, lpszCurrentPathW);
2871 return ret;
2874 /***********************************************************************
2875 * CreateScalableFontResourceW (GDI32.@)
2877 BOOL WINAPI CreateScalableFontResourceW( DWORD hidden, LPCWSTR resource_file,
2878 LPCWSTR font_file, LPCWSTR font_path )
2880 TRACE("(%d, %s, %s, %s)\n", hidden, debugstr_w(resource_file),
2881 debugstr_w(font_file), debugstr_w(font_path) );
2883 return WineEngCreateScalableFontResource( hidden, resource_file,
2884 font_file, font_path );
2887 /*************************************************************************
2888 * GetKerningPairsA (GDI32.@)
2890 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2891 LPKERNINGPAIR kern_pairA )
2893 UINT cp;
2894 CPINFO cpi;
2895 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2896 KERNINGPAIR *kern_pairW;
2898 if (!cPairs && kern_pairA)
2900 SetLastError(ERROR_INVALID_PARAMETER);
2901 return 0;
2904 cp = GdiGetCodePage(hDC);
2906 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2907 * to fail on an invalid character for CP_SYMBOL.
2909 cpi.DefaultChar[0] = 0;
2910 if (cp != CP_SYMBOL && !GetCPInfo(cp, &cpi))
2912 FIXME("Can't find codepage %u info\n", cp);
2913 return 0;
2916 total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2917 if (!total_kern_pairs) return 0;
2919 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2920 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2922 for (i = 0; i < total_kern_pairs; i++)
2924 char first, second;
2926 if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2927 continue;
2929 if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2930 continue;
2932 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2933 continue;
2935 if (kern_pairA)
2937 if (kern_pairs_copied >= cPairs) break;
2939 kern_pairA->wFirst = (BYTE)first;
2940 kern_pairA->wSecond = (BYTE)second;
2941 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2942 kern_pairA++;
2944 kern_pairs_copied++;
2947 HeapFree(GetProcessHeap(), 0, kern_pairW);
2949 return kern_pairs_copied;
2952 /*************************************************************************
2953 * GetKerningPairsW (GDI32.@)
2955 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2956 LPKERNINGPAIR lpKerningPairs )
2958 DC *dc;
2959 DWORD ret;
2960 PHYSDEV dev;
2962 TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2964 if (!cPairs && lpKerningPairs)
2966 SetLastError(ERROR_INVALID_PARAMETER);
2967 return 0;
2970 dc = get_dc_ptr(hDC);
2971 if (!dc) return 0;
2973 dev = GET_DC_PHYSDEV( dc, pGetKerningPairs );
2974 ret = dev->funcs->pGetKerningPairs( dev, cPairs, lpKerningPairs );
2975 release_dc_ptr( dc );
2976 return ret;
2979 /*************************************************************************
2980 * TranslateCharsetInfo [GDI32.@]
2982 * Fills a CHARSETINFO structure for a character set, code page, or
2983 * font. This allows making the correspondence between different labels
2984 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2985 * of the same encoding.
2987 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2988 * only one codepage should be set in *lpSrc.
2990 * RETURNS
2991 * TRUE on success, FALSE on failure.
2994 BOOL WINAPI TranslateCharsetInfo(
2995 LPDWORD lpSrc, /* [in]
2996 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2997 if flags == TCI_SRCCHARSET: a character set value
2998 if flags == TCI_SRCCODEPAGE: a code page value
3000 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
3001 DWORD flags /* [in] determines interpretation of lpSrc */)
3003 int index = 0;
3004 switch (flags) {
3005 case TCI_SRCFONTSIG:
3006 while (index < MAXTCIINDEX && !(*lpSrc>>index & 0x0001)) index++;
3007 break;
3008 case TCI_SRCCODEPAGE:
3009 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciACP) index++;
3010 break;
3011 case TCI_SRCCHARSET:
3012 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciCharset) index++;
3013 break;
3014 default:
3015 return FALSE;
3017 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
3018 *lpCs = FONT_tci[index];
3019 return TRUE;
3022 /*************************************************************************
3023 * GetFontLanguageInfo (GDI32.@)
3025 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
3027 FONTSIGNATURE fontsig;
3028 static const DWORD GCP_DBCS_MASK=0x003F0000,
3029 GCP_DIACRITIC_MASK=0x00000000,
3030 FLI_GLYPHS_MASK=0x00000000,
3031 GCP_GLYPHSHAPE_MASK=0x00000040,
3032 GCP_KASHIDA_MASK=0x00000000,
3033 GCP_LIGATE_MASK=0x00000000,
3034 GCP_USEKERNING_MASK=0x00000000,
3035 GCP_REORDER_MASK=0x00000060;
3037 DWORD result=0;
3039 GetTextCharsetInfo( hdc, &fontsig, 0 );
3040 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
3042 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
3043 result|=GCP_DBCS;
3045 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
3046 result|=GCP_DIACRITIC;
3048 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
3049 result|=FLI_GLYPHS;
3051 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
3052 result|=GCP_GLYPHSHAPE;
3054 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
3055 result|=GCP_KASHIDA;
3057 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
3058 result|=GCP_LIGATE;
3060 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
3061 result|=GCP_USEKERNING;
3063 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
3064 if( GetTextAlign( hdc) & TA_RTLREADING )
3065 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
3066 result|=GCP_REORDER;
3068 return result;
3072 /*************************************************************************
3073 * GetFontData [GDI32.@]
3075 * Retrieve data for TrueType font.
3077 * RETURNS
3079 * success: Number of bytes returned
3080 * failure: GDI_ERROR
3082 * NOTES
3084 * Calls SetLastError()
3087 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
3088 LPVOID buffer, DWORD length)
3090 DC *dc = get_dc_ptr(hdc);
3091 PHYSDEV dev;
3092 DWORD ret;
3094 if(!dc) return GDI_ERROR;
3096 dev = GET_DC_PHYSDEV( dc, pGetFontData );
3097 ret = dev->funcs->pGetFontData( dev, table, offset, buffer, length );
3098 release_dc_ptr( dc );
3099 return ret;
3102 /*************************************************************************
3103 * GetGlyphIndicesA [GDI32.@]
3105 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
3106 LPWORD pgi, DWORD flags)
3108 DWORD ret;
3109 WCHAR *lpstrW;
3110 INT countW;
3112 TRACE("(%p, %s, %d, %p, 0x%x)\n",
3113 hdc, debugstr_an(lpstr, count), count, pgi, flags);
3115 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
3116 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
3117 HeapFree(GetProcessHeap(), 0, lpstrW);
3119 return ret;
3122 /*************************************************************************
3123 * GetGlyphIndicesW [GDI32.@]
3125 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
3126 LPWORD pgi, DWORD flags)
3128 DC *dc = get_dc_ptr(hdc);
3129 PHYSDEV dev;
3130 DWORD ret;
3132 TRACE("(%p, %s, %d, %p, 0x%x)\n",
3133 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
3135 if(!dc) return GDI_ERROR;
3137 dev = GET_DC_PHYSDEV( dc, pGetGlyphIndices );
3138 ret = dev->funcs->pGetGlyphIndices( dev, lpstr, count, pgi, flags );
3139 release_dc_ptr( dc );
3140 return ret;
3143 /*************************************************************************
3144 * GetCharacterPlacementA [GDI32.@]
3146 * See GetCharacterPlacementW.
3148 * NOTES:
3149 * the web browser control of ie4 calls this with dwFlags=0
3151 DWORD WINAPI
3152 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
3153 INT nMaxExtent, GCP_RESULTSA *lpResults,
3154 DWORD dwFlags)
3156 WCHAR *lpStringW;
3157 INT uCountW;
3158 GCP_RESULTSW resultsW;
3159 DWORD ret;
3160 UINT font_cp;
3162 TRACE("%s, %d, %d, 0x%08x\n",
3163 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
3165 /* both structs are equal in size */
3166 memcpy(&resultsW, lpResults, sizeof(resultsW));
3168 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
3169 if(lpResults->lpOutString)
3170 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
3172 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
3174 lpResults->nGlyphs = resultsW.nGlyphs;
3175 lpResults->nMaxFit = resultsW.nMaxFit;
3177 if(lpResults->lpOutString) {
3178 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
3179 lpResults->lpOutString, uCount, NULL, NULL );
3182 HeapFree(GetProcessHeap(), 0, lpStringW);
3183 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
3185 return ret;
3188 /*************************************************************************
3189 * GetCharacterPlacementW [GDI32.@]
3191 * Retrieve information about a string. This includes the width, reordering,
3192 * Glyphing and so on.
3194 * RETURNS
3196 * The width and height of the string if successful, 0 if failed.
3198 * BUGS
3200 * All flags except GCP_REORDER are not yet implemented.
3201 * Reordering is not 100% compliant to the Windows BiDi method.
3202 * Caret positioning is not yet implemented for BiDi.
3203 * Classes are not yet implemented.
3206 DWORD WINAPI
3207 GetCharacterPlacementW(
3208 HDC hdc, /* [in] Device context for which the rendering is to be done */
3209 LPCWSTR lpString, /* [in] The string for which information is to be returned */
3210 INT uCount, /* [in] Number of WORDS in string. */
3211 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
3212 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
3213 DWORD dwFlags /* [in] Flags specifying how to process the string */
3216 DWORD ret=0;
3217 SIZE size;
3218 UINT i, nSet;
3220 TRACE("%s, %d, %d, 0x%08x\n",
3221 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
3223 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
3224 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
3225 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
3226 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
3227 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
3229 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08x ignored\n", dwFlags);
3230 if(lpResults->lpClass) FIXME("classes not implemented\n");
3231 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
3232 FIXME("Caret positions for complex scripts not implemented\n");
3234 nSet = (UINT)uCount;
3235 if(nSet > lpResults->nGlyphs)
3236 nSet = lpResults->nGlyphs;
3238 /* return number of initialized fields */
3239 lpResults->nGlyphs = nSet;
3241 if((dwFlags&GCP_REORDER)==0 )
3243 /* Treat the case where no special handling was requested in a fastpath way */
3244 /* copy will do if the GCP_REORDER flag is not set */
3245 if(lpResults->lpOutString)
3246 memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
3248 if(lpResults->lpOrder)
3250 for(i = 0; i < nSet; i++)
3251 lpResults->lpOrder[i] = i;
3253 } else
3255 BIDI_Reorder(NULL, lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
3256 nSet, lpResults->lpOrder, NULL, NULL );
3259 /* FIXME: Will use the placement chars */
3260 if (lpResults->lpDx)
3262 int c;
3263 for (i = 0; i < nSet; i++)
3265 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
3266 lpResults->lpDx[i]= c;
3270 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
3272 int pos = 0;
3274 lpResults->lpCaretPos[0] = 0;
3275 for (i = 1; i < nSet; i++)
3276 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
3277 lpResults->lpCaretPos[i] = (pos += size.cx);
3280 if(lpResults->lpGlyphs)
3281 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
3283 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
3284 ret = MAKELONG(size.cx, size.cy);
3286 return ret;
3289 /*************************************************************************
3290 * GetCharABCWidthsFloatA [GDI32.@]
3292 * See GetCharABCWidthsFloatW.
3294 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3296 INT i, wlen;
3297 LPSTR str;
3298 LPWSTR wstr;
3299 BOOL ret = TRUE;
3301 str = FONT_GetCharsByRangeA(hdc, first, last, &i);
3302 if (str == NULL)
3303 return FALSE;
3305 wstr = FONT_mbtowc( hdc, str, i, &wlen, NULL );
3307 for (i = 0; i < wlen; i++)
3309 if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
3311 ret = FALSE;
3312 break;
3314 abcf++;
3317 HeapFree( GetProcessHeap(), 0, str );
3318 HeapFree( GetProcessHeap(), 0, wstr );
3320 return ret;
3323 /*************************************************************************
3324 * GetCharABCWidthsFloatW [GDI32.@]
3326 * Retrieves widths of a range of characters.
3328 * PARAMS
3329 * hdc [I] Handle to device context.
3330 * first [I] First character in range to query.
3331 * last [I] Last character in range to query.
3332 * abcf [O] Array of LPABCFLOAT structures.
3334 * RETURNS
3335 * Success: TRUE
3336 * Failure: FALSE
3338 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3340 UINT i;
3341 ABC *abc;
3342 PHYSDEV dev;
3343 BOOL ret = FALSE;
3344 DC *dc = get_dc_ptr( hdc );
3346 TRACE("%p, %d, %d, %p\n", hdc, first, last, abcf);
3348 if (!dc) return FALSE;
3350 if (!abcf) goto done;
3351 if (!(abc = HeapAlloc( GetProcessHeap(), 0, (last - first + 1) * sizeof(*abc) ))) goto done;
3353 dev = GET_DC_PHYSDEV( dc, pGetCharABCWidths );
3354 ret = dev->funcs->pGetCharABCWidths( dev, first, last, abc );
3355 if (ret)
3357 /* convert device units to logical */
3358 for (i = first; i <= last; i++, abcf++)
3360 abcf->abcfA = abc[i - first].abcA * dc->xformVport2World.eM11;
3361 abcf->abcfB = abc[i - first].abcB * dc->xformVport2World.eM11;
3362 abcf->abcfC = abc[i - first].abcC * dc->xformVport2World.eM11;
3365 HeapFree( GetProcessHeap(), 0, abc );
3367 done:
3368 release_dc_ptr( dc );
3369 return ret;
3372 /*************************************************************************
3373 * GetCharWidthFloatA [GDI32.@]
3375 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
3376 UINT iLastChar, PFLOAT pxBuffer)
3378 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3379 return 0;
3382 /*************************************************************************
3383 * GetCharWidthFloatW [GDI32.@]
3385 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
3386 UINT iLastChar, PFLOAT pxBuffer)
3388 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3389 return 0;
3393 /***********************************************************************
3395 * Font Resource API *
3397 ***********************************************************************/
3399 /***********************************************************************
3400 * AddFontResourceA (GDI32.@)
3402 INT WINAPI AddFontResourceA( LPCSTR str )
3404 return AddFontResourceExA( str, 0, NULL);
3407 /***********************************************************************
3408 * AddFontResourceW (GDI32.@)
3410 INT WINAPI AddFontResourceW( LPCWSTR str )
3412 return AddFontResourceExW(str, 0, NULL);
3416 /***********************************************************************
3417 * AddFontResourceExA (GDI32.@)
3419 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3421 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3422 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3423 INT ret;
3425 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3426 ret = AddFontResourceExW(strW, fl, pdv);
3427 HeapFree(GetProcessHeap(), 0, strW);
3428 return ret;
3431 static BOOL CALLBACK load_enumed_resource(HMODULE hModule, LPCWSTR type, LPWSTR name, LONG_PTR lParam)
3433 HRSRC rsrc = FindResourceW(hModule, name, type);
3434 HGLOBAL hMem = LoadResource(hModule, rsrc);
3435 LPVOID *pMem = LockResource(hMem);
3436 int *num_total = (int *)lParam;
3437 DWORD num_in_res;
3439 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type));
3440 if (!AddFontMemResourceEx(pMem, SizeofResource(hModule, rsrc), NULL, &num_in_res))
3442 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule, hMem);
3443 return FALSE;
3446 *num_total += num_in_res;
3447 return TRUE;
3450 static void *map_file( const WCHAR *filename, LARGE_INTEGER *size )
3452 HANDLE file, mapping;
3453 void *ptr;
3455 file = CreateFileW( filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
3456 if (file == INVALID_HANDLE_VALUE) return NULL;
3458 if (!GetFileSizeEx( file, size ) || size->u.HighPart)
3460 CloseHandle( file );
3461 return NULL;
3464 mapping = CreateFileMappingW( file, NULL, PAGE_READONLY, 0, 0, NULL );
3465 CloseHandle( file );
3466 if (!mapping) return NULL;
3468 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 );
3469 CloseHandle( mapping );
3471 return ptr;
3474 static WCHAR *get_scalable_filename( const WCHAR *res )
3476 LARGE_INTEGER size;
3477 BYTE *ptr = map_file( res, &size );
3478 const IMAGE_DOS_HEADER *dos;
3479 const IMAGE_OS2_HEADER *ne;
3480 WCHAR *name = NULL;
3481 WORD rsrc_off, align, type_id, count;
3482 DWORD res_off, res_len, i;
3483 int len;
3485 if (!ptr) return NULL;
3487 if (size.u.LowPart < sizeof( *dos )) goto fail;
3488 dos = (const IMAGE_DOS_HEADER *)ptr;
3489 if (dos->e_magic != IMAGE_DOS_SIGNATURE) goto fail;
3490 if (size.u.LowPart < dos->e_lfanew + sizeof( *ne )) goto fail;
3491 ne = (const IMAGE_OS2_HEADER *)(ptr + dos->e_lfanew);
3492 rsrc_off = dos->e_lfanew + ne->ne_rsrctab;
3493 if (size.u.LowPart < rsrc_off + 10) goto fail;
3494 align = *(WORD *)(ptr + rsrc_off);
3495 rsrc_off += 2;
3496 type_id = *(WORD *)(ptr + rsrc_off);
3497 while (type_id && type_id != 0x80cc)
3499 count = *(WORD *)(ptr + rsrc_off + 2);
3500 rsrc_off += 8 + count * 12;
3501 if (size.u.LowPart < rsrc_off + 8) goto fail;
3502 type_id = *(WORD *)(ptr + rsrc_off);
3504 if (!type_id) goto fail;
3505 count = *(WORD *)(ptr + rsrc_off + 2);
3506 if (size.u.LowPart < rsrc_off + 8 + count * 12) goto fail;
3508 res_off = *(WORD *)(ptr + rsrc_off + 8) << align;
3509 res_len = *(WORD *)(ptr + rsrc_off + 10) << align;
3510 if (size.u.LowPart < res_off + res_len) goto fail;
3512 for (i = 0; i < res_len; i++)
3513 if (ptr[ res_off + i ] == 0) break;
3514 if (i == res_len) goto fail;
3516 len = MultiByteToWideChar( CP_ACP, 0, (char *)ptr + res_off, -1, NULL, 0 );
3517 name = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
3518 if (name) MultiByteToWideChar( CP_ACP, 0, (char *)ptr + res_off, -1, name, len );
3520 fail:
3521 UnmapViewOfFile( ptr );
3522 return name;
3525 /***********************************************************************
3526 * AddFontResourceExW (GDI32.@)
3528 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3530 int ret = WineEngAddFontResourceEx(str, fl, pdv);
3531 WCHAR *filename;
3533 if (ret == 0)
3535 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3536 HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
3537 if (hModule != NULL)
3539 int num_resources = 0;
3540 LPWSTR rt_font = (LPWSTR)((ULONG_PTR)8); /* we don't want to include winuser.h */
3542 TRACE("WineEngAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3543 wine_dbgstr_w(str));
3544 if (EnumResourceNamesW(hModule, rt_font, load_enumed_resource, (LONG_PTR)&num_resources))
3545 ret = num_resources;
3546 FreeLibrary(hModule);
3548 else if ((filename = get_scalable_filename( str )) != NULL)
3550 ret = WineEngAddFontResourceEx( filename, fl, pdv );
3551 HeapFree( GetProcessHeap(), 0, filename );
3554 return ret;
3557 /***********************************************************************
3558 * RemoveFontResourceA (GDI32.@)
3560 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3562 return RemoveFontResourceExA(str, 0, 0);
3565 /***********************************************************************
3566 * RemoveFontResourceW (GDI32.@)
3568 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3570 return RemoveFontResourceExW(str, 0, 0);
3573 /***********************************************************************
3574 * AddFontMemResourceEx (GDI32.@)
3576 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3578 HANDLE ret;
3579 DWORD num_fonts;
3581 if (!pbFont || !cbFont || !pcFonts)
3583 SetLastError(ERROR_INVALID_PARAMETER);
3584 return NULL;
3587 ret = WineEngAddFontMemResourceEx(pbFont, cbFont, pdv, &num_fonts);
3588 if (ret)
3590 __TRY
3592 *pcFonts = num_fonts;
3594 __EXCEPT_PAGE_FAULT
3596 WARN("page fault while writing to *pcFonts (%p)\n", pcFonts);
3597 RemoveFontMemResourceEx(ret);
3598 ret = 0;
3600 __ENDTRY
3602 return ret;
3605 /***********************************************************************
3606 * RemoveFontMemResourceEx (GDI32.@)
3608 BOOL WINAPI RemoveFontMemResourceEx( HANDLE fh )
3610 FIXME("(%p) stub\n", fh);
3611 return TRUE;
3614 /***********************************************************************
3615 * RemoveFontResourceExA (GDI32.@)
3617 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3619 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3620 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3621 INT ret;
3623 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3624 ret = RemoveFontResourceExW(strW, fl, pdv);
3625 HeapFree(GetProcessHeap(), 0, strW);
3626 return ret;
3629 /***********************************************************************
3630 * RemoveFontResourceExW (GDI32.@)
3632 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3634 return WineEngRemoveFontResourceEx(str, fl, pdv);
3637 /***********************************************************************
3638 * GetTextCharset (GDI32.@)
3640 UINT WINAPI GetTextCharset(HDC hdc)
3642 /* MSDN docs say this is equivalent */
3643 return GetTextCharsetInfo(hdc, NULL, 0);
3646 /***********************************************************************
3647 * GetTextCharsetInfo (GDI32.@)
3649 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3651 UINT ret = DEFAULT_CHARSET;
3652 DC *dc = get_dc_ptr(hdc);
3653 PHYSDEV dev;
3655 if (dc)
3657 dev = GET_DC_PHYSDEV( dc, pGetTextCharsetInfo );
3658 ret = dev->funcs->pGetTextCharsetInfo( dev, fs, flags );
3659 release_dc_ptr( dc );
3662 if (ret == DEFAULT_CHARSET && fs)
3663 memset(fs, 0, sizeof(FONTSIGNATURE));
3664 return ret;
3667 /***********************************************************************
3668 * GdiGetCharDimensions (GDI32.@)
3670 * Gets the average width of the characters in the English alphabet.
3672 * PARAMS
3673 * hdc [I] Handle to the device context to measure on.
3674 * lptm [O] Pointer to memory to store the text metrics into.
3675 * height [O] On exit, the maximum height of characters in the English alphabet.
3677 * RETURNS
3678 * The average width of characters in the English alphabet.
3680 * NOTES
3681 * This function is used by the dialog manager to get the size of a dialog
3682 * unit. It should also be used by other pieces of code that need to know
3683 * the size of a dialog unit in logical units without having access to the
3684 * window handle of the dialog.
3685 * Windows caches the font metrics from this function, but we don't and
3686 * there doesn't appear to be an immediate advantage to do so.
3688 * SEE ALSO
3689 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3691 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3693 SIZE sz;
3694 static const WCHAR alphabet[] = {
3695 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3696 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3697 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3699 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3701 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3703 if (height) *height = sz.cy;
3704 return (sz.cx / 26 + 1) / 2;
3707 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3709 FIXME("(%d): stub\n", fEnableEUDC);
3710 return FALSE;
3713 /***********************************************************************
3714 * GetCharWidthI (GDI32.@)
3716 * Retrieve widths of characters.
3718 * PARAMS
3719 * hdc [I] Handle to a device context.
3720 * first [I] First glyph in range to query.
3721 * count [I] Number of glyph indices to query.
3722 * glyphs [I] Array of glyphs to query.
3723 * buffer [O] Buffer to receive character widths.
3725 * NOTES
3726 * Only works with TrueType fonts.
3728 * RETURNS
3729 * Success: TRUE
3730 * Failure: FALSE
3732 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3734 ABC *abc;
3735 unsigned int i;
3737 TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3739 if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3740 return FALSE;
3742 if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3744 HeapFree(GetProcessHeap(), 0, abc);
3745 return FALSE;
3748 for (i = 0; i < count; i++)
3749 buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3751 HeapFree(GetProcessHeap(), 0, abc);
3752 return TRUE;
3755 /***********************************************************************
3756 * GetFontUnicodeRanges (GDI32.@)
3758 * Retrieve a list of supported Unicode characters in a font.
3760 * PARAMS
3761 * hdc [I] Handle to a device context.
3762 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3764 * RETURNS
3765 * Success: Number of bytes written to the buffer pointed to by lpgs.
3766 * Failure: 0
3769 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3771 DWORD ret;
3772 PHYSDEV dev;
3773 DC *dc = get_dc_ptr(hdc);
3775 TRACE("(%p, %p)\n", hdc, lpgs);
3777 if (!dc) return 0;
3779 dev = GET_DC_PHYSDEV( dc, pGetFontUnicodeRanges );
3780 ret = dev->funcs->pGetFontUnicodeRanges( dev, lpgs );
3781 release_dc_ptr(dc);
3782 return ret;
3786 /*************************************************************
3787 * FontIsLinked (GDI32.@)
3789 BOOL WINAPI FontIsLinked(HDC hdc)
3791 DC *dc = get_dc_ptr(hdc);
3792 PHYSDEV dev;
3793 BOOL ret;
3795 if (!dc) return FALSE;
3796 dev = GET_DC_PHYSDEV( dc, pFontIsLinked );
3797 ret = dev->funcs->pFontIsLinked( dev );
3798 release_dc_ptr(dc);
3799 TRACE("returning %d\n", ret);
3800 return ret;
3803 /*************************************************************
3804 * GdiRealizationInfo (GDI32.@)
3806 * Returns a structure that contains some font information.
3808 BOOL WINAPI GdiRealizationInfo(HDC hdc, realization_info_t *info)
3810 DC *dc = get_dc_ptr(hdc);
3811 PHYSDEV dev;
3812 BOOL ret;
3814 if (!dc) return FALSE;
3815 dev = GET_DC_PHYSDEV( dc, pGdiRealizationInfo );
3816 ret = dev->funcs->pGdiRealizationInfo( dev, info );
3817 release_dc_ptr(dc);
3818 return ret;