msxml3: Don't return REFIID to avoid compiler warnings.
[wine/multimedia.git] / dlls / gdi32 / font.c
blob0f01a928f6f82f4ea49eb4f973bb663effc5d785
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 "gdi_private.h"
36 #include "wine/exception.h"
37 #include "wine/unicode.h"
38 #include "wine/debug.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(font);
42 /* Device -> World size conversion */
44 /* Performs a device to world transformation on the specified width (which
45 * is in integer format).
47 static inline INT INTERNAL_XDSTOWS(DC *dc, INT width)
49 double floatWidth;
51 /* Perform operation with floating point */
52 floatWidth = (double)width * dc->xformVport2World.eM11;
53 /* Round to integers */
54 return GDI_ROUND(floatWidth);
57 /* Performs a device to world transformation on the specified size (which
58 * is in integer format).
60 static inline INT INTERNAL_YDSTOWS(DC *dc, INT height)
62 double floatHeight;
64 /* Perform operation with floating point */
65 floatHeight = (double)height * dc->xformVport2World.eM22;
66 /* Round to integers */
67 return GDI_ROUND(floatHeight);
70 static inline INT INTERNAL_XWSTODS(DC *dc, INT width)
72 POINT pt[2];
73 pt[0].x = pt[0].y = 0;
74 pt[1].x = width;
75 pt[1].y = 0;
76 LPtoDP(dc->hSelf, pt, 2);
77 return pt[1].x - pt[0].x;
80 static inline INT INTERNAL_YWSTODS(DC *dc, INT height)
82 POINT pt[2];
83 pt[0].x = pt[0].y = 0;
84 pt[1].x = 0;
85 pt[1].y = height;
86 LPtoDP(dc->hSelf, pt, 2);
87 return pt[1].y - pt[0].y;
90 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc );
91 static INT FONT_GetObjectA( HGDIOBJ handle, INT count, LPVOID buffer );
92 static INT FONT_GetObjectW( HGDIOBJ handle, INT count, LPVOID buffer );
93 static BOOL FONT_DeleteObject( HGDIOBJ handle );
95 static const struct gdi_obj_funcs font_funcs =
97 FONT_SelectObject, /* pSelectObject */
98 FONT_GetObjectA, /* pGetObjectA */
99 FONT_GetObjectW, /* pGetObjectW */
100 NULL, /* pUnrealizeObject */
101 FONT_DeleteObject /* pDeleteObject */
104 typedef struct
106 GDIOBJHDR header;
107 LOGFONTW logfont;
108 } FONTOBJ;
110 struct font_enum
112 LPLOGFONTW lpLogFontParam;
113 FONTENUMPROCW lpEnumFunc;
114 LPARAM lpData;
115 BOOL unicode;
116 HDC hdc;
120 * For TranslateCharsetInfo
122 #define MAXTCIINDEX 32
123 static const CHARSETINFO FONT_tci[MAXTCIINDEX] = {
124 /* ANSI */
125 { ANSI_CHARSET, 1252, {{0,0,0,0},{FS_LATIN1,0}} },
126 { EASTEUROPE_CHARSET, 1250, {{0,0,0,0},{FS_LATIN2,0}} },
127 { RUSSIAN_CHARSET, 1251, {{0,0,0,0},{FS_CYRILLIC,0}} },
128 { GREEK_CHARSET, 1253, {{0,0,0,0},{FS_GREEK,0}} },
129 { TURKISH_CHARSET, 1254, {{0,0,0,0},{FS_TURKISH,0}} },
130 { HEBREW_CHARSET, 1255, {{0,0,0,0},{FS_HEBREW,0}} },
131 { ARABIC_CHARSET, 1256, {{0,0,0,0},{FS_ARABIC,0}} },
132 { BALTIC_CHARSET, 1257, {{0,0,0,0},{FS_BALTIC,0}} },
133 { VIETNAMESE_CHARSET, 1258, {{0,0,0,0},{FS_VIETNAMESE,0}} },
134 /* reserved by ANSI */
135 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
136 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
137 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
138 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
139 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
140 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
141 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
142 /* ANSI and OEM */
143 { THAI_CHARSET, 874, {{0,0,0,0},{FS_THAI,0}} },
144 { SHIFTJIS_CHARSET, 932, {{0,0,0,0},{FS_JISJAPAN,0}} },
145 { GB2312_CHARSET, 936, {{0,0,0,0},{FS_CHINESESIMP,0}} },
146 { HANGEUL_CHARSET, 949, {{0,0,0,0},{FS_WANSUNG,0}} },
147 { CHINESEBIG5_CHARSET, 950, {{0,0,0,0},{FS_CHINESETRAD,0}} },
148 { JOHAB_CHARSET, 1361, {{0,0,0,0},{FS_JOHAB,0}} },
149 /* reserved for alternate ANSI and OEM */
150 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
151 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
152 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
153 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
154 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
155 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
156 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
157 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
158 /* reserved for system */
159 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
160 { SYMBOL_CHARSET, CP_SYMBOL, {{0,0,0,0},{FS_SYMBOL,0}} }
163 static void FONT_LogFontAToW( const LOGFONTA *fontA, LPLOGFONTW fontW )
165 memcpy(fontW, fontA, sizeof(LOGFONTA) - LF_FACESIZE);
166 MultiByteToWideChar(CP_ACP, 0, fontA->lfFaceName, -1, fontW->lfFaceName,
167 LF_FACESIZE);
168 fontW->lfFaceName[LF_FACESIZE-1] = 0;
171 static void FONT_LogFontWToA( const LOGFONTW *fontW, LPLOGFONTA fontA )
173 memcpy(fontA, fontW, sizeof(LOGFONTA) - LF_FACESIZE);
174 WideCharToMultiByte(CP_ACP, 0, fontW->lfFaceName, -1, fontA->lfFaceName,
175 LF_FACESIZE, NULL, NULL);
176 fontA->lfFaceName[LF_FACESIZE-1] = 0;
179 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEXA fontA )
181 FONT_LogFontWToA( &fontW->elfLogFont, &fontA->elfLogFont );
183 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
184 (LPSTR) fontA->elfFullName, LF_FULLFACESIZE, NULL, NULL );
185 fontA->elfFullName[LF_FULLFACESIZE-1] = '\0';
186 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
187 (LPSTR) fontA->elfStyle, LF_FACESIZE, NULL, NULL );
188 fontA->elfStyle[LF_FACESIZE-1] = '\0';
189 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
190 (LPSTR) fontA->elfScript, LF_FACESIZE, NULL, NULL );
191 fontA->elfScript[LF_FACESIZE-1] = '\0';
194 static void FONT_EnumLogFontExAToW( const ENUMLOGFONTEXA *fontA, LPENUMLOGFONTEXW fontW )
196 FONT_LogFontAToW( &fontA->elfLogFont, &fontW->elfLogFont );
198 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfFullName, -1,
199 fontW->elfFullName, LF_FULLFACESIZE );
200 fontW->elfFullName[LF_FULLFACESIZE-1] = '\0';
201 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfStyle, -1,
202 fontW->elfStyle, LF_FACESIZE );
203 fontW->elfStyle[LF_FACESIZE-1] = '\0';
204 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfScript, -1,
205 fontW->elfScript, LF_FACESIZE );
206 fontW->elfScript[LF_FACESIZE-1] = '\0';
209 /***********************************************************************
210 * TEXTMETRIC conversion functions.
212 static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
214 ptmA->tmHeight = ptmW->tmHeight;
215 ptmA->tmAscent = ptmW->tmAscent;
216 ptmA->tmDescent = ptmW->tmDescent;
217 ptmA->tmInternalLeading = ptmW->tmInternalLeading;
218 ptmA->tmExternalLeading = ptmW->tmExternalLeading;
219 ptmA->tmAveCharWidth = ptmW->tmAveCharWidth;
220 ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth;
221 ptmA->tmWeight = ptmW->tmWeight;
222 ptmA->tmOverhang = ptmW->tmOverhang;
223 ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX;
224 ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
225 ptmA->tmFirstChar = min(ptmW->tmFirstChar, 255);
226 if (ptmW->tmCharSet == SYMBOL_CHARSET)
228 ptmA->tmFirstChar = 0x1e;
229 ptmA->tmLastChar = 0xff; /* win9x behaviour - we need the OS2 table data to calculate correctly */
231 else if (ptmW->tmPitchAndFamily & TMPF_TRUETYPE)
233 ptmA->tmFirstChar = ptmW->tmDefaultChar - 1;
234 ptmA->tmLastChar = min(ptmW->tmLastChar, 0xff);
236 else
238 ptmA->tmFirstChar = min(ptmW->tmFirstChar, 0xff);
239 ptmA->tmLastChar = min(ptmW->tmLastChar, 0xff);
241 ptmA->tmDefaultChar = ptmW->tmDefaultChar;
242 ptmA->tmBreakChar = ptmW->tmBreakChar;
243 ptmA->tmItalic = ptmW->tmItalic;
244 ptmA->tmUnderlined = ptmW->tmUnderlined;
245 ptmA->tmStruckOut = ptmW->tmStruckOut;
246 ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
247 ptmA->tmCharSet = ptmW->tmCharSet;
251 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW *ptmW, NEWTEXTMETRICEXA *ptmA )
253 FONT_TextMetricWToA((const TEXTMETRICW *)ptmW, (LPTEXTMETRICA)ptmA);
254 ptmA->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
255 ptmA->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
256 ptmA->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
257 ptmA->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
258 memcpy(&ptmA->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
262 UINT get_font_aa_flags( HDC hdc )
264 LOGFONTW lf;
266 if (GetObjectType( hdc ) == OBJ_MEMDC)
268 BITMAP bm;
269 GetObjectW( GetCurrentObject( hdc, OBJ_BITMAP ), sizeof(bm), &bm );
270 if (bm.bmBitsPixel <= 8) return GGO_BITMAP;
272 else if (GetDeviceCaps( hdc, BITSPIXEL ) <= 8) return GGO_BITMAP;
274 GetObjectW( GetCurrentObject( hdc, OBJ_FONT ), sizeof(lf), &lf );
275 if (lf.lfQuality == NONANTIALIASED_QUALITY) return GGO_BITMAP;
277 /* FIXME, check gasp and user prefs */
278 return GGO_GRAY4_BITMAP;
281 /***********************************************************************
282 * GdiGetCodePage (GDI32.@)
284 DWORD WINAPI GdiGetCodePage( HDC hdc )
286 UINT cp = CP_ACP;
287 DC *dc = get_dc_ptr( hdc );
289 if (dc)
291 cp = dc->font_code_page;
292 release_dc_ptr( dc );
294 return cp;
297 /***********************************************************************
298 * FONT_mbtowc
300 * Returns a Unicode translation of str using the charset of the
301 * currently selected font in hdc. If count is -1 then str is assumed
302 * to be '\0' terminated, otherwise it contains the number of bytes to
303 * convert. If plenW is non-NULL, on return it will point to the
304 * number of WCHARs that have been written. If pCP is non-NULL, on
305 * return it will point to the codepage used in the conversion. The
306 * caller should free the returned LPWSTR from the process heap
307 * itself.
309 static LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
311 UINT cp;
312 INT lenW;
313 LPWSTR strW;
315 cp = GdiGetCodePage( hdc );
317 if(count == -1) count = strlen(str);
318 lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
319 strW = HeapAlloc(GetProcessHeap(), 0, lenW*sizeof(WCHAR));
320 MultiByteToWideChar(cp, 0, str, count, strW, lenW);
321 TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW));
322 if(plenW) *plenW = lenW;
323 if(pCP) *pCP = cp;
324 return strW;
327 /***********************************************************************
328 * CreateFontIndirectExA (GDI32.@)
330 HFONT WINAPI CreateFontIndirectExA( const ENUMLOGFONTEXDVA *penumexA )
332 ENUMLOGFONTEXDVW enumexW;
334 if (!penumexA) return 0;
336 FONT_EnumLogFontExAToW( &penumexA->elfEnumLogfontEx, &enumexW.elfEnumLogfontEx );
337 enumexW.elfDesignVector = penumexA->elfDesignVector;
338 return CreateFontIndirectExW( &enumexW );
341 /***********************************************************************
342 * CreateFontIndirectExW (GDI32.@)
344 HFONT WINAPI CreateFontIndirectExW( const ENUMLOGFONTEXDVW *penumex )
346 HFONT hFont;
347 FONTOBJ *fontPtr;
348 const LOGFONTW *plf;
350 if (!penumex) return 0;
352 if (penumex->elfEnumLogfontEx.elfFullName[0] ||
353 penumex->elfEnumLogfontEx.elfStyle[0] ||
354 penumex->elfEnumLogfontEx.elfScript[0])
356 FIXME("some fields ignored. fullname=%s, style=%s, script=%s\n",
357 debugstr_w(penumex->elfEnumLogfontEx.elfFullName),
358 debugstr_w(penumex->elfEnumLogfontEx.elfStyle),
359 debugstr_w(penumex->elfEnumLogfontEx.elfScript));
362 plf = &penumex->elfEnumLogfontEx.elfLogFont;
363 if (!(fontPtr = HeapAlloc( GetProcessHeap(), 0, sizeof(*fontPtr) ))) return 0;
365 fontPtr->logfont = *plf;
367 if (plf->lfEscapement != plf->lfOrientation)
369 /* this should really depend on whether GM_ADVANCED is set */
370 fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
371 WARN("orientation angle %f set to "
372 "escapement angle %f for new font %p\n",
373 plf->lfOrientation/10., plf->lfEscapement/10., fontPtr);
376 if (!(hFont = alloc_gdi_handle( &fontPtr->header, OBJ_FONT, &font_funcs )))
378 HeapFree( GetProcessHeap(), 0, fontPtr );
379 return 0;
382 TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
383 plf->lfHeight, plf->lfWidth,
384 plf->lfEscapement, plf->lfOrientation,
385 plf->lfPitchAndFamily,
386 plf->lfOutPrecision, plf->lfClipPrecision,
387 plf->lfQuality, plf->lfCharSet,
388 debugstr_w(plf->lfFaceName),
389 plf->lfWeight > 400 ? "Bold" : "",
390 plf->lfItalic ? "Italic" : "",
391 plf->lfUnderline ? "Underline" : "", hFont);
393 return hFont;
396 /***********************************************************************
397 * CreateFontIndirectA (GDI32.@)
399 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *plfA )
401 LOGFONTW lfW;
403 if (!plfA) return 0;
405 FONT_LogFontAToW( plfA, &lfW );
406 return CreateFontIndirectW( &lfW );
409 /***********************************************************************
410 * CreateFontIndirectW (GDI32.@)
412 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
414 ENUMLOGFONTEXDVW exdv;
416 if (!plf) return 0;
418 exdv.elfEnumLogfontEx.elfLogFont = *plf;
419 exdv.elfEnumLogfontEx.elfFullName[0] = 0;
420 exdv.elfEnumLogfontEx.elfStyle[0] = 0;
421 exdv.elfEnumLogfontEx.elfScript[0] = 0;
422 return CreateFontIndirectExW( &exdv );
425 /*************************************************************************
426 * CreateFontA (GDI32.@)
428 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
429 INT orient, INT weight, DWORD italic,
430 DWORD underline, DWORD strikeout, DWORD charset,
431 DWORD outpres, DWORD clippres, DWORD quality,
432 DWORD pitch, LPCSTR name )
434 LOGFONTA logfont;
436 logfont.lfHeight = height;
437 logfont.lfWidth = width;
438 logfont.lfEscapement = esc;
439 logfont.lfOrientation = orient;
440 logfont.lfWeight = weight;
441 logfont.lfItalic = italic;
442 logfont.lfUnderline = underline;
443 logfont.lfStrikeOut = strikeout;
444 logfont.lfCharSet = charset;
445 logfont.lfOutPrecision = outpres;
446 logfont.lfClipPrecision = clippres;
447 logfont.lfQuality = quality;
448 logfont.lfPitchAndFamily = pitch;
450 if (name)
451 lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
452 else
453 logfont.lfFaceName[0] = '\0';
455 return CreateFontIndirectA( &logfont );
458 /*************************************************************************
459 * CreateFontW (GDI32.@)
461 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
462 INT orient, INT weight, DWORD italic,
463 DWORD underline, DWORD strikeout, DWORD charset,
464 DWORD outpres, DWORD clippres, DWORD quality,
465 DWORD pitch, LPCWSTR name )
467 LOGFONTW logfont;
469 logfont.lfHeight = height;
470 logfont.lfWidth = width;
471 logfont.lfEscapement = esc;
472 logfont.lfOrientation = orient;
473 logfont.lfWeight = weight;
474 logfont.lfItalic = italic;
475 logfont.lfUnderline = underline;
476 logfont.lfStrikeOut = strikeout;
477 logfont.lfCharSet = charset;
478 logfont.lfOutPrecision = outpres;
479 logfont.lfClipPrecision = clippres;
480 logfont.lfQuality = quality;
481 logfont.lfPitchAndFamily = pitch;
483 if (name)
484 lstrcpynW(logfont.lfFaceName, name,
485 sizeof(logfont.lfFaceName) / sizeof(WCHAR));
486 else
487 logfont.lfFaceName[0] = '\0';
489 return CreateFontIndirectW( &logfont );
492 static void update_font_code_page( DC *dc )
494 CHARSETINFO csi;
495 int charset = GetTextCharsetInfo( dc->hSelf, NULL, 0 );
497 /* Hmm, nicely designed api this one! */
498 if (TranslateCharsetInfo( ULongToPtr(charset), &csi, TCI_SRCCHARSET) )
499 dc->font_code_page = csi.ciACP;
500 else {
501 switch(charset) {
502 case OEM_CHARSET:
503 dc->font_code_page = GetOEMCP();
504 break;
505 case DEFAULT_CHARSET:
506 dc->font_code_page = GetACP();
507 break;
509 case VISCII_CHARSET:
510 case TCVN_CHARSET:
511 case KOI8_CHARSET:
512 case ISO3_CHARSET:
513 case ISO4_CHARSET:
514 case ISO10_CHARSET:
515 case CELTIC_CHARSET:
516 /* FIXME: These have no place here, but because x11drv
517 enumerates fonts with these (made up) charsets some apps
518 might use them and then the FIXME below would become
519 annoying. Now we could pick the intended codepage for
520 each of these, but since it's broken anyway we'll just
521 use CP_ACP and hope it'll go away...
523 dc->font_code_page = CP_ACP;
524 break;
526 default:
527 FIXME("Can't find codepage for charset %d\n", charset);
528 dc->font_code_page = CP_ACP;
529 break;
533 TRACE("charset %d => cp %d\n", charset, dc->font_code_page);
536 /***********************************************************************
537 * FONT_SelectObject
539 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc )
541 HGDIOBJ ret = 0;
542 DC *dc = get_dc_ptr( hdc );
543 PHYSDEV physdev;
545 if (!dc) return 0;
547 if (!GDI_inc_ref_count( handle ))
549 release_dc_ptr( dc );
550 return 0;
553 physdev = GET_DC_PHYSDEV( dc, pSelectFont );
554 if (physdev->funcs->pSelectFont( physdev, handle ))
556 ret = dc->hFont;
557 dc->hFont = handle;
558 update_font_code_page( dc );
559 GDI_dec_ref_count( ret );
561 else GDI_dec_ref_count( handle );
563 release_dc_ptr( dc );
564 return ret;
568 /***********************************************************************
569 * FONT_GetObjectA
571 static INT FONT_GetObjectA( HGDIOBJ handle, INT count, LPVOID buffer )
573 FONTOBJ *font = GDI_GetObjPtr( handle, OBJ_FONT );
574 LOGFONTA lfA;
576 if (!font) return 0;
577 if (buffer)
579 FONT_LogFontWToA( &font->logfont, &lfA );
580 if (count > sizeof(lfA)) count = sizeof(lfA);
581 memcpy( buffer, &lfA, count );
583 else count = sizeof(lfA);
584 GDI_ReleaseObj( handle );
585 return count;
588 /***********************************************************************
589 * FONT_GetObjectW
591 static INT FONT_GetObjectW( HGDIOBJ handle, INT count, LPVOID buffer )
593 FONTOBJ *font = GDI_GetObjPtr( handle, OBJ_FONT );
595 if (!font) return 0;
596 if (buffer)
598 if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
599 memcpy( buffer, &font->logfont, count );
601 else count = sizeof(LOGFONTW);
602 GDI_ReleaseObj( handle );
603 return count;
607 /***********************************************************************
608 * FONT_DeleteObject
610 static BOOL FONT_DeleteObject( HGDIOBJ handle )
612 FONTOBJ *obj;
614 WineEngDestroyFontInstance( handle );
616 if (!(obj = free_gdi_handle( handle ))) return FALSE;
617 return HeapFree( GetProcessHeap(), 0, obj );
621 /***********************************************************************
622 * FONT_EnumInstance
624 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
625 * We have to use other types because of the FONTENUMPROCW definition.
627 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
628 DWORD fType, LPARAM lp )
630 struct font_enum *pfe = (struct font_enum *)lp;
631 INT ret = 1;
633 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
634 if ((!pfe->lpLogFontParam ||
635 pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
636 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
637 (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
639 /* convert font metrics */
640 ENUMLOGFONTEXA logfont;
641 NEWTEXTMETRICEXA tmA;
643 if (!pfe->unicode)
645 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
646 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
647 plf = (LOGFONTW *)&logfont.elfLogFont;
648 ptm = (TEXTMETRICW *)&tmA;
650 ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
652 return ret;
655 /***********************************************************************
656 * FONT_EnumFontFamiliesEx
658 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf, FONTENUMPROCW efproc,
659 LPARAM lParam, BOOL unicode )
661 INT ret = 0;
662 DC *dc = get_dc_ptr( hDC );
663 struct font_enum fe;
665 if (dc)
667 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pEnumFonts );
669 if (plf) TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName), plf->lfCharSet);
670 fe.lpLogFontParam = plf;
671 fe.lpEnumFunc = efproc;
672 fe.lpData = lParam;
673 fe.unicode = unicode;
674 fe.hdc = hDC;
675 ret = physdev->funcs->pEnumFonts( physdev, plf, FONT_EnumInstance, (LPARAM)&fe );
676 release_dc_ptr( dc );
678 return ret;
681 /***********************************************************************
682 * EnumFontFamiliesExW (GDI32.@)
684 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
685 FONTENUMPROCW efproc,
686 LPARAM lParam, DWORD dwFlags )
688 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, TRUE );
691 /***********************************************************************
692 * EnumFontFamiliesExA (GDI32.@)
694 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
695 FONTENUMPROCA efproc,
696 LPARAM lParam, DWORD dwFlags)
698 LOGFONTW lfW, *plfW;
700 if (plf)
702 FONT_LogFontAToW( plf, &lfW );
703 plfW = &lfW;
705 else plfW = NULL;
707 return FONT_EnumFontFamiliesEx( hDC, plfW, (FONTENUMPROCW)efproc, lParam, FALSE );
710 /***********************************************************************
711 * EnumFontFamiliesA (GDI32.@)
713 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
714 FONTENUMPROCA efproc, LPARAM lpData )
716 LOGFONTA lf, *plf;
718 if (lpFamily)
720 if (!*lpFamily) return 1;
721 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
722 lf.lfCharSet = DEFAULT_CHARSET;
723 lf.lfPitchAndFamily = 0;
724 plf = &lf;
726 else plf = NULL;
728 return EnumFontFamiliesExA( hDC, plf, efproc, lpData, 0 );
731 /***********************************************************************
732 * EnumFontFamiliesW (GDI32.@)
734 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
735 FONTENUMPROCW efproc, LPARAM lpData )
737 LOGFONTW lf, *plf;
739 if (lpFamily)
741 if (!*lpFamily) return 1;
742 lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
743 lf.lfCharSet = DEFAULT_CHARSET;
744 lf.lfPitchAndFamily = 0;
745 plf = &lf;
747 else plf = NULL;
749 return EnumFontFamiliesExW( hDC, plf, efproc, lpData, 0 );
752 /***********************************************************************
753 * EnumFontsA (GDI32.@)
755 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
756 LPARAM lpData )
758 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
761 /***********************************************************************
762 * EnumFontsW (GDI32.@)
764 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
765 LPARAM lpData )
767 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
771 /***********************************************************************
772 * GetTextCharacterExtra (GDI32.@)
774 INT WINAPI GetTextCharacterExtra( HDC hdc )
776 INT ret;
777 DC *dc = get_dc_ptr( hdc );
778 if (!dc) return 0x80000000;
779 ret = dc->charExtra;
780 release_dc_ptr( dc );
781 return ret;
785 /***********************************************************************
786 * SetTextCharacterExtra (GDI32.@)
788 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
790 INT ret = 0x80000000;
791 DC * dc = get_dc_ptr( hdc );
793 if (dc)
795 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetTextCharacterExtra );
796 extra = physdev->funcs->pSetTextCharacterExtra( physdev, extra );
797 if (extra != 0x80000000)
799 ret = dc->charExtra;
800 dc->charExtra = extra;
802 release_dc_ptr( dc );
804 return ret;
808 /***********************************************************************
809 * SetTextJustification (GDI32.@)
811 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
813 BOOL ret;
814 PHYSDEV physdev;
815 DC * dc = get_dc_ptr( hdc );
817 if (!dc) return FALSE;
819 physdev = GET_DC_PHYSDEV( dc, pSetTextJustification );
820 ret = physdev->funcs->pSetTextJustification( physdev, extra, breaks );
821 if (ret)
823 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
824 if (!extra) breaks = 0;
825 if (breaks)
827 dc->breakExtra = extra / breaks;
828 dc->breakRem = extra - (breaks * dc->breakExtra);
830 else
832 dc->breakExtra = 0;
833 dc->breakRem = 0;
836 release_dc_ptr( dc );
837 return ret;
841 /***********************************************************************
842 * GetTextFaceA (GDI32.@)
844 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
846 INT res = GetTextFaceW(hdc, 0, NULL);
847 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
848 GetTextFaceW( hdc, res, nameW );
850 if (name)
852 if (count)
854 res = WideCharToMultiByte(CP_ACP, 0, nameW, -1, name, count, NULL, NULL);
855 if (res == 0)
856 res = count;
857 name[count-1] = 0;
858 /* GetTextFaceA does NOT include the nul byte in the return count. */
859 res--;
861 else
862 res = 0;
864 else
865 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
866 HeapFree( GetProcessHeap(), 0, nameW );
867 return res;
870 /***********************************************************************
871 * GetTextFaceW (GDI32.@)
873 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
875 PHYSDEV dev;
876 INT ret;
878 DC * dc = get_dc_ptr( hdc );
879 if (!dc) return 0;
881 dev = GET_DC_PHYSDEV( dc, pGetTextFace );
882 ret = dev->funcs->pGetTextFace( dev, count, name );
883 release_dc_ptr( dc );
884 return ret;
888 /***********************************************************************
889 * GetTextExtentPoint32A (GDI32.@)
891 * See GetTextExtentPoint32W.
893 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
894 LPSIZE size )
896 BOOL ret = FALSE;
897 INT wlen;
898 LPWSTR p;
900 if (count < 0) return FALSE;
902 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
904 if (p)
906 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
907 HeapFree( GetProcessHeap(), 0, p );
910 TRACE("(%p %s %d %p): returning %d x %d\n",
911 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
912 return ret;
916 /***********************************************************************
917 * GetTextExtentPoint32W [GDI32.@]
919 * Computes width/height for a string.
921 * Computes width and height of the specified string.
923 * RETURNS
924 * Success: TRUE
925 * Failure: FALSE
927 BOOL WINAPI GetTextExtentPoint32W(
928 HDC hdc, /* [in] Handle of device context */
929 LPCWSTR str, /* [in] Address of text string */
930 INT count, /* [in] Number of characters in string */
931 LPSIZE size) /* [out] Address of structure for string size */
933 return GetTextExtentExPointW(hdc, str, count, 0, NULL, NULL, size);
936 /***********************************************************************
937 * GetTextExtentExPointI [GDI32.@]
939 * Computes width and height of the array of glyph indices.
941 * PARAMS
942 * hdc [I] Handle of device context.
943 * indices [I] Glyph index array.
944 * count [I] Number of glyphs in array.
945 * max_ext [I] Maximum width in glyphs.
946 * nfit [O] Maximum number of characters.
947 * dxs [O] Partial string widths.
948 * size [O] Returned string size.
950 * RETURNS
951 * Success: TRUE
952 * Failure: FALSE
954 BOOL WINAPI GetTextExtentExPointI( HDC hdc, const WORD *indices, INT count, INT max_ext,
955 LPINT nfit, LPINT dxs, LPSIZE size )
957 PHYSDEV dev;
958 BOOL ret;
959 DC *dc;
961 if (count < 0) return FALSE;
963 dc = get_dc_ptr( hdc );
964 if (!dc) return FALSE;
966 dev = GET_DC_PHYSDEV( dc, pGetTextExtentExPointI );
967 ret = dev->funcs->pGetTextExtentExPointI( dev, indices, count, max_ext, nfit, dxs, size );
968 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
969 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
970 size->cx += count * dc->charExtra;
971 release_dc_ptr( dc );
973 TRACE("(%p %p %d %p): returning %d x %d\n",
974 hdc, indices, count, size, size->cx, size->cy );
975 return ret;
978 /***********************************************************************
979 * GetTextExtentPointI [GDI32.@]
981 * Computes width and height of the array of glyph indices.
983 * PARAMS
984 * hdc [I] Handle of device context.
985 * indices [I] Glyph index array.
986 * count [I] Number of glyphs in array.
987 * size [O] Returned string size.
989 * RETURNS
990 * Success: TRUE
991 * Failure: FALSE
993 BOOL WINAPI GetTextExtentPointI( HDC hdc, const WORD *indices, INT count, LPSIZE size )
995 return GetTextExtentExPointI( hdc, indices, count, 0, NULL, NULL, size );
999 /***********************************************************************
1000 * GetTextExtentPointA (GDI32.@)
1002 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
1003 LPSIZE size )
1005 TRACE("not bug compatible.\n");
1006 return GetTextExtentPoint32A( hdc, str, count, size );
1009 /***********************************************************************
1010 * GetTextExtentPointW (GDI32.@)
1012 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1013 LPSIZE size )
1015 TRACE("not bug compatible.\n");
1016 return GetTextExtentPoint32W( hdc, str, count, size );
1020 /***********************************************************************
1021 * GetTextExtentExPointA (GDI32.@)
1023 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1024 INT maxExt, LPINT lpnFit,
1025 LPINT alpDx, LPSIZE size )
1027 BOOL ret;
1028 INT wlen;
1029 INT *walpDx = NULL;
1030 LPWSTR p = NULL;
1032 if (count < 0) return FALSE;
1034 if (alpDx)
1036 walpDx = HeapAlloc( GetProcessHeap(), 0, count * sizeof(INT) );
1037 if (!walpDx) return FALSE;
1040 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1041 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
1042 if (walpDx)
1044 INT n = lpnFit ? *lpnFit : wlen;
1045 INT i, j;
1046 for(i = 0, j = 0; i < n; i++, j++)
1048 alpDx[j] = walpDx[i];
1049 if (IsDBCSLeadByte(str[j])) alpDx[++j] = walpDx[i];
1052 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1053 HeapFree( GetProcessHeap(), 0, p );
1054 HeapFree( GetProcessHeap(), 0, walpDx );
1055 return ret;
1059 /***********************************************************************
1060 * GetTextExtentExPointW (GDI32.@)
1062 * Return the size of the string as it would be if it was output properly by
1063 * e.g. TextOut.
1065 * This should include
1066 * - Intercharacter spacing
1067 * - justification spacing (not yet done)
1068 * - kerning? see below
1070 * Kerning. Since kerning would be carried out by the rendering code it should
1071 * be done by the driver. However they don't support it yet. Also I am not
1072 * yet persuaded that (certainly under Win95) any kerning is actually done.
1074 * str: According to MSDN this should be null-terminated. That is not true; a
1075 * null will not terminate it early.
1076 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1077 * than count. I have seen it be either the size of the full string or
1078 * 1 less than the size of the full string. I have not seen it bear any
1079 * resemblance to the portion that would fit.
1080 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1081 * trailing intercharacter spacing and any trailing justification.
1083 * FIXME
1084 * Currently we do this by measuring each character etc. We should do it by
1085 * passing the request to the driver, perhaps by extending the
1086 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1087 * thinking about kerning issues and rounding issues in the justification.
1090 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1091 INT maxExt, LPINT lpnFit,
1092 LPINT alpDx, LPSIZE size )
1094 INT nFit = 0;
1095 LPINT dxs = NULL;
1096 DC *dc;
1097 BOOL ret = FALSE;
1098 TEXTMETRICW tm;
1099 PHYSDEV dev;
1101 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1103 if (count < 0) return FALSE;
1105 dc = get_dc_ptr(hdc);
1106 if (!dc) return FALSE;
1108 GetTextMetricsW(hdc, &tm);
1110 /* If we need to calculate nFit, then we need the partial extents even if
1111 the user hasn't provided us with an array. */
1112 if (lpnFit)
1114 dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]);
1115 if (! dxs)
1117 release_dc_ptr(dc);
1118 SetLastError(ERROR_OUTOFMEMORY);
1119 return FALSE;
1122 else
1123 dxs = alpDx;
1125 dev = GET_DC_PHYSDEV( dc, pGetTextExtentExPoint );
1126 ret = dev->funcs->pGetTextExtentExPoint(dev, str, count, 0, NULL, dxs, size);
1128 /* Perform device size to world size transformations. */
1129 if (ret)
1131 INT extra = dc->charExtra,
1132 breakExtra = dc->breakExtra,
1133 breakRem = dc->breakRem,
1136 if (dxs)
1138 for (i = 0; i < count; ++i)
1140 dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
1141 dxs[i] += (i+1) * extra;
1142 if (count > 1 && (breakExtra || breakRem) && str[i] == tm.tmBreakChar)
1144 dxs[i] += breakExtra;
1145 if (breakRem > 0)
1147 breakRem--;
1148 dxs[i]++;
1151 if (dxs[i] <= maxExt)
1152 ++nFit;
1154 breakRem = dc->breakRem;
1156 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1157 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1159 if (!dxs && count > 1 && (breakExtra || breakRem))
1161 for (i = 0; i < count; i++)
1163 if (str[i] == tm.tmBreakChar)
1165 size->cx += breakExtra;
1166 if (breakRem > 0)
1168 breakRem--;
1169 (size->cx)++;
1176 if (lpnFit)
1177 *lpnFit = nFit;
1179 if (! alpDx)
1180 HeapFree(GetProcessHeap(), 0, dxs);
1182 release_dc_ptr( dc );
1184 TRACE("returning %d %d x %d\n",nFit,size->cx,size->cy);
1185 return ret;
1188 /***********************************************************************
1189 * GetTextMetricsA (GDI32.@)
1191 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1193 TEXTMETRICW tm32;
1195 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1196 FONT_TextMetricWToA( &tm32, metrics );
1197 return TRUE;
1200 /***********************************************************************
1201 * GetTextMetricsW (GDI32.@)
1203 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1205 PHYSDEV physdev;
1206 BOOL ret = FALSE;
1207 DC * dc = get_dc_ptr( hdc );
1208 if (!dc) return FALSE;
1210 physdev = GET_DC_PHYSDEV( dc, pGetTextMetrics );
1211 ret = physdev->funcs->pGetTextMetrics( physdev, metrics );
1213 if (ret)
1215 /* device layer returns values in device units
1216 * therefore we have to convert them to logical */
1218 metrics->tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1219 metrics->tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1221 #define WDPTOLP(x) ((x<0)? \
1222 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1223 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1224 #define HDPTOLP(y) ((y<0)? \
1225 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1226 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1228 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1229 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1230 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1231 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1232 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1233 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1234 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1235 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1236 ret = TRUE;
1237 #undef WDPTOLP
1238 #undef HDPTOLP
1239 TRACE("text metrics:\n"
1240 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1241 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1242 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1243 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1244 " PitchAndFamily = %02x\n"
1245 " --------------------\n"
1246 " InternalLeading = %i\n"
1247 " Ascent = %i\n"
1248 " Descent = %i\n"
1249 " Height = %i\n",
1250 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1251 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1252 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1253 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1254 metrics->tmPitchAndFamily,
1255 metrics->tmInternalLeading,
1256 metrics->tmAscent,
1257 metrics->tmDescent,
1258 metrics->tmHeight );
1260 release_dc_ptr( dc );
1261 return ret;
1265 /***********************************************************************
1266 * GetOutlineTextMetricsA (GDI32.@)
1267 * Gets metrics for TrueType fonts.
1269 * NOTES
1270 * If the supplied buffer isn't big enough Windows partially fills it up to
1271 * its given length and returns that length.
1273 * RETURNS
1274 * Success: Non-zero or size of required buffer
1275 * Failure: 0
1277 UINT WINAPI GetOutlineTextMetricsA(
1278 HDC hdc, /* [in] Handle of device context */
1279 UINT cbData, /* [in] Size of metric data array */
1280 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1282 char buf[512], *ptr;
1283 UINT ret, needed;
1284 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1285 OUTLINETEXTMETRICA *output = lpOTM;
1286 INT left, len;
1288 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1289 return 0;
1290 if(ret > sizeof(buf))
1291 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1292 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1294 needed = sizeof(OUTLINETEXTMETRICA);
1295 if(lpOTMW->otmpFamilyName)
1296 needed += WideCharToMultiByte(CP_ACP, 0,
1297 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1298 NULL, 0, NULL, NULL);
1299 if(lpOTMW->otmpFaceName)
1300 needed += WideCharToMultiByte(CP_ACP, 0,
1301 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1302 NULL, 0, NULL, NULL);
1303 if(lpOTMW->otmpStyleName)
1304 needed += WideCharToMultiByte(CP_ACP, 0,
1305 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1306 NULL, 0, NULL, NULL);
1307 if(lpOTMW->otmpFullName)
1308 needed += WideCharToMultiByte(CP_ACP, 0,
1309 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1310 NULL, 0, NULL, NULL);
1312 if(!lpOTM) {
1313 ret = needed;
1314 goto end;
1317 TRACE("needed = %d\n", needed);
1318 if(needed > cbData)
1319 /* Since the supplied buffer isn't big enough, we'll alloc one
1320 that is and memcpy the first cbData bytes into the lpOTM at
1321 the end. */
1322 output = HeapAlloc(GetProcessHeap(), 0, needed);
1324 ret = output->otmSize = min(needed, cbData);
1325 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1326 output->otmFiller = 0;
1327 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1328 output->otmfsSelection = lpOTMW->otmfsSelection;
1329 output->otmfsType = lpOTMW->otmfsType;
1330 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1331 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1332 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1333 output->otmEMSquare = lpOTMW->otmEMSquare;
1334 output->otmAscent = lpOTMW->otmAscent;
1335 output->otmDescent = lpOTMW->otmDescent;
1336 output->otmLineGap = lpOTMW->otmLineGap;
1337 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1338 output->otmsXHeight = lpOTMW->otmsXHeight;
1339 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1340 output->otmMacAscent = lpOTMW->otmMacAscent;
1341 output->otmMacDescent = lpOTMW->otmMacDescent;
1342 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1343 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1344 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1345 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1346 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1347 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1348 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1349 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1350 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1351 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1354 ptr = (char*)(output + 1);
1355 left = needed - sizeof(*output);
1357 if(lpOTMW->otmpFamilyName) {
1358 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1359 len = WideCharToMultiByte(CP_ACP, 0,
1360 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1361 ptr, left, NULL, NULL);
1362 left -= len;
1363 ptr += len;
1364 } else
1365 output->otmpFamilyName = 0;
1367 if(lpOTMW->otmpFaceName) {
1368 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1369 len = WideCharToMultiByte(CP_ACP, 0,
1370 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1371 ptr, left, NULL, NULL);
1372 left -= len;
1373 ptr += len;
1374 } else
1375 output->otmpFaceName = 0;
1377 if(lpOTMW->otmpStyleName) {
1378 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1379 len = WideCharToMultiByte(CP_ACP, 0,
1380 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1381 ptr, left, NULL, NULL);
1382 left -= len;
1383 ptr += len;
1384 } else
1385 output->otmpStyleName = 0;
1387 if(lpOTMW->otmpFullName) {
1388 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1389 len = WideCharToMultiByte(CP_ACP, 0,
1390 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1391 ptr, left, NULL, NULL);
1392 left -= len;
1393 } else
1394 output->otmpFullName = 0;
1396 assert(left == 0);
1398 if(output != lpOTM) {
1399 memcpy(lpOTM, output, cbData);
1400 HeapFree(GetProcessHeap(), 0, output);
1402 /* check if the string offsets really fit into the provided size */
1403 /* FIXME: should we check string length as well? */
1404 /* make sure that we don't read/write beyond the provided buffer */
1405 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(LPSTR))
1407 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1408 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1411 /* make sure that we don't read/write beyond the provided buffer */
1412 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(LPSTR))
1414 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1415 lpOTM->otmpFaceName = 0; /* doesn't fit */
1418 /* make sure that we don't read/write beyond the provided buffer */
1419 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(LPSTR))
1421 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1422 lpOTM->otmpStyleName = 0; /* doesn't fit */
1425 /* make sure that we don't read/write beyond the provided buffer */
1426 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(LPSTR))
1428 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1429 lpOTM->otmpFullName = 0; /* doesn't fit */
1433 end:
1434 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1435 HeapFree(GetProcessHeap(), 0, lpOTMW);
1437 return ret;
1441 /***********************************************************************
1442 * GetOutlineTextMetricsW [GDI32.@]
1444 UINT WINAPI GetOutlineTextMetricsW(
1445 HDC hdc, /* [in] Handle of device context */
1446 UINT cbData, /* [in] Size of metric data array */
1447 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1449 DC *dc = get_dc_ptr( hdc );
1450 OUTLINETEXTMETRICW *output = lpOTM;
1451 PHYSDEV dev;
1452 UINT ret;
1454 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1455 if(!dc) return 0;
1457 dev = GET_DC_PHYSDEV( dc, pGetOutlineTextMetrics );
1458 ret = dev->funcs->pGetOutlineTextMetrics( dev, cbData, output );
1460 if (lpOTM && ret > cbData)
1462 output = HeapAlloc(GetProcessHeap(), 0, ret);
1463 ret = dev->funcs->pGetOutlineTextMetrics( dev, ret, output );
1466 if (lpOTM && ret)
1468 output->otmTextMetrics.tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1469 output->otmTextMetrics.tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1471 #define WDPTOLP(x) ((x<0)? \
1472 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1473 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1474 #define HDPTOLP(y) ((y<0)? \
1475 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1476 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1478 output->otmTextMetrics.tmHeight = HDPTOLP(output->otmTextMetrics.tmHeight);
1479 output->otmTextMetrics.tmAscent = HDPTOLP(output->otmTextMetrics.tmAscent);
1480 output->otmTextMetrics.tmDescent = HDPTOLP(output->otmTextMetrics.tmDescent);
1481 output->otmTextMetrics.tmInternalLeading = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1482 output->otmTextMetrics.tmExternalLeading = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1483 output->otmTextMetrics.tmAveCharWidth = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1484 output->otmTextMetrics.tmMaxCharWidth = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1485 output->otmTextMetrics.tmOverhang = WDPTOLP(output->otmTextMetrics.tmOverhang);
1486 output->otmAscent = HDPTOLP(output->otmAscent);
1487 output->otmDescent = HDPTOLP(output->otmDescent);
1488 output->otmLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmLineGap));
1489 output->otmsCapEmHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsCapEmHeight));
1490 output->otmsXHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsXHeight));
1491 output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1492 output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1493 output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1494 output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1495 output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1496 output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1497 output->otmMacLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmMacLineGap));
1498 output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1499 output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1500 output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1501 output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1502 output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1503 output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1504 output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1505 output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1506 output->otmsStrikeoutSize = abs(INTERNAL_YDSTOWS(dc,output->otmsStrikeoutSize));
1507 output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1508 output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1509 output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1510 #undef WDPTOLP
1511 #undef HDPTOLP
1512 if(output != lpOTM)
1514 memcpy(lpOTM, output, cbData);
1515 HeapFree(GetProcessHeap(), 0, output);
1516 ret = cbData;
1519 release_dc_ptr(dc);
1520 return ret;
1523 static LPSTR FONT_GetCharsByRangeA(HDC hdc, UINT firstChar, UINT lastChar, PINT pByteLen)
1525 INT i, count = lastChar - firstChar + 1;
1526 UINT c;
1527 LPSTR str;
1529 if (count <= 0)
1530 return NULL;
1532 switch (GdiGetCodePage(hdc))
1534 case 932:
1535 case 936:
1536 case 949:
1537 case 950:
1538 case 1361:
1539 if (lastChar > 0xffff)
1540 return NULL;
1541 if ((firstChar ^ lastChar) > 0xff)
1542 return NULL;
1543 break;
1544 default:
1545 if (lastChar > 0xff)
1546 return NULL;
1547 break;
1550 str = HeapAlloc(GetProcessHeap(), 0, count * 2 + 1);
1551 if (str == NULL)
1552 return NULL;
1554 for(i = 0, c = firstChar; c <= lastChar; i++, c++)
1556 if (c > 0xff)
1557 str[i++] = (BYTE)(c >> 8);
1558 str[i] = (BYTE)c;
1560 str[i] = '\0';
1562 *pByteLen = i;
1564 return str;
1567 /***********************************************************************
1568 * GetCharWidthW (GDI32.@)
1569 * GetCharWidth32W (GDI32.@)
1571 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1572 LPINT buffer )
1574 UINT i;
1575 BOOL ret;
1576 PHYSDEV dev;
1577 DC * dc = get_dc_ptr( hdc );
1579 if (!dc) return FALSE;
1581 dev = GET_DC_PHYSDEV( dc, pGetCharWidth );
1582 ret = dev->funcs->pGetCharWidth( dev, firstChar, lastChar, buffer );
1584 if (ret)
1586 /* convert device units to logical */
1587 for( i = firstChar; i <= lastChar; i++, buffer++ )
1588 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1590 release_dc_ptr( dc );
1591 return ret;
1595 /***********************************************************************
1596 * GetCharWidthA (GDI32.@)
1597 * GetCharWidth32A (GDI32.@)
1599 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1600 LPINT buffer )
1602 INT i, wlen;
1603 LPSTR str;
1604 LPWSTR wstr;
1605 BOOL ret = TRUE;
1607 str = FONT_GetCharsByRangeA(hdc, firstChar, lastChar, &i);
1608 if(str == NULL)
1609 return FALSE;
1611 wstr = FONT_mbtowc(hdc, str, i, &wlen, NULL);
1613 for(i = 0; i < wlen; i++)
1615 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1617 ret = FALSE;
1618 break;
1620 buffer++;
1623 HeapFree(GetProcessHeap(), 0, str);
1624 HeapFree(GetProcessHeap(), 0, wstr);
1626 return ret;
1630 /* helper for nulldrv_ExtTextOut */
1631 static DWORD get_glyph_bitmap( HDC hdc, UINT index, UINT aa_flags,
1632 GLYPHMETRICS *metrics, struct gdi_image_bits *image )
1634 UINT ggo_flags = aa_flags | GGO_GLYPH_INDEX;
1635 static const MAT2 identity = { {0,1}, {0,0}, {0,0}, {0,1} };
1636 UINT indices[3] = {0, 0, 0x20};
1637 int i;
1638 DWORD ret, size;
1639 int stride;
1641 indices[0] = index;
1643 for (i = 0; i < sizeof(indices) / sizeof(indices[0]); index = indices[++i])
1645 ret = GetGlyphOutlineW( hdc, index, ggo_flags, metrics, 0, NULL, &identity );
1646 if (ret != GDI_ERROR) break;
1649 if (ret == GDI_ERROR) return ERROR_NOT_FOUND;
1650 if (!image) return ERROR_SUCCESS;
1652 image->ptr = NULL;
1653 image->free = NULL;
1654 if (!ret) return ERROR_SUCCESS; /* empty glyph */
1656 stride = get_dib_stride( metrics->gmBlackBoxX, 1 );
1657 size = metrics->gmBlackBoxY * stride;
1659 if (!(image->ptr = HeapAlloc( GetProcessHeap(), 0, size ))) return ERROR_OUTOFMEMORY;
1660 image->is_copy = TRUE;
1661 image->free = free_heap_bits;
1663 ret = GetGlyphOutlineW( hdc, index, ggo_flags, metrics, size, image->ptr, &identity );
1664 if (ret == GDI_ERROR)
1666 HeapFree( GetProcessHeap(), 0, image->ptr );
1667 return ERROR_NOT_FOUND;
1669 return ERROR_SUCCESS;
1672 /* helper for nulldrv_ExtTextOut */
1673 static RECT get_total_extents( HDC hdc, INT x, INT y, UINT flags, UINT aa_flags,
1674 LPCWSTR str, UINT count, const INT *dx )
1676 int i;
1677 RECT rect;
1679 rect.left = rect.top = INT_MAX;
1680 rect.right = rect.bottom = INT_MIN;
1681 for (i = 0; i < count; i++)
1683 GLYPHMETRICS metrics;
1685 if (get_glyph_bitmap( hdc, (UINT)str[i], aa_flags, &metrics, NULL )) continue;
1687 rect.left = min( rect.left, x + metrics.gmptGlyphOrigin.x );
1688 rect.top = min( rect.top, y - metrics.gmptGlyphOrigin.y );
1689 rect.right = max( rect.right, x + metrics.gmptGlyphOrigin.x + (int)metrics.gmBlackBoxX );
1690 rect.bottom = max( rect.bottom, y - metrics.gmptGlyphOrigin.y + (int)metrics.gmBlackBoxY );
1692 if (dx)
1694 if (flags & ETO_PDY)
1696 x += dx[ i * 2 ];
1697 y += dx[ i * 2 + 1];
1699 else x += dx[ i ];
1701 else
1703 x += metrics.gmCellIncX;
1704 y += metrics.gmCellIncY;
1707 return rect;
1710 /* helper for nulldrv_ExtTextOut */
1711 static void draw_glyph( HDC hdc, INT origin_x, INT origin_y, const GLYPHMETRICS *metrics,
1712 const struct gdi_image_bits *image, const RECT *clip )
1714 static const BYTE masks[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
1715 UINT x, y, i, count;
1716 BYTE *ptr = image->ptr;
1717 int stride = get_dib_stride( metrics->gmBlackBoxX, 1 );
1718 POINT *pts;
1719 RECT rect, clipped_rect;
1721 rect.left = origin_x + metrics->gmptGlyphOrigin.x;
1722 rect.top = origin_y - metrics->gmptGlyphOrigin.y;
1723 rect.right = rect.left + metrics->gmBlackBoxX;
1724 rect.bottom = rect.top + metrics->gmBlackBoxY;
1725 if (!clip) clipped_rect = rect;
1726 else if (!intersect_rect( &clipped_rect, &rect, clip )) return;
1728 pts = HeapAlloc( GetProcessHeap(), 0,
1729 max(2,metrics->gmBlackBoxX) * metrics->gmBlackBoxY * sizeof(*pts) );
1730 if (!pts) return;
1732 count = 0;
1733 ptr += (clipped_rect.top - rect.top) * stride;
1734 for (y = clipped_rect.top; y < clipped_rect.bottom; y++, ptr += stride)
1736 for (x = clipped_rect.left - rect.left; x < clipped_rect.right - rect.left; x++)
1738 while (x < clipped_rect.right - rect.left && !(ptr[x / 8] & masks[x % 8])) x++;
1739 pts[count].x = rect.left + x;
1740 while (x < clipped_rect.right - rect.left && (ptr[x / 8] & masks[x % 8])) x++;
1741 pts[count + 1].x = rect.left + x;
1742 if (pts[count + 1].x > pts[count].x)
1744 pts[count].y = pts[count + 1].y = y;
1745 count += 2;
1749 DPtoLP( hdc, pts, count );
1750 for (i = 0; i < count; i += 2) Polyline( hdc, pts + i, 2 );
1751 HeapFree( GetProcessHeap(), 0, pts );
1754 /***********************************************************************
1755 * nulldrv_ExtTextOut
1757 BOOL nulldrv_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags, const RECT *rect,
1758 LPCWSTR str, UINT count, const INT *dx )
1760 DC *dc = get_nulldrv_dc( dev );
1761 UINT aa_flags, i;
1762 DWORD err;
1763 HGDIOBJ orig;
1764 HPEN pen;
1766 if (flags & ETO_OPAQUE)
1768 RECT rc = *rect;
1769 HBRUSH brush = CreateSolidBrush( GetNearestColor( dev->hdc, GetBkColor(dev->hdc) ));
1771 if (brush)
1773 orig = SelectObject( dev->hdc, brush );
1774 DPtoLP( dev->hdc, (POINT *)&rc, 2 );
1775 PatBlt( dev->hdc, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, PATCOPY );
1776 SelectObject( dev->hdc, orig );
1777 DeleteObject( brush );
1781 if (!count) return TRUE;
1783 aa_flags = get_font_aa_flags( dev->hdc );
1785 if (aa_flags != GGO_BITMAP)
1787 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1788 BITMAPINFO *info = (BITMAPINFO *)buffer;
1789 struct gdi_image_bits bits;
1790 struct bitblt_coords src, dst;
1791 PHYSDEV dst_dev;
1792 RECT clip;
1794 dst_dev = GET_DC_PHYSDEV( dc, pPutImage );
1795 src.visrect = get_total_extents( dev->hdc, x, y, flags, aa_flags, str, count, dx );
1796 if (flags & ETO_CLIPPED) intersect_rect( &src.visrect, &src.visrect, rect );
1797 if (get_clip_box( dc, &clip )) intersect_rect( &src.visrect, &src.visrect, &clip );
1798 if (is_rect_empty( &src.visrect )) return TRUE;
1800 /* FIXME: check for ETO_OPAQUE and avoid GetImage */
1801 src.x = src.visrect.left;
1802 src.y = src.visrect.top;
1803 src.width = src.visrect.right - src.visrect.left;
1804 src.height = src.visrect.bottom - src.visrect.top;
1805 dst = src;
1806 if ((flags & ETO_OPAQUE) && (src.visrect.left >= rect->left) && (src.visrect.top >= rect->top) &&
1807 (src.visrect.right <= rect->right) && (src.visrect.bottom <= rect->bottom))
1809 /* we can avoid the GetImage, just query the needed format */
1810 memset( &info->bmiHeader, 0, sizeof(info->bmiHeader) );
1811 info->bmiHeader.biSize = sizeof(info->bmiHeader);
1812 info->bmiHeader.biWidth = src.width;
1813 info->bmiHeader.biHeight = -src.height;
1814 err = dst_dev->funcs->pPutImage( dst_dev, 0, 0, info, NULL, NULL, NULL, 0 );
1815 if (!err || err == ERROR_BAD_FORMAT)
1817 /* make the source rectangle relative to the source bits */
1818 src.x = src.y = 0;
1819 src.visrect.left = src.visrect.top = 0;
1820 src.visrect.right = src.width;
1821 src.visrect.bottom = src.height;
1823 bits.ptr = HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( info ));
1824 if (!bits.ptr) return ERROR_OUTOFMEMORY;
1825 bits.is_copy = TRUE;
1826 bits.free = free_heap_bits;
1827 err = ERROR_SUCCESS;
1830 else
1832 PHYSDEV src_dev = GET_DC_PHYSDEV( dc, pGetImage );
1833 err = src_dev->funcs->pGetImage( src_dev, 0, info, &bits, &src );
1834 if (!err && !bits.is_copy)
1836 void *ptr = HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( info ));
1837 if (!ptr)
1839 if (bits.free) bits.free( &bits );
1840 return ERROR_OUTOFMEMORY;
1842 memcpy( ptr, bits.ptr, get_dib_image_size( info ));
1843 if (bits.free) bits.free( &bits );
1844 bits.ptr = ptr;
1845 bits.is_copy = TRUE;
1846 bits.free = free_heap_bits;
1849 if (!err)
1851 /* make x,y relative to the image bits */
1852 x += src.visrect.left - dst.visrect.left;
1853 y += src.visrect.top - dst.visrect.top;
1854 render_aa_text_bitmapinfo( dev->hdc, info, &bits, &src, x, y, flags,
1855 aa_flags, str, count, dx );
1856 err = dst_dev->funcs->pPutImage( dst_dev, 0, 0, info, &bits, &src, &dst, SRCCOPY );
1857 if (bits.free) bits.free( &bits );
1858 return !err;
1862 pen = CreatePen( PS_SOLID, 1, GetTextColor(dev->hdc) );
1863 orig = SelectObject( dev->hdc, pen );
1865 for (i = 0; i < count; i++)
1867 GLYPHMETRICS metrics;
1868 struct gdi_image_bits image;
1870 err = get_glyph_bitmap( dev->hdc, (UINT)str[i], GGO_BITMAP, &metrics, &image );
1871 if (err) continue;
1873 if (image.ptr) draw_glyph( dev->hdc, x, y, &metrics, &image, (flags & ETO_CLIPPED) ? rect : NULL );
1874 if (image.free) image.free( &image );
1876 if (dx)
1878 if (flags & ETO_PDY)
1880 x += dx[ i * 2 ];
1881 y += dx[ i * 2 + 1];
1883 else x += dx[ i ];
1885 else
1887 x += metrics.gmCellIncX;
1888 y += metrics.gmCellIncY;
1892 SelectObject( dev->hdc, orig );
1893 DeleteObject( pen );
1894 return TRUE;
1898 /***********************************************************************
1899 * ExtTextOutA (GDI32.@)
1901 * See ExtTextOutW.
1903 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1904 const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1906 INT wlen;
1907 UINT codepage;
1908 LPWSTR p;
1909 BOOL ret;
1910 LPINT lpDxW = NULL;
1912 if (flags & ETO_GLYPH_INDEX)
1913 return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
1915 p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
1917 if (lpDx) {
1918 unsigned int i = 0, j = 0;
1920 /* allocate enough for a ETO_PDY */
1921 lpDxW = HeapAlloc( GetProcessHeap(), 0, 2*wlen*sizeof(INT));
1922 while(i < count) {
1923 if(IsDBCSLeadByteEx(codepage, str[i]))
1925 if(flags & ETO_PDY)
1927 lpDxW[j++] = lpDx[i * 2] + lpDx[(i + 1) * 2];
1928 lpDxW[j++] = lpDx[i * 2 + 1] + lpDx[(i + 1) * 2 + 1];
1930 else
1931 lpDxW[j++] = lpDx[i] + lpDx[i + 1];
1932 i = i + 2;
1934 else
1936 if(flags & ETO_PDY)
1938 lpDxW[j++] = lpDx[i * 2];
1939 lpDxW[j++] = lpDx[i * 2 + 1];
1941 else
1942 lpDxW[j++] = lpDx[i];
1943 i = i + 1;
1948 ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1950 HeapFree( GetProcessHeap(), 0, p );
1951 HeapFree( GetProcessHeap(), 0, lpDxW );
1952 return ret;
1956 /***********************************************************************
1957 * ExtTextOutW (GDI32.@)
1959 * Draws text using the currently selected font, background color, and text color.
1962 * PARAMS
1963 * x,y [I] coordinates of string
1964 * flags [I]
1965 * ETO_GRAYED - undocumented on MSDN
1966 * ETO_OPAQUE - use background color for fill the rectangle
1967 * ETO_CLIPPED - clipping text to the rectangle
1968 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1969 * than encoded characters. Implies ETO_IGNORELANGUAGE
1970 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1971 * Affects BiDi ordering
1972 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1973 * ETO_PDY - unimplemented
1974 * ETO_NUMERICSLATIN - unimplemented always assumed -
1975 * do not translate numbers into locale representations
1976 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1977 * lprect [I] dimensions for clipping or/and opaquing
1978 * str [I] text string
1979 * count [I] number of symbols in string
1980 * lpDx [I] optional parameter with distance between drawing characters
1982 * RETURNS
1983 * Success: TRUE
1984 * Failure: FALSE
1986 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1987 const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1989 BOOL ret = FALSE;
1990 LPWSTR reordered_str = (LPWSTR)str;
1991 WORD *glyphs = NULL;
1992 UINT align = GetTextAlign( hdc );
1993 DWORD layout = GetLayout( hdc );
1994 POINT pt;
1995 TEXTMETRICW tm;
1996 LOGFONTW lf;
1997 double cosEsc, sinEsc;
1998 INT char_extra;
1999 SIZE sz;
2000 RECT rc;
2001 BOOL done_extents = FALSE;
2002 POINT *deltas = NULL, width = {0, 0};
2003 DWORD type;
2004 DC * dc = get_dc_ptr( hdc );
2005 PHYSDEV physdev;
2006 INT breakRem;
2007 static int quietfixme = 0;
2009 if (!dc) return FALSE;
2011 breakRem = dc->breakRem;
2013 if (quietfixme == 0 && flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN))
2015 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN unimplemented\n");
2016 quietfixme = 1;
2019 update_dc( dc );
2020 physdev = GET_DC_PHYSDEV( dc, pExtTextOut );
2021 type = GetObjectType(hdc);
2022 if(type == OBJ_METADC || type == OBJ_ENHMETADC)
2024 ret = physdev->funcs->pExtTextOut( physdev, x, y, flags, lprect, str, count, lpDx );
2025 release_dc_ptr( dc );
2026 return ret;
2029 if (!lprect)
2030 flags &= ~ETO_CLIPPED;
2032 if (flags & ETO_RTLREADING) align |= TA_RTLREADING;
2033 if (layout & LAYOUT_RTL)
2035 if ((align & TA_CENTER) != TA_CENTER) align ^= TA_RIGHT;
2036 align ^= TA_RTLREADING;
2039 if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && count > 0 )
2041 INT cGlyphs;
2042 reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
2044 BIDI_Reorder( hdc, str, count, GCP_REORDER,
2045 (align & TA_RTLREADING) ? WINE_GCPW_FORCE_RTL : WINE_GCPW_FORCE_LTR,
2046 reordered_str, count, NULL, &glyphs, &cGlyphs);
2048 flags |= ETO_IGNORELANGUAGE;
2049 if (glyphs)
2051 flags |= ETO_GLYPH_INDEX;
2052 if (cGlyphs != count)
2053 count = cGlyphs;
2056 else if(flags & ETO_GLYPH_INDEX)
2057 glyphs = reordered_str;
2059 TRACE("%p, %d, %d, %08x, %s, %s, %d, %p)\n", hdc, x, y, flags,
2060 wine_dbgstr_rect(lprect), debugstr_wn(str, count), count, lpDx);
2061 TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
2063 if(align & TA_UPDATECP)
2065 GetCurrentPositionEx( hdc, &pt );
2066 x = pt.x;
2067 y = pt.y;
2070 GetTextMetricsW(hdc, &tm);
2071 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
2073 if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
2074 lf.lfEscapement = 0;
2076 if(lf.lfEscapement != 0)
2078 cosEsc = cos(lf.lfEscapement * M_PI / 1800);
2079 sinEsc = sin(lf.lfEscapement * M_PI / 1800);
2081 else
2083 cosEsc = 1;
2084 sinEsc = 0;
2087 if(flags & (ETO_CLIPPED | ETO_OPAQUE))
2089 if(!lprect)
2091 if(flags & ETO_GLYPH_INDEX)
2092 GetTextExtentPointI(hdc, glyphs, count, &sz);
2093 else
2094 GetTextExtentPointW(hdc, reordered_str, count, &sz);
2096 done_extents = TRUE;
2097 rc.left = x;
2098 rc.top = y;
2099 rc.right = x + sz.cx;
2100 rc.bottom = y + sz.cy;
2102 else
2104 rc = *lprect;
2107 LPtoDP(hdc, (POINT*)&rc, 2);
2109 if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
2110 if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
2113 if (flags & ETO_OPAQUE)
2114 physdev->funcs->pExtTextOut( physdev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL );
2116 if(count == 0)
2118 ret = TRUE;
2119 goto done;
2122 pt.x = x;
2123 pt.y = y;
2124 LPtoDP(hdc, &pt, 1);
2125 x = pt.x;
2126 y = pt.y;
2128 char_extra = GetTextCharacterExtra(hdc);
2129 if(char_extra || dc->breakExtra || breakRem || lpDx || lf.lfEscapement != 0)
2131 UINT i;
2132 SIZE tmpsz;
2133 POINT total = {0, 0}, desired[2];
2135 deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
2136 for(i = 0; i < count; i++)
2138 if(lpDx)
2140 if(flags & ETO_PDY)
2142 deltas[i].x = lpDx[i * 2] + char_extra;
2143 deltas[i].y = -lpDx[i * 2 + 1];
2145 else
2147 deltas[i].x = lpDx[i] + char_extra;
2148 deltas[i].y = 0;
2152 else
2154 if(flags & ETO_GLYPH_INDEX)
2155 GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
2156 else
2157 GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
2159 deltas[i].x = tmpsz.cx;
2160 deltas[i].y = 0;
2163 if (!(flags & ETO_GLYPH_INDEX) && (dc->breakExtra || breakRem) && reordered_str[i] == tm.tmBreakChar)
2165 deltas[i].x = deltas[i].x + dc->breakExtra;
2166 if (breakRem > 0)
2168 breakRem--;
2169 deltas[i].x++;
2172 total.x += deltas[i].x;
2173 total.y += deltas[i].y;
2175 desired[0].x = desired[0].y = 0;
2177 desired[1].x = cosEsc * total.x + sinEsc * total.y;
2178 desired[1].y = -sinEsc * total.x + cosEsc * total.y;
2180 LPtoDP(hdc, desired, 2);
2181 desired[1].x -= desired[0].x;
2182 desired[1].y -= desired[0].y;
2183 if (layout & LAYOUT_RTL) desired[1].x = -desired[1].x;
2185 deltas[i].x = desired[1].x - width.x;
2186 deltas[i].y = desired[1].y - width.y;
2188 width = desired[1];
2190 flags |= ETO_PDY;
2192 else
2194 if(!done_extents)
2196 if(flags & ETO_GLYPH_INDEX)
2197 GetTextExtentPointI(hdc, glyphs, count, &sz);
2198 else
2199 GetTextExtentPointW(hdc, reordered_str, count, &sz);
2200 done_extents = TRUE;
2202 width.x = abs(INTERNAL_XWSTODS(dc, sz.cx));
2203 width.y = 0;
2206 tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
2207 tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
2208 switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
2210 case TA_LEFT:
2211 if (align & TA_UPDATECP)
2213 pt.x = x + width.x;
2214 pt.y = y + width.y;
2215 DPtoLP(hdc, &pt, 1);
2216 MoveToEx(hdc, pt.x, pt.y, NULL);
2218 break;
2220 case TA_CENTER:
2221 x -= width.x / 2;
2222 y -= width.y / 2;
2223 break;
2225 case TA_RIGHT:
2226 x -= width.x;
2227 y -= width.y;
2228 if (align & TA_UPDATECP)
2230 pt.x = x;
2231 pt.y = y;
2232 DPtoLP(hdc, &pt, 1);
2233 MoveToEx(hdc, pt.x, pt.y, NULL);
2235 break;
2238 switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
2240 case TA_TOP:
2241 y += tm.tmAscent * cosEsc;
2242 x += tm.tmAscent * sinEsc;
2243 break;
2245 case TA_BOTTOM:
2246 y -= tm.tmDescent * cosEsc;
2247 x -= tm.tmDescent * sinEsc;
2248 break;
2250 case TA_BASELINE:
2251 break;
2254 if (GetBkMode(hdc) != TRANSPARENT)
2256 if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
2258 if(!(flags & ETO_OPAQUE) || x < rc.left || x + width.x >= rc.right ||
2259 y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
2261 RECT rc;
2262 rc.left = x;
2263 rc.right = x + width.x;
2264 rc.top = y - tm.tmAscent;
2265 rc.bottom = y + tm.tmDescent;
2267 if(flags & ETO_CLIPPED)
2269 rc.left = max(lprect->left, rc.left);
2270 rc.right = min(lprect->right, rc.right);
2271 rc.top = max(lprect->top, rc.top);
2272 rc.bottom = min(lprect->bottom, rc.bottom);
2274 if(rc.left < rc.right && rc.top < rc.bottom)
2275 physdev->funcs->pExtTextOut( physdev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL );
2280 if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
2282 HFONT orig_font = dc->hFont, cur_font;
2283 UINT glyph;
2284 INT span = 0;
2285 POINT *offsets = NULL;
2286 unsigned int i;
2288 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2289 for(i = 0; i < count; i++)
2291 WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
2292 if(cur_font != dc->hFont)
2294 if(!offsets)
2296 unsigned int j;
2297 offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
2298 offsets[0].x = offsets[0].y = 0;
2300 if(!deltas)
2302 SIZE tmpsz;
2303 for(j = 1; j < count; j++)
2305 GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
2306 offsets[j].x = offsets[j - 1].x + abs(INTERNAL_XWSTODS(dc, tmpsz.cx));
2307 offsets[j].y = 0;
2310 else
2312 for(j = 1; j < count; j++)
2314 offsets[j].x = offsets[j - 1].x + deltas[j].x;
2315 offsets[j].y = offsets[j - 1].y + deltas[j].y;
2319 if(span)
2321 physdev->funcs->pExtTextOut( physdev, x + offsets[i - span].x,
2322 y + offsets[i - span].y,
2323 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc, glyphs,
2324 span, deltas ? (INT*)(deltas + (i - span)) : NULL);
2325 span = 0;
2327 SelectObject(hdc, cur_font);
2329 glyphs[span++] = glyph;
2331 if(i == count - 1)
2333 ret = physdev->funcs->pExtTextOut(physdev, x + (offsets ? offsets[count - span].x : 0),
2334 y + (offsets ? offsets[count - span].y : 0),
2335 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc, glyphs,
2336 span, deltas ? (INT*)(deltas + (count - span)) : NULL);
2337 SelectObject(hdc, orig_font);
2338 HeapFree(GetProcessHeap(), 0, offsets);
2342 else
2344 if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
2346 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2347 GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
2348 flags |= ETO_GLYPH_INDEX;
2350 ret = physdev->funcs->pExtTextOut( physdev, x, y, (flags & ~ETO_OPAQUE), &rc,
2351 glyphs ? glyphs : reordered_str, count, (INT*)deltas );
2354 done:
2355 HeapFree(GetProcessHeap(), 0, deltas);
2356 if(glyphs != reordered_str)
2357 HeapFree(GetProcessHeap(), 0, glyphs);
2358 if(reordered_str != str)
2359 HeapFree(GetProcessHeap(), 0, reordered_str);
2361 release_dc_ptr( dc );
2363 if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2365 int underlinePos, strikeoutPos;
2366 int underlineWidth, strikeoutWidth;
2367 UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2368 OUTLINETEXTMETRICW* otm = NULL;
2369 POINT pts[5];
2370 HPEN hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2371 HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2373 hbrush = SelectObject(hdc, hbrush);
2375 if(!size)
2377 underlinePos = 0;
2378 underlineWidth = tm.tmAscent / 20 + 1;
2379 strikeoutPos = tm.tmAscent / 2;
2380 strikeoutWidth = underlineWidth;
2382 else
2384 otm = HeapAlloc(GetProcessHeap(), 0, size);
2385 GetOutlineTextMetricsW(hdc, size, otm);
2386 underlinePos = abs( INTERNAL_YWSTODS( dc, otm->otmsUnderscorePosition ));
2387 if (otm->otmsUnderscorePosition < 0) underlinePos = -underlinePos;
2388 underlineWidth = abs( INTERNAL_YWSTODS( dc, otm->otmsUnderscoreSize ));
2389 if (otm->otmsUnderscoreSize < 0) underlineWidth = -underlineWidth;
2390 strikeoutPos = abs( INTERNAL_YWSTODS( dc, otm->otmsStrikeoutPosition ));
2391 if (otm->otmsStrikeoutPosition < 0) strikeoutPos = -strikeoutPos;
2392 strikeoutWidth = abs( INTERNAL_YWSTODS( dc, otm->otmsStrikeoutSize ));
2393 HeapFree(GetProcessHeap(), 0, otm);
2397 if (lf.lfUnderline)
2399 pts[0].x = x - (underlinePos + underlineWidth / 2) * sinEsc;
2400 pts[0].y = y - (underlinePos + underlineWidth / 2) * cosEsc;
2401 pts[1].x = x + width.x - (underlinePos + underlineWidth / 2) * sinEsc;
2402 pts[1].y = y + width.y - (underlinePos + underlineWidth / 2) * cosEsc;
2403 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2404 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2405 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2406 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2407 pts[4].x = pts[0].x;
2408 pts[4].y = pts[0].y;
2409 DPtoLP(hdc, pts, 5);
2410 Polygon(hdc, pts, 5);
2413 if (lf.lfStrikeOut)
2415 pts[0].x = x - (strikeoutPos + strikeoutWidth / 2) * sinEsc;
2416 pts[0].y = y - (strikeoutPos + strikeoutWidth / 2) * cosEsc;
2417 pts[1].x = x + width.x - (strikeoutPos + strikeoutWidth / 2) * sinEsc;
2418 pts[1].y = y + width.y - (strikeoutPos + strikeoutWidth / 2) * cosEsc;
2419 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2420 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2421 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2422 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2423 pts[4].x = pts[0].x;
2424 pts[4].y = pts[0].y;
2425 DPtoLP(hdc, pts, 5);
2426 Polygon(hdc, pts, 5);
2429 SelectObject(hdc, hpen);
2430 hbrush = SelectObject(hdc, hbrush);
2431 DeleteObject(hbrush);
2434 return ret;
2438 /***********************************************************************
2439 * TextOutA (GDI32.@)
2441 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2443 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2447 /***********************************************************************
2448 * TextOutW (GDI32.@)
2450 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2452 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2456 /***********************************************************************
2457 * PolyTextOutA (GDI32.@)
2459 * See PolyTextOutW.
2461 BOOL WINAPI PolyTextOutA( HDC hdc, const POLYTEXTA *pptxt, INT cStrings )
2463 for (; cStrings>0; cStrings--, pptxt++)
2464 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2465 return FALSE;
2466 return TRUE;
2471 /***********************************************************************
2472 * PolyTextOutW (GDI32.@)
2474 * Draw several Strings
2476 * RETURNS
2477 * TRUE: Success.
2478 * FALSE: Failure.
2480 BOOL WINAPI PolyTextOutW( HDC hdc, const POLYTEXTW *pptxt, INT cStrings )
2482 for (; cStrings>0; cStrings--, pptxt++)
2483 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2484 return FALSE;
2485 return TRUE;
2489 /***********************************************************************
2490 * SetMapperFlags (GDI32.@)
2492 DWORD WINAPI SetMapperFlags( HDC hdc, DWORD flags )
2494 DC *dc = get_dc_ptr( hdc );
2495 DWORD ret = GDI_ERROR;
2497 if (dc)
2499 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetMapperFlags );
2500 flags = physdev->funcs->pSetMapperFlags( physdev, flags );
2501 if (flags != GDI_ERROR)
2503 ret = dc->mapperFlags;
2504 dc->mapperFlags = flags;
2506 release_dc_ptr( dc );
2508 return ret;
2511 /***********************************************************************
2512 * GetAspectRatioFilterEx (GDI32.@)
2514 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2516 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2517 return FALSE;
2521 /***********************************************************************
2522 * GetCharABCWidthsA (GDI32.@)
2524 * See GetCharABCWidthsW.
2526 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2527 LPABC abc )
2529 INT i, wlen;
2530 LPSTR str;
2531 LPWSTR wstr;
2532 BOOL ret = TRUE;
2534 str = FONT_GetCharsByRangeA(hdc, firstChar, lastChar, &i);
2535 if (str == NULL)
2536 return FALSE;
2538 wstr = FONT_mbtowc(hdc, str, i, &wlen, NULL);
2539 if (wstr == NULL)
2541 HeapFree(GetProcessHeap(), 0, str);
2542 return FALSE;
2545 for(i = 0; i < wlen; i++)
2547 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2549 ret = FALSE;
2550 break;
2552 abc++;
2555 HeapFree(GetProcessHeap(), 0, str);
2556 HeapFree(GetProcessHeap(), 0, wstr);
2558 return ret;
2562 /******************************************************************************
2563 * GetCharABCWidthsW [GDI32.@]
2565 * Retrieves widths of characters in range.
2567 * PARAMS
2568 * hdc [I] Handle of device context
2569 * firstChar [I] First character in range to query
2570 * lastChar [I] Last character in range to query
2571 * abc [O] Address of character-width structure
2573 * NOTES
2574 * Only works with TrueType fonts
2576 * RETURNS
2577 * Success: TRUE
2578 * Failure: FALSE
2580 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2581 LPABC abc )
2583 DC *dc = get_dc_ptr(hdc);
2584 PHYSDEV dev;
2585 unsigned int i;
2586 BOOL ret;
2588 if (!dc) return FALSE;
2590 if (!abc)
2592 release_dc_ptr( dc );
2593 return FALSE;
2596 dev = GET_DC_PHYSDEV( dc, pGetCharABCWidths );
2597 ret = dev->funcs->pGetCharABCWidths( dev, firstChar, lastChar, abc );
2598 if (ret)
2600 /* convert device units to logical */
2601 for( i = firstChar; i <= lastChar; i++, abc++ ) {
2602 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2603 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2604 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2608 release_dc_ptr( dc );
2609 return ret;
2613 /******************************************************************************
2614 * GetCharABCWidthsI [GDI32.@]
2616 * Retrieves widths of characters in range.
2618 * PARAMS
2619 * hdc [I] Handle of device context
2620 * firstChar [I] First glyphs in range to query
2621 * count [I] Last glyphs in range to query
2622 * pgi [i] Array of glyphs to query
2623 * abc [O] Address of character-width structure
2625 * NOTES
2626 * Only works with TrueType fonts
2628 * RETURNS
2629 * Success: TRUE
2630 * Failure: FALSE
2632 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2633 LPWORD pgi, LPABC abc)
2635 DC *dc = get_dc_ptr(hdc);
2636 PHYSDEV dev;
2637 unsigned int i;
2638 BOOL ret;
2640 if (!dc) return FALSE;
2642 if (!abc)
2644 release_dc_ptr( dc );
2645 return FALSE;
2648 dev = GET_DC_PHYSDEV( dc, pGetCharABCWidthsI );
2649 ret = dev->funcs->pGetCharABCWidthsI( dev, firstChar, count, pgi, abc );
2650 if (ret)
2652 /* convert device units to logical */
2653 for( i = 0; i < count; i++, abc++ ) {
2654 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2655 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2656 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2660 release_dc_ptr( dc );
2661 return ret;
2665 /***********************************************************************
2666 * GetGlyphOutlineA (GDI32.@)
2668 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2669 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2670 LPVOID lpBuffer, const MAT2 *lpmat2 )
2672 if (!lpmat2) return GDI_ERROR;
2674 if(!(fuFormat & GGO_GLYPH_INDEX)) {
2675 UINT cp;
2676 int len;
2677 char mbchs[2];
2679 cp = GdiGetCodePage(hdc);
2680 if (IsDBCSLeadByteEx(cp, uChar >> 8)) {
2681 len = 2;
2682 mbchs[0] = (uChar & 0xff00) >> 8;
2683 mbchs[1] = (uChar & 0xff);
2684 } else {
2685 len = 1;
2686 mbchs[0] = (uChar & 0xff);
2688 uChar = 0;
2689 MultiByteToWideChar(cp, 0, mbchs, len, (LPWSTR)&uChar, 1);
2692 return GetGlyphOutlineW(hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer,
2693 lpmat2);
2696 /***********************************************************************
2697 * GetGlyphOutlineW (GDI32.@)
2699 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2700 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2701 LPVOID lpBuffer, const MAT2 *lpmat2 )
2703 DC *dc;
2704 DWORD ret;
2705 PHYSDEV dev;
2707 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2708 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2710 if (!lpmat2) return GDI_ERROR;
2712 dc = get_dc_ptr(hdc);
2713 if(!dc) return GDI_ERROR;
2715 dev = GET_DC_PHYSDEV( dc, pGetGlyphOutline );
2716 ret = dev->funcs->pGetGlyphOutline( dev, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2717 release_dc_ptr( dc );
2718 return ret;
2722 /***********************************************************************
2723 * CreateScalableFontResourceA (GDI32.@)
2725 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2726 LPCSTR lpszResourceFile,
2727 LPCSTR lpszFontFile,
2728 LPCSTR lpszCurrentPath )
2730 LPWSTR lpszResourceFileW = NULL;
2731 LPWSTR lpszFontFileW = NULL;
2732 LPWSTR lpszCurrentPathW = NULL;
2733 int len;
2734 BOOL ret;
2736 if (lpszResourceFile)
2738 len = MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, NULL, 0);
2739 lpszResourceFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2740 MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, lpszResourceFileW, len);
2743 if (lpszFontFile)
2745 len = MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, NULL, 0);
2746 lpszFontFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2747 MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, lpszFontFileW, len);
2750 if (lpszCurrentPath)
2752 len = MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, NULL, 0);
2753 lpszCurrentPathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2754 MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, lpszCurrentPathW, len);
2757 ret = CreateScalableFontResourceW(fHidden, lpszResourceFileW,
2758 lpszFontFileW, lpszCurrentPathW);
2760 HeapFree(GetProcessHeap(), 0, lpszResourceFileW);
2761 HeapFree(GetProcessHeap(), 0, lpszFontFileW);
2762 HeapFree(GetProcessHeap(), 0, lpszCurrentPathW);
2764 return ret;
2767 /***********************************************************************
2768 * CreateScalableFontResourceW (GDI32.@)
2770 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2771 LPCWSTR lpszResourceFile,
2772 LPCWSTR lpszFontFile,
2773 LPCWSTR lpszCurrentPath )
2775 HANDLE f;
2776 FIXME("(%d,%s,%s,%s): stub\n",
2777 fHidden, debugstr_w(lpszResourceFile), debugstr_w(lpszFontFile),
2778 debugstr_w(lpszCurrentPath) );
2780 /* fHidden=1 - only visible for the calling app, read-only, not
2781 * enumerated with EnumFonts/EnumFontFamilies
2782 * lpszCurrentPath can be NULL
2785 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2786 if ((f = CreateFileW(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2787 CloseHandle(f);
2788 SetLastError(ERROR_FILE_EXISTS);
2789 return FALSE;
2791 return FALSE; /* create failed */
2794 /*************************************************************************
2795 * GetKerningPairsA (GDI32.@)
2797 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2798 LPKERNINGPAIR kern_pairA )
2800 UINT cp;
2801 CPINFO cpi;
2802 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2803 KERNINGPAIR *kern_pairW;
2805 if (!cPairs && kern_pairA)
2807 SetLastError(ERROR_INVALID_PARAMETER);
2808 return 0;
2811 cp = GdiGetCodePage(hDC);
2813 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2814 * to fail on an invalid character for CP_SYMBOL.
2816 cpi.DefaultChar[0] = 0;
2817 if (cp != CP_SYMBOL && !GetCPInfo(cp, &cpi))
2819 FIXME("Can't find codepage %u info\n", cp);
2820 return 0;
2823 total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2824 if (!total_kern_pairs) return 0;
2826 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2827 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2829 for (i = 0; i < total_kern_pairs; i++)
2831 char first, second;
2833 if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2834 continue;
2836 if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2837 continue;
2839 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2840 continue;
2842 if (kern_pairA)
2844 if (kern_pairs_copied >= cPairs) break;
2846 kern_pairA->wFirst = (BYTE)first;
2847 kern_pairA->wSecond = (BYTE)second;
2848 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2849 kern_pairA++;
2851 kern_pairs_copied++;
2854 HeapFree(GetProcessHeap(), 0, kern_pairW);
2856 return kern_pairs_copied;
2859 /*************************************************************************
2860 * GetKerningPairsW (GDI32.@)
2862 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2863 LPKERNINGPAIR lpKerningPairs )
2865 DC *dc;
2866 DWORD ret;
2867 PHYSDEV dev;
2869 TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2871 if (!cPairs && lpKerningPairs)
2873 SetLastError(ERROR_INVALID_PARAMETER);
2874 return 0;
2877 dc = get_dc_ptr(hDC);
2878 if (!dc) return 0;
2880 dev = GET_DC_PHYSDEV( dc, pGetKerningPairs );
2881 ret = dev->funcs->pGetKerningPairs( dev, cPairs, lpKerningPairs );
2882 release_dc_ptr( dc );
2883 return ret;
2886 /*************************************************************************
2887 * TranslateCharsetInfo [GDI32.@]
2889 * Fills a CHARSETINFO structure for a character set, code page, or
2890 * font. This allows making the correspondence between different labels
2891 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2892 * of the same encoding.
2894 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2895 * only one codepage should be set in *lpSrc.
2897 * RETURNS
2898 * TRUE on success, FALSE on failure.
2901 BOOL WINAPI TranslateCharsetInfo(
2902 LPDWORD lpSrc, /* [in]
2903 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2904 if flags == TCI_SRCCHARSET: a character set value
2905 if flags == TCI_SRCCODEPAGE: a code page value
2907 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2908 DWORD flags /* [in] determines interpretation of lpSrc */)
2910 int index = 0;
2911 switch (flags) {
2912 case TCI_SRCFONTSIG:
2913 while (index < MAXTCIINDEX && !(*lpSrc>>index & 0x0001)) index++;
2914 break;
2915 case TCI_SRCCODEPAGE:
2916 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciACP) index++;
2917 break;
2918 case TCI_SRCCHARSET:
2919 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciCharset) index++;
2920 break;
2921 default:
2922 return FALSE;
2924 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2925 *lpCs = FONT_tci[index];
2926 return TRUE;
2929 /*************************************************************************
2930 * GetFontLanguageInfo (GDI32.@)
2932 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2934 FONTSIGNATURE fontsig;
2935 static const DWORD GCP_DBCS_MASK=0x003F0000,
2936 GCP_DIACRITIC_MASK=0x00000000,
2937 FLI_GLYPHS_MASK=0x00000000,
2938 GCP_GLYPHSHAPE_MASK=0x00000040,
2939 GCP_KASHIDA_MASK=0x00000000,
2940 GCP_LIGATE_MASK=0x00000000,
2941 GCP_USEKERNING_MASK=0x00000000,
2942 GCP_REORDER_MASK=0x00000060;
2944 DWORD result=0;
2946 GetTextCharsetInfo( hdc, &fontsig, 0 );
2947 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2949 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2950 result|=GCP_DBCS;
2952 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2953 result|=GCP_DIACRITIC;
2955 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2956 result|=FLI_GLYPHS;
2958 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2959 result|=GCP_GLYPHSHAPE;
2961 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2962 result|=GCP_KASHIDA;
2964 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2965 result|=GCP_LIGATE;
2967 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2968 result|=GCP_USEKERNING;
2970 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2971 if( GetTextAlign( hdc) & TA_RTLREADING )
2972 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2973 result|=GCP_REORDER;
2975 return result;
2979 /*************************************************************************
2980 * GetFontData [GDI32.@]
2982 * Retrieve data for TrueType font.
2984 * RETURNS
2986 * success: Number of bytes returned
2987 * failure: GDI_ERROR
2989 * NOTES
2991 * Calls SetLastError()
2994 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2995 LPVOID buffer, DWORD length)
2997 DC *dc = get_dc_ptr(hdc);
2998 PHYSDEV dev;
2999 DWORD ret;
3001 if(!dc) return GDI_ERROR;
3003 dev = GET_DC_PHYSDEV( dc, pGetFontData );
3004 ret = dev->funcs->pGetFontData( dev, table, offset, buffer, length );
3005 release_dc_ptr( dc );
3006 return ret;
3009 /*************************************************************************
3010 * GetGlyphIndicesA [GDI32.@]
3012 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
3013 LPWORD pgi, DWORD flags)
3015 DWORD ret;
3016 WCHAR *lpstrW;
3017 INT countW;
3019 TRACE("(%p, %s, %d, %p, 0x%x)\n",
3020 hdc, debugstr_an(lpstr, count), count, pgi, flags);
3022 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
3023 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
3024 HeapFree(GetProcessHeap(), 0, lpstrW);
3026 return ret;
3029 /*************************************************************************
3030 * GetGlyphIndicesW [GDI32.@]
3032 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
3033 LPWORD pgi, DWORD flags)
3035 DC *dc = get_dc_ptr(hdc);
3036 PHYSDEV dev;
3037 DWORD ret;
3039 TRACE("(%p, %s, %d, %p, 0x%x)\n",
3040 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
3042 if(!dc) return GDI_ERROR;
3044 dev = GET_DC_PHYSDEV( dc, pGetGlyphIndices );
3045 ret = dev->funcs->pGetGlyphIndices( dev, lpstr, count, pgi, flags );
3046 release_dc_ptr( dc );
3047 return ret;
3050 /*************************************************************************
3051 * GetCharacterPlacementA [GDI32.@]
3053 * See GetCharacterPlacementW.
3055 * NOTES:
3056 * the web browser control of ie4 calls this with dwFlags=0
3058 DWORD WINAPI
3059 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
3060 INT nMaxExtent, GCP_RESULTSA *lpResults,
3061 DWORD dwFlags)
3063 WCHAR *lpStringW;
3064 INT uCountW;
3065 GCP_RESULTSW resultsW;
3066 DWORD ret;
3067 UINT font_cp;
3069 TRACE("%s, %d, %d, 0x%08x\n",
3070 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
3072 /* both structs are equal in size */
3073 memcpy(&resultsW, lpResults, sizeof(resultsW));
3075 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
3076 if(lpResults->lpOutString)
3077 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
3079 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
3081 lpResults->nGlyphs = resultsW.nGlyphs;
3082 lpResults->nMaxFit = resultsW.nMaxFit;
3084 if(lpResults->lpOutString) {
3085 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
3086 lpResults->lpOutString, uCount, NULL, NULL );
3089 HeapFree(GetProcessHeap(), 0, lpStringW);
3090 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
3092 return ret;
3095 /*************************************************************************
3096 * GetCharacterPlacementW [GDI32.@]
3098 * Retrieve information about a string. This includes the width, reordering,
3099 * Glyphing and so on.
3101 * RETURNS
3103 * The width and height of the string if successful, 0 if failed.
3105 * BUGS
3107 * All flags except GCP_REORDER are not yet implemented.
3108 * Reordering is not 100% compliant to the Windows BiDi method.
3109 * Caret positioning is not yet implemented for BiDi.
3110 * Classes are not yet implemented.
3113 DWORD WINAPI
3114 GetCharacterPlacementW(
3115 HDC hdc, /* [in] Device context for which the rendering is to be done */
3116 LPCWSTR lpString, /* [in] The string for which information is to be returned */
3117 INT uCount, /* [in] Number of WORDS in string. */
3118 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
3119 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
3120 DWORD dwFlags /* [in] Flags specifying how to process the string */
3123 DWORD ret=0;
3124 SIZE size;
3125 UINT i, nSet;
3127 TRACE("%s, %d, %d, 0x%08x\n",
3128 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
3130 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
3131 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
3132 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
3133 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
3134 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
3136 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08x ignored\n", dwFlags);
3137 if(lpResults->lpClass) FIXME("classes not implemented\n");
3138 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
3139 FIXME("Caret positions for complex scripts not implemented\n");
3141 nSet = (UINT)uCount;
3142 if(nSet > lpResults->nGlyphs)
3143 nSet = lpResults->nGlyphs;
3145 /* return number of initialized fields */
3146 lpResults->nGlyphs = nSet;
3148 if((dwFlags&GCP_REORDER)==0 )
3150 /* Treat the case where no special handling was requested in a fastpath way */
3151 /* copy will do if the GCP_REORDER flag is not set */
3152 if(lpResults->lpOutString)
3153 memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
3155 if(lpResults->lpOrder)
3157 for(i = 0; i < nSet; i++)
3158 lpResults->lpOrder[i] = i;
3160 } else
3162 BIDI_Reorder(NULL, lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
3163 nSet, lpResults->lpOrder, NULL, NULL );
3166 /* FIXME: Will use the placement chars */
3167 if (lpResults->lpDx)
3169 int c;
3170 for (i = 0; i < nSet; i++)
3172 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
3173 lpResults->lpDx[i]= c;
3177 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
3179 int pos = 0;
3181 lpResults->lpCaretPos[0] = 0;
3182 for (i = 1; i < nSet; i++)
3183 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
3184 lpResults->lpCaretPos[i] = (pos += size.cx);
3187 if(lpResults->lpGlyphs)
3188 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
3190 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
3191 ret = MAKELONG(size.cx, size.cy);
3193 return ret;
3196 /*************************************************************************
3197 * GetCharABCWidthsFloatA [GDI32.@]
3199 * See GetCharABCWidthsFloatW.
3201 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3203 INT i, wlen;
3204 LPSTR str;
3205 LPWSTR wstr;
3206 BOOL ret = TRUE;
3208 str = FONT_GetCharsByRangeA(hdc, first, last, &i);
3209 if (str == NULL)
3210 return FALSE;
3212 wstr = FONT_mbtowc( hdc, str, i, &wlen, NULL );
3214 for (i = 0; i < wlen; i++)
3216 if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
3218 ret = FALSE;
3219 break;
3221 abcf++;
3224 HeapFree( GetProcessHeap(), 0, str );
3225 HeapFree( GetProcessHeap(), 0, wstr );
3227 return ret;
3230 /*************************************************************************
3231 * GetCharABCWidthsFloatW [GDI32.@]
3233 * Retrieves widths of a range of characters.
3235 * PARAMS
3236 * hdc [I] Handle to device context.
3237 * first [I] First character in range to query.
3238 * last [I] Last character in range to query.
3239 * abcf [O] Array of LPABCFLOAT structures.
3241 * RETURNS
3242 * Success: TRUE
3243 * Failure: FALSE
3245 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3247 UINT i;
3248 ABC *abc;
3249 PHYSDEV dev;
3250 BOOL ret = FALSE;
3251 DC *dc = get_dc_ptr( hdc );
3253 TRACE("%p, %d, %d, %p\n", hdc, first, last, abcf);
3255 if (!dc) return FALSE;
3257 if (!abcf) goto done;
3258 if (!(abc = HeapAlloc( GetProcessHeap(), 0, (last - first + 1) * sizeof(*abc) ))) goto done;
3260 dev = GET_DC_PHYSDEV( dc, pGetCharABCWidths );
3261 ret = dev->funcs->pGetCharABCWidths( dev, first, last, abc );
3262 if (ret)
3264 /* convert device units to logical */
3265 for (i = first; i <= last; i++, abcf++)
3267 abcf->abcfA = abc->abcA * dc->xformVport2World.eM11;
3268 abcf->abcfB = abc->abcB * dc->xformVport2World.eM11;
3269 abcf->abcfC = abc->abcC * dc->xformVport2World.eM11;
3272 HeapFree( GetProcessHeap(), 0, abc );
3274 done:
3275 release_dc_ptr( dc );
3276 return ret;
3279 /*************************************************************************
3280 * GetCharWidthFloatA [GDI32.@]
3282 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
3283 UINT iLastChar, PFLOAT pxBuffer)
3285 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3286 return 0;
3289 /*************************************************************************
3290 * GetCharWidthFloatW [GDI32.@]
3292 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
3293 UINT iLastChar, PFLOAT pxBuffer)
3295 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3296 return 0;
3300 /***********************************************************************
3302 * Font Resource API *
3304 ***********************************************************************/
3306 /***********************************************************************
3307 * AddFontResourceA (GDI32.@)
3309 INT WINAPI AddFontResourceA( LPCSTR str )
3311 return AddFontResourceExA( str, 0, NULL);
3314 /***********************************************************************
3315 * AddFontResourceW (GDI32.@)
3317 INT WINAPI AddFontResourceW( LPCWSTR str )
3319 return AddFontResourceExW(str, 0, NULL);
3323 /***********************************************************************
3324 * AddFontResourceExA (GDI32.@)
3326 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3328 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3329 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3330 INT ret;
3332 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3333 ret = AddFontResourceExW(strW, fl, pdv);
3334 HeapFree(GetProcessHeap(), 0, strW);
3335 return ret;
3338 static BOOL CALLBACK load_enumed_resource(HMODULE hModule, LPCWSTR type, LPWSTR name, LONG_PTR lParam)
3340 HRSRC rsrc = FindResourceW(hModule, name, type);
3341 HGLOBAL hMem = LoadResource(hModule, rsrc);
3342 LPVOID *pMem = LockResource(hMem);
3343 int *num_total = (int *)lParam;
3344 DWORD num_in_res;
3346 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type));
3347 if (!AddFontMemResourceEx(pMem, SizeofResource(hModule, rsrc), NULL, &num_in_res))
3349 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule, hMem);
3350 return FALSE;
3353 *num_total += num_in_res;
3354 return TRUE;
3357 /***********************************************************************
3358 * AddFontResourceExW (GDI32.@)
3360 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3362 int ret = WineEngAddFontResourceEx(str, fl, pdv);
3363 if (ret == 0)
3365 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3366 HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
3367 if (hModule != NULL)
3369 int num_resources = 0;
3370 LPWSTR rt_font = (LPWSTR)((ULONG_PTR)8); /* we don't want to include winuser.h */
3372 TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3373 wine_dbgstr_w(str));
3374 if (EnumResourceNamesW(hModule, rt_font, load_enumed_resource, (LONG_PTR)&num_resources))
3375 ret = num_resources;
3376 FreeLibrary(hModule);
3379 return ret;
3382 /***********************************************************************
3383 * RemoveFontResourceA (GDI32.@)
3385 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3387 return RemoveFontResourceExA(str, 0, 0);
3390 /***********************************************************************
3391 * RemoveFontResourceW (GDI32.@)
3393 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3395 return RemoveFontResourceExW(str, 0, 0);
3398 /***********************************************************************
3399 * AddFontMemResourceEx (GDI32.@)
3401 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3403 HANDLE ret;
3404 DWORD num_fonts;
3406 if (!pbFont || !cbFont || !pcFonts)
3408 SetLastError(ERROR_INVALID_PARAMETER);
3409 return NULL;
3412 ret = WineEngAddFontMemResourceEx(pbFont, cbFont, pdv, &num_fonts);
3413 if (ret)
3415 __TRY
3417 *pcFonts = num_fonts;
3419 __EXCEPT_PAGE_FAULT
3421 WARN("page fault while writing to *pcFonts (%p)\n", pcFonts);
3422 RemoveFontMemResourceEx(ret);
3423 ret = 0;
3425 __ENDTRY
3427 return ret;
3430 /***********************************************************************
3431 * RemoveFontMemResourceEx (GDI32.@)
3433 BOOL WINAPI RemoveFontMemResourceEx( HANDLE fh )
3435 FIXME("(%p) stub\n", fh);
3436 return TRUE;
3439 /***********************************************************************
3440 * RemoveFontResourceExA (GDI32.@)
3442 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3444 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3445 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3446 INT ret;
3448 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3449 ret = RemoveFontResourceExW(strW, fl, pdv);
3450 HeapFree(GetProcessHeap(), 0, strW);
3451 return ret;
3454 /***********************************************************************
3455 * RemoveFontResourceExW (GDI32.@)
3457 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3459 return WineEngRemoveFontResourceEx(str, fl, pdv);
3462 /***********************************************************************
3463 * GetTextCharset (GDI32.@)
3465 UINT WINAPI GetTextCharset(HDC hdc)
3467 /* MSDN docs say this is equivalent */
3468 return GetTextCharsetInfo(hdc, NULL, 0);
3471 /***********************************************************************
3472 * GetTextCharsetInfo (GDI32.@)
3474 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3476 UINT ret = DEFAULT_CHARSET;
3477 DC *dc = get_dc_ptr(hdc);
3478 PHYSDEV dev;
3480 if (dc)
3482 dev = GET_DC_PHYSDEV( dc, pGetTextCharsetInfo );
3483 ret = dev->funcs->pGetTextCharsetInfo( dev, fs, flags );
3484 release_dc_ptr( dc );
3487 if (ret == DEFAULT_CHARSET && fs)
3488 memset(fs, 0, sizeof(FONTSIGNATURE));
3489 return ret;
3492 /***********************************************************************
3493 * GdiGetCharDimensions (GDI32.@)
3495 * Gets the average width of the characters in the English alphabet.
3497 * PARAMS
3498 * hdc [I] Handle to the device context to measure on.
3499 * lptm [O] Pointer to memory to store the text metrics into.
3500 * height [O] On exit, the maximum height of characters in the English alphabet.
3502 * RETURNS
3503 * The average width of characters in the English alphabet.
3505 * NOTES
3506 * This function is used by the dialog manager to get the size of a dialog
3507 * unit. It should also be used by other pieces of code that need to know
3508 * the size of a dialog unit in logical units without having access to the
3509 * window handle of the dialog.
3510 * Windows caches the font metrics from this function, but we don't and
3511 * there doesn't appear to be an immediate advantage to do so.
3513 * SEE ALSO
3514 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3516 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3518 SIZE sz;
3519 static const WCHAR alphabet[] = {
3520 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3521 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3522 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3524 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3526 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3528 if (height) *height = sz.cy;
3529 return (sz.cx / 26 + 1) / 2;
3532 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3534 FIXME("(%d): stub\n", fEnableEUDC);
3535 return FALSE;
3538 /***********************************************************************
3539 * GetCharWidthI (GDI32.@)
3541 * Retrieve widths of characters.
3543 * PARAMS
3544 * hdc [I] Handle to a device context.
3545 * first [I] First glyph in range to query.
3546 * count [I] Number of glyph indices to query.
3547 * glyphs [I] Array of glyphs to query.
3548 * buffer [O] Buffer to receive character widths.
3550 * NOTES
3551 * Only works with TrueType fonts.
3553 * RETURNS
3554 * Success: TRUE
3555 * Failure: FALSE
3557 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3559 ABC *abc;
3560 unsigned int i;
3562 TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3564 if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3565 return FALSE;
3567 if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3569 HeapFree(GetProcessHeap(), 0, abc);
3570 return FALSE;
3573 for (i = 0; i < count; i++)
3574 buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3576 HeapFree(GetProcessHeap(), 0, abc);
3577 return TRUE;
3580 /***********************************************************************
3581 * GetFontUnicodeRanges (GDI32.@)
3583 * Retrieve a list of supported Unicode characters in a font.
3585 * PARAMS
3586 * hdc [I] Handle to a device context.
3587 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3589 * RETURNS
3590 * Success: Number of bytes written to the buffer pointed to by lpgs.
3591 * Failure: 0
3594 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3596 DWORD ret;
3597 PHYSDEV dev;
3598 DC *dc = get_dc_ptr(hdc);
3600 TRACE("(%p, %p)\n", hdc, lpgs);
3602 if (!dc) return 0;
3604 dev = GET_DC_PHYSDEV( dc, pGetFontUnicodeRanges );
3605 ret = dev->funcs->pGetFontUnicodeRanges( dev, lpgs );
3606 release_dc_ptr(dc);
3607 return ret;
3611 /*************************************************************
3612 * FontIsLinked (GDI32.@)
3614 BOOL WINAPI FontIsLinked(HDC hdc)
3616 DC *dc = get_dc_ptr(hdc);
3617 PHYSDEV dev;
3618 BOOL ret;
3620 if (!dc) return FALSE;
3621 dev = GET_DC_PHYSDEV( dc, pFontIsLinked );
3622 ret = dev->funcs->pFontIsLinked( dev );
3623 release_dc_ptr(dc);
3624 TRACE("returning %d\n", ret);
3625 return ret;
3628 /*************************************************************
3629 * GdiRealizationInfo (GDI32.@)
3631 * Returns a structure that contains some font information.
3633 BOOL WINAPI GdiRealizationInfo(HDC hdc, realization_info_t *info)
3635 DC *dc = get_dc_ptr(hdc);
3636 PHYSDEV dev;
3637 BOOL ret;
3639 if (!dc) return FALSE;
3640 dev = GET_DC_PHYSDEV( dc, pGdiRealizationInfo );
3641 ret = dev->funcs->pGdiRealizationInfo( dev, info );
3642 release_dc_ptr(dc);
3643 return ret;