windowscodecs: Add support for converting to 32bppPBGRA.
[wine.git] / dlls / gdi32 / font.c
blob93b425a92084560de6f35a8165efe702a17a0539
1 /*
2 * GDI font objects
4 * Copyright 1993 Alexandre Julliard
5 * 1997 Alex Korobka
6 * Copyright 2002,2003 Shachar Shemesh
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "config.h"
24 #include "wine/port.h"
26 #include <stdarg.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <assert.h>
30 #include "winerror.h"
31 #include "windef.h"
32 #include "winbase.h"
33 #include "winnls.h"
34 #include "gdi_private.h"
35 #include "wine/exception.h"
36 #include "wine/unicode.h"
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(font);
41 /* Device -> World size conversion */
43 /* Performs a device to world transformation on the specified width (which
44 * is in integer format).
46 static inline INT INTERNAL_XDSTOWS(DC *dc, INT width)
48 double floatWidth;
50 /* Perform operation with floating point */
51 floatWidth = (double)width * dc->xformVport2World.eM11;
52 /* Round to integers */
53 return GDI_ROUND(floatWidth);
56 /* Performs a device to world transformation on the specified size (which
57 * is in integer format).
59 static inline INT INTERNAL_YDSTOWS(DC *dc, INT height)
61 double floatHeight;
63 /* Perform operation with floating point */
64 floatHeight = (double)height * dc->xformVport2World.eM22;
65 /* Round to integers */
66 return GDI_ROUND(floatHeight);
69 static inline INT INTERNAL_XWSTODS(DC *dc, INT width)
71 POINT pt[2];
72 pt[0].x = pt[0].y = 0;
73 pt[1].x = width;
74 pt[1].y = 0;
75 LPtoDP(dc->hSelf, pt, 2);
76 return pt[1].x - pt[0].x;
79 static inline INT INTERNAL_YWSTODS(DC *dc, INT height)
81 POINT pt[2];
82 pt[0].x = pt[0].y = 0;
83 pt[1].x = 0;
84 pt[1].y = height;
85 LPtoDP(dc->hSelf, pt, 2);
86 return pt[1].y - pt[0].y;
89 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc );
90 static INT FONT_GetObjectA( HGDIOBJ handle, INT count, LPVOID buffer );
91 static INT FONT_GetObjectW( HGDIOBJ handle, INT count, LPVOID buffer );
92 static BOOL FONT_DeleteObject( HGDIOBJ handle );
94 static const struct gdi_obj_funcs font_funcs =
96 FONT_SelectObject, /* pSelectObject */
97 FONT_GetObjectA, /* pGetObjectA */
98 FONT_GetObjectW, /* pGetObjectW */
99 NULL, /* pUnrealizeObject */
100 FONT_DeleteObject /* pDeleteObject */
103 #define ENUM_UNICODE 0x00000001
104 #define ENUM_CALLED 0x00000002
106 typedef struct
108 GDIOBJHDR header;
109 LOGFONTW logfont;
110 } FONTOBJ;
112 typedef struct
114 LPLOGFONTW lpLogFontParam;
115 FONTENUMPROCW lpEnumFunc;
116 LPARAM lpData;
117 DWORD dwFlags;
118 HDC hdc;
119 } fontEnum32;
122 * For TranslateCharsetInfo
124 #define MAXTCIINDEX 32
125 static const CHARSETINFO FONT_tci[MAXTCIINDEX] = {
126 /* ANSI */
127 { ANSI_CHARSET, 1252, {{0,0,0,0},{FS_LATIN1,0}} },
128 { EASTEUROPE_CHARSET, 1250, {{0,0,0,0},{FS_LATIN2,0}} },
129 { RUSSIAN_CHARSET, 1251, {{0,0,0,0},{FS_CYRILLIC,0}} },
130 { GREEK_CHARSET, 1253, {{0,0,0,0},{FS_GREEK,0}} },
131 { TURKISH_CHARSET, 1254, {{0,0,0,0},{FS_TURKISH,0}} },
132 { HEBREW_CHARSET, 1255, {{0,0,0,0},{FS_HEBREW,0}} },
133 { ARABIC_CHARSET, 1256, {{0,0,0,0},{FS_ARABIC,0}} },
134 { BALTIC_CHARSET, 1257, {{0,0,0,0},{FS_BALTIC,0}} },
135 { VIETNAMESE_CHARSET, 1258, {{0,0,0,0},{FS_VIETNAMESE,0}} },
136 /* reserved by ANSI */
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 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
143 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
144 /* ANSI and OEM */
145 { THAI_CHARSET, 874, {{0,0,0,0},{FS_THAI,0}} },
146 { SHIFTJIS_CHARSET, 932, {{0,0,0,0},{FS_JISJAPAN,0}} },
147 { GB2312_CHARSET, 936, {{0,0,0,0},{FS_CHINESESIMP,0}} },
148 { HANGEUL_CHARSET, 949, {{0,0,0,0},{FS_WANSUNG,0}} },
149 { CHINESEBIG5_CHARSET, 950, {{0,0,0,0},{FS_CHINESETRAD,0}} },
150 { JOHAB_CHARSET, 1361, {{0,0,0,0},{FS_JOHAB,0}} },
151 /* reserved for alternate ANSI and OEM */
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 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
159 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
160 /* reserved for system */
161 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
162 { SYMBOL_CHARSET, CP_SYMBOL, {{0,0,0,0},{FS_SYMBOL,0}} }
165 static void FONT_LogFontAToW( const LOGFONTA *fontA, LPLOGFONTW fontW )
167 memcpy(fontW, fontA, sizeof(LOGFONTA) - LF_FACESIZE);
168 MultiByteToWideChar(CP_ACP, 0, fontA->lfFaceName, -1, fontW->lfFaceName,
169 LF_FACESIZE);
170 fontW->lfFaceName[LF_FACESIZE-1] = 0;
173 static void FONT_LogFontWToA( const LOGFONTW *fontW, LPLOGFONTA fontA )
175 memcpy(fontA, fontW, sizeof(LOGFONTA) - LF_FACESIZE);
176 WideCharToMultiByte(CP_ACP, 0, fontW->lfFaceName, -1, fontA->lfFaceName,
177 LF_FACESIZE, NULL, NULL);
178 fontA->lfFaceName[LF_FACESIZE-1] = 0;
181 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEXA fontA )
183 FONT_LogFontWToA( &fontW->elfLogFont, &fontA->elfLogFont );
185 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
186 (LPSTR) fontA->elfFullName, LF_FULLFACESIZE, NULL, NULL );
187 fontA->elfFullName[LF_FULLFACESIZE-1] = '\0';
188 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
189 (LPSTR) fontA->elfStyle, LF_FACESIZE, NULL, NULL );
190 fontA->elfStyle[LF_FACESIZE-1] = '\0';
191 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
192 (LPSTR) fontA->elfScript, LF_FACESIZE, NULL, NULL );
193 fontA->elfScript[LF_FACESIZE-1] = '\0';
196 static void FONT_EnumLogFontExAToW( const ENUMLOGFONTEXA *fontA, LPENUMLOGFONTEXW fontW )
198 FONT_LogFontAToW( &fontA->elfLogFont, &fontW->elfLogFont );
200 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfFullName, -1,
201 fontW->elfFullName, LF_FULLFACESIZE );
202 fontW->elfFullName[LF_FULLFACESIZE-1] = '\0';
203 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfStyle, -1,
204 fontW->elfStyle, LF_FACESIZE );
205 fontW->elfStyle[LF_FACESIZE-1] = '\0';
206 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfScript, -1,
207 fontW->elfScript, LF_FACESIZE );
208 fontW->elfScript[LF_FACESIZE-1] = '\0';
211 /***********************************************************************
212 * TEXTMETRIC conversion functions.
214 static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
216 ptmA->tmHeight = ptmW->tmHeight;
217 ptmA->tmAscent = ptmW->tmAscent;
218 ptmA->tmDescent = ptmW->tmDescent;
219 ptmA->tmInternalLeading = ptmW->tmInternalLeading;
220 ptmA->tmExternalLeading = ptmW->tmExternalLeading;
221 ptmA->tmAveCharWidth = ptmW->tmAveCharWidth;
222 ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth;
223 ptmA->tmWeight = ptmW->tmWeight;
224 ptmA->tmOverhang = ptmW->tmOverhang;
225 ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX;
226 ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
227 ptmA->tmFirstChar = min(ptmW->tmFirstChar, 255);
228 if (ptmW->tmCharSet == SYMBOL_CHARSET)
230 ptmA->tmFirstChar = 0x1e;
231 ptmA->tmLastChar = 0xff; /* win9x behaviour - we need the OS2 table data to calculate correctly */
233 else
235 ptmA->tmFirstChar = ptmW->tmDefaultChar - 1;
236 ptmA->tmLastChar = min(ptmW->tmLastChar, 0xff);
238 ptmA->tmDefaultChar = ptmW->tmDefaultChar;
239 ptmA->tmBreakChar = ptmW->tmBreakChar;
240 ptmA->tmItalic = ptmW->tmItalic;
241 ptmA->tmUnderlined = ptmW->tmUnderlined;
242 ptmA->tmStruckOut = ptmW->tmStruckOut;
243 ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
244 ptmA->tmCharSet = ptmW->tmCharSet;
248 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW *ptmW, NEWTEXTMETRICEXA *ptmA )
250 FONT_TextMetricWToA((const TEXTMETRICW *)ptmW, (LPTEXTMETRICA)ptmA);
251 ptmA->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
252 ptmA->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
253 ptmA->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
254 ptmA->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
255 memcpy(&ptmA->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
259 /***********************************************************************
260 * GdiGetCodePage (GDI32.@)
262 DWORD WINAPI GdiGetCodePage( HDC hdc )
264 UINT cp = CP_ACP;
265 DC *dc = get_dc_ptr( hdc );
267 if (dc)
269 cp = dc->font_code_page;
270 release_dc_ptr( dc );
272 return cp;
275 /***********************************************************************
276 * FONT_mbtowc
278 * Returns a Unicode translation of str using the charset of the
279 * currently selected font in hdc. If count is -1 then str is assumed
280 * to be '\0' terminated, otherwise it contains the number of bytes to
281 * convert. If plenW is non-NULL, on return it will point to the
282 * number of WCHARs that have been written. If pCP is non-NULL, on
283 * return it will point to the codepage used in the conversion. The
284 * caller should free the returned LPWSTR from the process heap
285 * itself.
287 static LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
289 UINT cp;
290 INT lenW;
291 LPWSTR strW;
293 cp = GdiGetCodePage( hdc );
295 if(count == -1) count = strlen(str);
296 lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
297 strW = HeapAlloc(GetProcessHeap(), 0, lenW*sizeof(WCHAR));
298 MultiByteToWideChar(cp, 0, str, count, strW, lenW);
299 TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW));
300 if(plenW) *plenW = lenW;
301 if(pCP) *pCP = cp;
302 return strW;
305 /***********************************************************************
306 * CreateFontIndirectExA (GDI32.@)
308 HFONT WINAPI CreateFontIndirectExA( const ENUMLOGFONTEXDVA *penumexA )
310 ENUMLOGFONTEXDVW enumexW;
312 if (!penumexA) return 0;
314 FONT_EnumLogFontExAToW( &penumexA->elfEnumLogfontEx, &enumexW.elfEnumLogfontEx );
315 enumexW.elfDesignVector = penumexA->elfDesignVector;
316 return CreateFontIndirectExW( &enumexW );
319 /***********************************************************************
320 * CreateFontIndirectExW (GDI32.@)
322 HFONT WINAPI CreateFontIndirectExW( const ENUMLOGFONTEXDVW *penumex )
324 HFONT hFont;
325 FONTOBJ *fontPtr;
326 const LOGFONTW *plf;
328 if (!penumex) return 0;
330 if (penumex->elfEnumLogfontEx.elfFullName[0] ||
331 penumex->elfEnumLogfontEx.elfStyle[0] ||
332 penumex->elfEnumLogfontEx.elfScript[0])
334 FIXME("some fields ignored. fullname=%s, style=%s, script=%s\n",
335 debugstr_w(penumex->elfEnumLogfontEx.elfFullName),
336 debugstr_w(penumex->elfEnumLogfontEx.elfStyle),
337 debugstr_w(penumex->elfEnumLogfontEx.elfScript));
340 plf = &penumex->elfEnumLogfontEx.elfLogFont;
341 if (!(fontPtr = HeapAlloc( GetProcessHeap(), 0, sizeof(*fontPtr) ))) return 0;
343 fontPtr->logfont = *plf;
345 if (plf->lfEscapement != plf->lfOrientation)
347 /* this should really depend on whether GM_ADVANCED is set */
348 fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
349 WARN("orientation angle %f set to "
350 "escapement angle %f for new font %p\n",
351 plf->lfOrientation/10., plf->lfEscapement/10., fontPtr);
354 if (!(hFont = alloc_gdi_handle( &fontPtr->header, OBJ_FONT, &font_funcs )))
356 HeapFree( GetProcessHeap(), 0, fontPtr );
357 return 0;
360 TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
361 plf->lfHeight, plf->lfWidth,
362 plf->lfEscapement, plf->lfOrientation,
363 plf->lfPitchAndFamily,
364 plf->lfOutPrecision, plf->lfClipPrecision,
365 plf->lfQuality, plf->lfCharSet,
366 debugstr_w(plf->lfFaceName),
367 plf->lfWeight > 400 ? "Bold" : "",
368 plf->lfItalic ? "Italic" : "",
369 plf->lfUnderline ? "Underline" : "", hFont);
371 return hFont;
374 /***********************************************************************
375 * CreateFontIndirectA (GDI32.@)
377 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *plfA )
379 LOGFONTW lfW;
381 if (!plfA) return 0;
383 FONT_LogFontAToW( plfA, &lfW );
384 return CreateFontIndirectW( &lfW );
387 /***********************************************************************
388 * CreateFontIndirectW (GDI32.@)
390 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
392 ENUMLOGFONTEXDVW exdv;
394 if (!plf) return 0;
396 exdv.elfEnumLogfontEx.elfLogFont = *plf;
397 exdv.elfEnumLogfontEx.elfFullName[0] = 0;
398 exdv.elfEnumLogfontEx.elfStyle[0] = 0;
399 exdv.elfEnumLogfontEx.elfScript[0] = 0;
400 return CreateFontIndirectExW( &exdv );
403 /*************************************************************************
404 * CreateFontA (GDI32.@)
406 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
407 INT orient, INT weight, DWORD italic,
408 DWORD underline, DWORD strikeout, DWORD charset,
409 DWORD outpres, DWORD clippres, DWORD quality,
410 DWORD pitch, LPCSTR name )
412 LOGFONTA logfont;
414 logfont.lfHeight = height;
415 logfont.lfWidth = width;
416 logfont.lfEscapement = esc;
417 logfont.lfOrientation = orient;
418 logfont.lfWeight = weight;
419 logfont.lfItalic = italic;
420 logfont.lfUnderline = underline;
421 logfont.lfStrikeOut = strikeout;
422 logfont.lfCharSet = charset;
423 logfont.lfOutPrecision = outpres;
424 logfont.lfClipPrecision = clippres;
425 logfont.lfQuality = quality;
426 logfont.lfPitchAndFamily = pitch;
428 if (name)
429 lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
430 else
431 logfont.lfFaceName[0] = '\0';
433 return CreateFontIndirectA( &logfont );
436 /*************************************************************************
437 * CreateFontW (GDI32.@)
439 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
440 INT orient, INT weight, DWORD italic,
441 DWORD underline, DWORD strikeout, DWORD charset,
442 DWORD outpres, DWORD clippres, DWORD quality,
443 DWORD pitch, LPCWSTR name )
445 LOGFONTW logfont;
447 logfont.lfHeight = height;
448 logfont.lfWidth = width;
449 logfont.lfEscapement = esc;
450 logfont.lfOrientation = orient;
451 logfont.lfWeight = weight;
452 logfont.lfItalic = italic;
453 logfont.lfUnderline = underline;
454 logfont.lfStrikeOut = strikeout;
455 logfont.lfCharSet = charset;
456 logfont.lfOutPrecision = outpres;
457 logfont.lfClipPrecision = clippres;
458 logfont.lfQuality = quality;
459 logfont.lfPitchAndFamily = pitch;
461 if (name)
462 lstrcpynW(logfont.lfFaceName, name,
463 sizeof(logfont.lfFaceName) / sizeof(WCHAR));
464 else
465 logfont.lfFaceName[0] = '\0';
467 return CreateFontIndirectW( &logfont );
470 static void update_font_code_page( DC *dc )
472 CHARSETINFO csi;
473 int charset = DEFAULT_CHARSET;
475 if (dc->gdiFont)
476 charset = WineEngGetTextCharsetInfo( dc->gdiFont, NULL, 0 );
478 /* Hmm, nicely designed api this one! */
479 if (TranslateCharsetInfo( ULongToPtr(charset), &csi, TCI_SRCCHARSET) )
480 dc->font_code_page = csi.ciACP;
481 else {
482 switch(charset) {
483 case OEM_CHARSET:
484 dc->font_code_page = GetOEMCP();
485 break;
486 case DEFAULT_CHARSET:
487 dc->font_code_page = GetACP();
488 break;
490 case VISCII_CHARSET:
491 case TCVN_CHARSET:
492 case KOI8_CHARSET:
493 case ISO3_CHARSET:
494 case ISO4_CHARSET:
495 case ISO10_CHARSET:
496 case CELTIC_CHARSET:
497 /* FIXME: These have no place here, but because x11drv
498 enumerates fonts with these (made up) charsets some apps
499 might use them and then the FIXME below would become
500 annoying. Now we could pick the intended codepage for
501 each of these, but since it's broken anyway we'll just
502 use CP_ACP and hope it'll go away...
504 dc->font_code_page = CP_ACP;
505 break;
507 default:
508 FIXME("Can't find codepage for charset %d\n", charset);
509 dc->font_code_page = CP_ACP;
510 break;
514 TRACE("charset %d => cp %d\n", charset, dc->font_code_page);
517 /***********************************************************************
518 * FONT_SelectObject
520 * If the driver supports vector fonts we create a gdi font first and
521 * then call the driver to give it a chance to supply its own device
522 * font. If the driver wants to do this it returns TRUE and we can
523 * delete the gdi font, if the driver wants to use the gdi font it
524 * should return FALSE, to signal an error return GDI_ERROR. For
525 * drivers that don't support vector fonts they must supply their own
526 * font.
528 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc )
530 HGDIOBJ ret = 0;
531 DC *dc = get_dc_ptr( hdc );
532 PHYSDEV physdev;
534 if (!dc) return 0;
536 if (!GDI_inc_ref_count( handle ))
538 release_dc_ptr( dc );
539 return 0;
542 if (GetDeviceCaps( dc->hSelf, TEXTCAPS ) & TC_VA_ABLE)
543 dc->gdiFont = WineEngCreateFontInstance( dc, handle );
545 physdev = GET_DC_PHYSDEV( dc, pSelectFont );
546 ret = physdev->funcs->pSelectFont( physdev, handle, dc->gdiFont );
548 if (ret && dc->gdiFont) dc->gdiFont = 0;
550 if (ret == HGDI_ERROR)
552 GDI_dec_ref_count( handle );
553 ret = 0; /* SelectObject returns 0 on error */
555 else
557 ret = dc->hFont;
558 dc->hFont = handle;
559 update_font_code_page( dc );
560 GDI_dec_ref_count( ret );
562 release_dc_ptr( dc );
563 return ret;
567 /***********************************************************************
568 * FONT_GetObjectA
570 static INT FONT_GetObjectA( HGDIOBJ handle, INT count, LPVOID buffer )
572 FONTOBJ *font = GDI_GetObjPtr( handle, OBJ_FONT );
573 LOGFONTA lfA;
575 if (!font) return 0;
576 if (buffer)
578 FONT_LogFontWToA( &font->logfont, &lfA );
579 if (count > sizeof(lfA)) count = sizeof(lfA);
580 memcpy( buffer, &lfA, count );
582 else count = sizeof(lfA);
583 GDI_ReleaseObj( handle );
584 return count;
587 /***********************************************************************
588 * FONT_GetObjectW
590 static INT FONT_GetObjectW( HGDIOBJ handle, INT count, LPVOID buffer )
592 FONTOBJ *font = GDI_GetObjPtr( handle, OBJ_FONT );
594 if (!font) return 0;
595 if (buffer)
597 if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
598 memcpy( buffer, &font->logfont, count );
600 else count = sizeof(LOGFONTW);
601 GDI_ReleaseObj( handle );
602 return count;
606 /***********************************************************************
607 * FONT_DeleteObject
609 static BOOL FONT_DeleteObject( HGDIOBJ handle )
611 FONTOBJ *obj;
613 WineEngDestroyFontInstance( handle );
615 if (!(obj = free_gdi_handle( handle ))) return FALSE;
616 return HeapFree( GetProcessHeap(), 0, obj );
620 /***********************************************************************
621 * FONT_EnumInstance
623 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
624 * We have to use other types because of the FONTENUMPROCW definition.
626 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
627 DWORD fType, LPARAM lp )
629 fontEnum32 *pfe = (fontEnum32*)lp;
630 INT ret = 1;
632 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
633 if ((!pfe->lpLogFontParam ||
634 pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
635 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
636 (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
638 /* convert font metrics */
639 ENUMLOGFONTEXA logfont;
640 NEWTEXTMETRICEXA tmA;
642 pfe->dwFlags |= ENUM_CALLED;
643 if (!(pfe->dwFlags & ENUM_UNICODE))
645 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
646 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
647 plf = (LOGFONTW *)&logfont.elfLogFont;
648 ptm = (TEXTMETRICW *)&tmA;
651 ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
653 return ret;
656 /***********************************************************************
657 * FONT_EnumFontFamiliesEx
659 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf,
660 FONTENUMPROCW efproc,
661 LPARAM lParam, DWORD dwUnicode)
663 INT ret = 1, ret2;
664 DC *dc = get_dc_ptr( hDC );
665 fontEnum32 fe32;
666 BOOL enum_gdi_fonts;
668 if (!dc) return 0;
670 if (plf)
671 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName),
672 plf->lfCharSet);
673 fe32.lpLogFontParam = plf;
674 fe32.lpEnumFunc = efproc;
675 fe32.lpData = lParam;
676 fe32.dwFlags = dwUnicode;
677 fe32.hdc = hDC;
679 enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE;
681 if (enum_gdi_fonts)
682 ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
683 fe32.dwFlags &= ~ENUM_CALLED;
684 if (ret)
686 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pEnumDeviceFonts );
687 ret2 = physdev->funcs->pEnumDeviceFonts( physdev, plf, FONT_EnumInstance, (LPARAM)&fe32 );
688 if(fe32.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
689 ret = ret2;
691 release_dc_ptr( dc );
692 return ret;
695 /***********************************************************************
696 * EnumFontFamiliesExW (GDI32.@)
698 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
699 FONTENUMPROCW efproc,
700 LPARAM lParam, DWORD dwFlags )
702 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, ENUM_UNICODE );
705 /***********************************************************************
706 * EnumFontFamiliesExA (GDI32.@)
708 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
709 FONTENUMPROCA efproc,
710 LPARAM lParam, DWORD dwFlags)
712 LOGFONTW lfW, *plfW;
714 if (plf)
716 FONT_LogFontAToW( plf, &lfW );
717 plfW = &lfW;
719 else plfW = NULL;
721 return FONT_EnumFontFamiliesEx( hDC, plfW, (FONTENUMPROCW)efproc, lParam, 0);
724 /***********************************************************************
725 * EnumFontFamiliesA (GDI32.@)
727 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
728 FONTENUMPROCA efproc, LPARAM lpData )
730 LOGFONTA lf, *plf;
732 if (lpFamily)
734 if (!*lpFamily) return 1;
735 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
736 lf.lfCharSet = DEFAULT_CHARSET;
737 lf.lfPitchAndFamily = 0;
738 plf = &lf;
740 else plf = NULL;
742 return EnumFontFamiliesExA( hDC, plf, efproc, lpData, 0 );
745 /***********************************************************************
746 * EnumFontFamiliesW (GDI32.@)
748 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
749 FONTENUMPROCW efproc, LPARAM lpData )
751 LOGFONTW lf, *plf;
753 if (lpFamily)
755 if (!*lpFamily) return 1;
756 lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
757 lf.lfCharSet = DEFAULT_CHARSET;
758 lf.lfPitchAndFamily = 0;
759 plf = &lf;
761 else plf = NULL;
763 return EnumFontFamiliesExW( hDC, plf, efproc, lpData, 0 );
766 /***********************************************************************
767 * EnumFontsA (GDI32.@)
769 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
770 LPARAM lpData )
772 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
775 /***********************************************************************
776 * EnumFontsW (GDI32.@)
778 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
779 LPARAM lpData )
781 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
785 /***********************************************************************
786 * GetTextCharacterExtra (GDI32.@)
788 INT WINAPI GetTextCharacterExtra( HDC hdc )
790 INT ret;
791 DC *dc = get_dc_ptr( hdc );
792 if (!dc) return 0x80000000;
793 ret = dc->charExtra;
794 release_dc_ptr( dc );
795 return ret;
799 /***********************************************************************
800 * SetTextCharacterExtra (GDI32.@)
802 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
804 INT ret = 0x80000000;
805 DC * dc = get_dc_ptr( hdc );
807 if (dc)
809 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetTextCharacterExtra );
810 extra = physdev->funcs->pSetTextCharacterExtra( physdev, extra );
811 if (extra != 0x80000000)
813 ret = dc->charExtra;
814 dc->charExtra = extra;
816 release_dc_ptr( dc );
818 return ret;
822 /***********************************************************************
823 * SetTextJustification (GDI32.@)
825 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
827 BOOL ret;
828 PHYSDEV physdev;
829 DC * dc = get_dc_ptr( hdc );
831 if (!dc) return FALSE;
833 physdev = GET_DC_PHYSDEV( dc, pSetTextJustification );
834 ret = physdev->funcs->pSetTextJustification( physdev, extra, breaks );
835 if (ret)
837 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
838 if (!extra) breaks = 0;
839 if (breaks)
841 dc->breakExtra = extra / breaks;
842 dc->breakRem = extra - (breaks * dc->breakExtra);
844 else
846 dc->breakExtra = 0;
847 dc->breakRem = 0;
850 release_dc_ptr( dc );
851 return ret;
855 /***********************************************************************
856 * GetTextFaceA (GDI32.@)
858 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
860 INT res = GetTextFaceW(hdc, 0, NULL);
861 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
862 GetTextFaceW( hdc, res, nameW );
864 if (name)
866 if (count)
868 res = WideCharToMultiByte(CP_ACP, 0, nameW, -1, name, count, NULL, NULL);
869 if (res == 0)
870 res = count;
871 name[count-1] = 0;
872 /* GetTextFaceA does NOT include the nul byte in the return count. */
873 res--;
875 else
876 res = 0;
878 else
879 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
880 HeapFree( GetProcessHeap(), 0, nameW );
881 return res;
884 /***********************************************************************
885 * GetTextFaceW (GDI32.@)
887 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
889 FONTOBJ *font;
890 INT ret = 0;
892 DC * dc = get_dc_ptr( hdc );
893 if (!dc) return 0;
895 if(dc->gdiFont)
896 ret = WineEngGetTextFace(dc->gdiFont, count, name);
897 else if ((font = GDI_GetObjPtr( dc->hFont, OBJ_FONT )))
899 INT n = strlenW(font->logfont.lfFaceName) + 1;
900 if (name)
902 lstrcpynW( name, font->logfont.lfFaceName, count );
903 ret = min(count, n);
905 else ret = n;
906 GDI_ReleaseObj( dc->hFont );
908 release_dc_ptr( dc );
909 return ret;
913 /***********************************************************************
914 * GetTextExtentPoint32A (GDI32.@)
916 * See GetTextExtentPoint32W.
918 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
919 LPSIZE size )
921 BOOL ret = FALSE;
922 INT wlen;
923 LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
925 if (p) {
926 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
927 HeapFree( GetProcessHeap(), 0, p );
930 TRACE("(%p %s %d %p): returning %d x %d\n",
931 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
932 return ret;
936 /***********************************************************************
937 * GetTextExtentPoint32W [GDI32.@]
939 * Computes width/height for a string.
941 * Computes width and height of the specified string.
943 * RETURNS
944 * Success: TRUE
945 * Failure: FALSE
947 BOOL WINAPI GetTextExtentPoint32W(
948 HDC hdc, /* [in] Handle of device context */
949 LPCWSTR str, /* [in] Address of text string */
950 INT count, /* [in] Number of characters in string */
951 LPSIZE size) /* [out] Address of structure for string size */
953 return GetTextExtentExPointW(hdc, str, count, 0, NULL, NULL, size);
956 /***********************************************************************
957 * GetTextExtentExPointI [GDI32.@]
959 * Computes width and height of the array of glyph indices.
961 * PARAMS
962 * hdc [I] Handle of device context.
963 * indices [I] Glyph index array.
964 * count [I] Number of glyphs in array.
965 * max_ext [I] Maximum width in glyphs.
966 * nfit [O] Maximum number of characters.
967 * dxs [O] Partial string widths.
968 * size [O] Returned string size.
970 * RETURNS
971 * Success: TRUE
972 * Failure: FALSE
974 BOOL WINAPI GetTextExtentExPointI( HDC hdc, const WORD *indices, INT count, INT max_ext,
975 LPINT nfit, LPINT dxs, LPSIZE size )
977 BOOL ret = FALSE;
978 DC * dc = get_dc_ptr( hdc );
979 if (!dc) return FALSE;
981 if(dc->gdiFont) {
982 ret = WineEngGetTextExtentExPointI(dc->gdiFont, indices, count, max_ext, nfit, dxs, size);
983 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
984 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
985 size->cx += count * dc->charExtra;
987 else
989 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pGetTextExtentExPoint );
990 FIXME("calling GetTextExtentExPoint\n");
991 ret = physdev->funcs->pGetTextExtentExPoint( physdev, indices, count, max_ext, nfit, dxs, size );
994 release_dc_ptr( dc );
996 TRACE("(%p %p %d %p): returning %d x %d\n",
997 hdc, indices, count, size, size->cx, size->cy );
998 return ret;
1001 /***********************************************************************
1002 * GetTextExtentPointI [GDI32.@]
1004 * Computes width and height of the array of glyph indices.
1006 * PARAMS
1007 * hdc [I] Handle of device context.
1008 * indices [I] Glyph index array.
1009 * count [I] Number of glyphs in array.
1010 * size [O] Returned string size.
1012 * RETURNS
1013 * Success: TRUE
1014 * Failure: FALSE
1016 BOOL WINAPI GetTextExtentPointI( HDC hdc, const WORD *indices, INT count, LPSIZE size )
1018 return GetTextExtentExPointI( hdc, indices, count, 0, NULL, NULL, size );
1022 /***********************************************************************
1023 * GetTextExtentPointA (GDI32.@)
1025 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
1026 LPSIZE size )
1028 TRACE("not bug compatible.\n");
1029 return GetTextExtentPoint32A( hdc, str, count, size );
1032 /***********************************************************************
1033 * GetTextExtentPointW (GDI32.@)
1035 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1036 LPSIZE size )
1038 TRACE("not bug compatible.\n");
1039 return GetTextExtentPoint32W( hdc, str, count, size );
1043 /***********************************************************************
1044 * GetTextExtentExPointA (GDI32.@)
1046 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1047 INT maxExt, LPINT lpnFit,
1048 LPINT alpDx, LPSIZE size )
1050 BOOL ret;
1051 INT wlen;
1052 INT *walpDx = NULL;
1053 LPWSTR p = NULL;
1055 if (alpDx &&
1056 NULL == (walpDx = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT))))
1057 return FALSE;
1059 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1060 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
1061 if (walpDx)
1063 INT n = lpnFit ? *lpnFit : wlen;
1064 INT i, j;
1065 for(i = 0, j = 0; i < n; i++, j++)
1067 alpDx[j] = walpDx[i];
1068 if (IsDBCSLeadByte(str[j])) alpDx[++j] = walpDx[i];
1071 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1072 HeapFree( GetProcessHeap(), 0, p );
1073 HeapFree( GetProcessHeap(), 0, walpDx );
1074 return ret;
1078 /***********************************************************************
1079 * GetTextExtentExPointW (GDI32.@)
1081 * Return the size of the string as it would be if it was output properly by
1082 * e.g. TextOut.
1084 * This should include
1085 * - Intercharacter spacing
1086 * - justification spacing (not yet done)
1087 * - kerning? see below
1089 * Kerning. Since kerning would be carried out by the rendering code it should
1090 * be done by the driver. However they don't support it yet. Also I am not
1091 * yet persuaded that (certainly under Win95) any kerning is actually done.
1093 * str: According to MSDN this should be null-terminated. That is not true; a
1094 * null will not terminate it early.
1095 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1096 * than count. I have seen it be either the size of the full string or
1097 * 1 less than the size of the full string. I have not seen it bear any
1098 * resemblance to the portion that would fit.
1099 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1100 * trailing intercharacter spacing and any trailing justification.
1102 * FIXME
1103 * Currently we do this by measuring each character etc. We should do it by
1104 * passing the request to the driver, perhaps by extending the
1105 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1106 * thinking about kerning issues and rounding issues in the justification.
1109 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1110 INT maxExt, LPINT lpnFit,
1111 LPINT alpDx, LPSIZE size )
1113 INT nFit = 0;
1114 LPINT dxs = NULL;
1115 DC *dc;
1116 BOOL ret = FALSE;
1117 TEXTMETRICW tm;
1119 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1121 dc = get_dc_ptr(hdc);
1122 if (! dc)
1123 return FALSE;
1125 GetTextMetricsW(hdc, &tm);
1127 /* If we need to calculate nFit, then we need the partial extents even if
1128 the user hasn't provided us with an array. */
1129 if (lpnFit)
1131 dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]);
1132 if (! dxs)
1134 release_dc_ptr(dc);
1135 SetLastError(ERROR_OUTOFMEMORY);
1136 return FALSE;
1139 else
1140 dxs = alpDx;
1142 if (dc->gdiFont)
1143 ret = WineEngGetTextExtentExPoint(dc->gdiFont, str, count,
1144 0, NULL, dxs, size);
1145 else
1147 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pGetTextExtentExPoint );
1148 ret = physdev->funcs->pGetTextExtentExPoint(physdev, str, count, 0, NULL, dxs, size);
1151 /* Perform device size to world size transformations. */
1152 if (ret)
1154 INT extra = dc->charExtra,
1155 breakExtra = dc->breakExtra,
1156 breakRem = dc->breakRem,
1159 if (dxs)
1161 for (i = 0; i < count; ++i)
1163 dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
1164 dxs[i] += (i+1) * extra;
1165 if (count > 1 && (breakExtra || breakRem) && str[i] == tm.tmBreakChar)
1167 dxs[i] += breakExtra;
1168 if (breakRem > 0)
1170 breakRem--;
1171 dxs[i]++;
1174 if (dxs[i] <= maxExt)
1175 ++nFit;
1177 breakRem = dc->breakRem;
1179 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1180 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1182 if (!dxs && count > 1 && (breakExtra || breakRem))
1184 for (i = 0; i < count; i++)
1186 if (str[i] == tm.tmBreakChar)
1188 size->cx += breakExtra;
1189 if (breakRem > 0)
1191 breakRem--;
1192 (size->cx)++;
1199 if (lpnFit)
1200 *lpnFit = nFit;
1202 if (! alpDx)
1203 HeapFree(GetProcessHeap(), 0, dxs);
1205 release_dc_ptr( dc );
1207 TRACE("returning %d %d x %d\n",nFit,size->cx,size->cy);
1208 return ret;
1211 /***********************************************************************
1212 * GetTextMetricsA (GDI32.@)
1214 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1216 TEXTMETRICW tm32;
1218 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1219 FONT_TextMetricWToA( &tm32, metrics );
1220 return TRUE;
1223 /***********************************************************************
1224 * GetTextMetricsW (GDI32.@)
1226 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1228 BOOL ret = FALSE;
1229 DC * dc = get_dc_ptr( hdc );
1230 if (!dc) return FALSE;
1232 if (dc->gdiFont)
1233 ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1234 else
1236 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pGetTextMetrics );
1237 ret = physdev->funcs->pGetTextMetrics( physdev, metrics );
1240 if (ret)
1242 /* device layer returns values in device units
1243 * therefore we have to convert them to logical */
1245 metrics->tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1246 metrics->tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1248 #define WDPTOLP(x) ((x<0)? \
1249 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1250 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1251 #define HDPTOLP(y) ((y<0)? \
1252 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1253 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1255 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1256 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1257 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1258 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1259 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1260 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1261 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1262 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1263 ret = TRUE;
1264 #undef WDPTOLP
1265 #undef HDPTOLP
1266 TRACE("text metrics:\n"
1267 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1268 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1269 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1270 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1271 " PitchAndFamily = %02x\n"
1272 " --------------------\n"
1273 " InternalLeading = %i\n"
1274 " Ascent = %i\n"
1275 " Descent = %i\n"
1276 " Height = %i\n",
1277 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1278 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1279 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1280 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1281 metrics->tmPitchAndFamily,
1282 metrics->tmInternalLeading,
1283 metrics->tmAscent,
1284 metrics->tmDescent,
1285 metrics->tmHeight );
1287 release_dc_ptr( dc );
1288 return ret;
1292 /***********************************************************************
1293 * GetOutlineTextMetricsA (GDI32.@)
1294 * Gets metrics for TrueType fonts.
1296 * NOTES
1297 * If the supplied buffer isn't big enough Windows partially fills it up to
1298 * its given length and returns that length.
1300 * RETURNS
1301 * Success: Non-zero or size of required buffer
1302 * Failure: 0
1304 UINT WINAPI GetOutlineTextMetricsA(
1305 HDC hdc, /* [in] Handle of device context */
1306 UINT cbData, /* [in] Size of metric data array */
1307 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1309 char buf[512], *ptr;
1310 UINT ret, needed;
1311 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1312 OUTLINETEXTMETRICA *output = lpOTM;
1313 INT left, len;
1315 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1316 return 0;
1317 if(ret > sizeof(buf))
1318 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1319 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1321 needed = sizeof(OUTLINETEXTMETRICA);
1322 if(lpOTMW->otmpFamilyName)
1323 needed += WideCharToMultiByte(CP_ACP, 0,
1324 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1325 NULL, 0, NULL, NULL);
1326 if(lpOTMW->otmpFaceName)
1327 needed += WideCharToMultiByte(CP_ACP, 0,
1328 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1329 NULL, 0, NULL, NULL);
1330 if(lpOTMW->otmpStyleName)
1331 needed += WideCharToMultiByte(CP_ACP, 0,
1332 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1333 NULL, 0, NULL, NULL);
1334 if(lpOTMW->otmpFullName)
1335 needed += WideCharToMultiByte(CP_ACP, 0,
1336 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1337 NULL, 0, NULL, NULL);
1339 if(!lpOTM) {
1340 ret = needed;
1341 goto end;
1344 TRACE("needed = %d\n", needed);
1345 if(needed > cbData)
1346 /* Since the supplied buffer isn't big enough, we'll alloc one
1347 that is and memcpy the first cbData bytes into the lpOTM at
1348 the end. */
1349 output = HeapAlloc(GetProcessHeap(), 0, needed);
1351 ret = output->otmSize = min(needed, cbData);
1352 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1353 output->otmFiller = 0;
1354 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1355 output->otmfsSelection = lpOTMW->otmfsSelection;
1356 output->otmfsType = lpOTMW->otmfsType;
1357 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1358 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1359 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1360 output->otmEMSquare = lpOTMW->otmEMSquare;
1361 output->otmAscent = lpOTMW->otmAscent;
1362 output->otmDescent = lpOTMW->otmDescent;
1363 output->otmLineGap = lpOTMW->otmLineGap;
1364 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1365 output->otmsXHeight = lpOTMW->otmsXHeight;
1366 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1367 output->otmMacAscent = lpOTMW->otmMacAscent;
1368 output->otmMacDescent = lpOTMW->otmMacDescent;
1369 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1370 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1371 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1372 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1373 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1374 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1375 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1376 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1377 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1378 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1381 ptr = (char*)(output + 1);
1382 left = needed - sizeof(*output);
1384 if(lpOTMW->otmpFamilyName) {
1385 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1386 len = WideCharToMultiByte(CP_ACP, 0,
1387 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1388 ptr, left, NULL, NULL);
1389 left -= len;
1390 ptr += len;
1391 } else
1392 output->otmpFamilyName = 0;
1394 if(lpOTMW->otmpFaceName) {
1395 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1396 len = WideCharToMultiByte(CP_ACP, 0,
1397 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1398 ptr, left, NULL, NULL);
1399 left -= len;
1400 ptr += len;
1401 } else
1402 output->otmpFaceName = 0;
1404 if(lpOTMW->otmpStyleName) {
1405 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1406 len = WideCharToMultiByte(CP_ACP, 0,
1407 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1408 ptr, left, NULL, NULL);
1409 left -= len;
1410 ptr += len;
1411 } else
1412 output->otmpStyleName = 0;
1414 if(lpOTMW->otmpFullName) {
1415 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1416 len = WideCharToMultiByte(CP_ACP, 0,
1417 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1418 ptr, left, NULL, NULL);
1419 left -= len;
1420 } else
1421 output->otmpFullName = 0;
1423 assert(left == 0);
1425 if(output != lpOTM) {
1426 memcpy(lpOTM, output, cbData);
1427 HeapFree(GetProcessHeap(), 0, output);
1429 /* check if the string offsets really fit into the provided size */
1430 /* FIXME: should we check string length as well? */
1431 /* make sure that we don't read/write beyond the provided buffer */
1432 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(LPSTR))
1434 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1435 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1438 /* make sure that we don't read/write beyond the provided buffer */
1439 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(LPSTR))
1441 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1442 lpOTM->otmpFaceName = 0; /* doesn't fit */
1445 /* make sure that we don't read/write beyond the provided buffer */
1446 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(LPSTR))
1448 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1449 lpOTM->otmpStyleName = 0; /* doesn't fit */
1452 /* make sure that we don't read/write beyond the provided buffer */
1453 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(LPSTR))
1455 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1456 lpOTM->otmpFullName = 0; /* doesn't fit */
1460 end:
1461 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1462 HeapFree(GetProcessHeap(), 0, lpOTMW);
1464 return ret;
1468 /***********************************************************************
1469 * GetOutlineTextMetricsW [GDI32.@]
1471 UINT WINAPI GetOutlineTextMetricsW(
1472 HDC hdc, /* [in] Handle of device context */
1473 UINT cbData, /* [in] Size of metric data array */
1474 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1476 DC *dc = get_dc_ptr( hdc );
1477 OUTLINETEXTMETRICW *output = lpOTM;
1478 UINT ret;
1480 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1481 if(!dc) return 0;
1483 if(dc->gdiFont) {
1484 ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, output);
1485 if(lpOTM && ret) {
1486 if(ret > cbData) {
1487 output = HeapAlloc(GetProcessHeap(), 0, ret);
1488 WineEngGetOutlineTextMetrics(dc->gdiFont, ret, output);
1491 output->otmTextMetrics.tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1492 output->otmTextMetrics.tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1494 #define WDPTOLP(x) ((x<0)? \
1495 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1496 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1497 #define HDPTOLP(y) ((y<0)? \
1498 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1499 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1501 output->otmTextMetrics.tmHeight = HDPTOLP(output->otmTextMetrics.tmHeight);
1502 output->otmTextMetrics.tmAscent = HDPTOLP(output->otmTextMetrics.tmAscent);
1503 output->otmTextMetrics.tmDescent = HDPTOLP(output->otmTextMetrics.tmDescent);
1504 output->otmTextMetrics.tmInternalLeading = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1505 output->otmTextMetrics.tmExternalLeading = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1506 output->otmTextMetrics.tmAveCharWidth = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1507 output->otmTextMetrics.tmMaxCharWidth = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1508 output->otmTextMetrics.tmOverhang = WDPTOLP(output->otmTextMetrics.tmOverhang);
1509 output->otmAscent = HDPTOLP(output->otmAscent);
1510 output->otmDescent = HDPTOLP(output->otmDescent);
1511 output->otmLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmLineGap));
1512 output->otmsCapEmHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsCapEmHeight));
1513 output->otmsXHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsXHeight));
1514 output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1515 output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1516 output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1517 output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1518 output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1519 output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1520 output->otmMacLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmMacLineGap));
1521 output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1522 output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1523 output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1524 output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1525 output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1526 output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1527 output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1528 output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1529 output->otmsStrikeoutSize = abs(INTERNAL_YDSTOWS(dc,output->otmsStrikeoutSize));
1530 output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1531 output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1532 output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1533 #undef WDPTOLP
1534 #undef HDPTOLP
1535 if(output != lpOTM) {
1536 memcpy(lpOTM, output, cbData);
1537 HeapFree(GetProcessHeap(), 0, output);
1538 ret = cbData;
1543 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1544 but really this should just be a return 0. */
1546 ret = sizeof(*lpOTM);
1547 if (lpOTM) {
1548 if(cbData < ret)
1549 ret = 0;
1550 else {
1551 memset(lpOTM, 0, ret);
1552 lpOTM->otmSize = sizeof(*lpOTM);
1553 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1555 Further fill of the structure not implemented,
1556 Needs real values for the structure members
1561 release_dc_ptr(dc);
1562 return ret;
1565 static LPSTR FONT_GetCharsByRangeA(HDC hdc, UINT firstChar, UINT lastChar, PINT pByteLen)
1567 INT i, count = lastChar - firstChar + 1;
1568 UINT c;
1569 LPSTR str;
1571 if (count <= 0)
1572 return NULL;
1574 switch (GdiGetCodePage(hdc))
1576 case 932:
1577 case 936:
1578 case 949:
1579 case 950:
1580 case 1361:
1581 if (lastChar > 0xffff)
1582 return NULL;
1583 if ((firstChar ^ lastChar) > 0xff)
1584 return NULL;
1585 break;
1586 default:
1587 if (lastChar > 0xff)
1588 return NULL;
1589 break;
1592 str = HeapAlloc(GetProcessHeap(), 0, count * 2 + 1);
1593 if (str == NULL)
1594 return NULL;
1596 for(i = 0, c = firstChar; c <= lastChar; i++, c++)
1598 if (c > 0xff)
1599 str[i++] = (BYTE)(c >> 8);
1600 str[i] = (BYTE)c;
1602 str[i] = '\0';
1604 *pByteLen = i;
1606 return str;
1609 /***********************************************************************
1610 * GetCharWidthW (GDI32.@)
1611 * GetCharWidth32W (GDI32.@)
1613 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1614 LPINT buffer )
1616 UINT i;
1617 BOOL ret;
1618 DC * dc = get_dc_ptr( hdc );
1619 if (!dc) return FALSE;
1621 if (dc->gdiFont)
1622 ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1623 else
1625 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pGetCharWidth );
1626 ret = physdev->funcs->pGetCharWidth( physdev, firstChar, lastChar, buffer);
1629 if (ret)
1631 /* convert device units to logical */
1632 for( i = firstChar; i <= lastChar; i++, buffer++ )
1633 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1634 ret = TRUE;
1636 release_dc_ptr( dc );
1637 return ret;
1641 /***********************************************************************
1642 * GetCharWidthA (GDI32.@)
1643 * GetCharWidth32A (GDI32.@)
1645 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1646 LPINT buffer )
1648 INT i, wlen;
1649 LPSTR str;
1650 LPWSTR wstr;
1651 BOOL ret = TRUE;
1653 str = FONT_GetCharsByRangeA(hdc, firstChar, lastChar, &i);
1654 if(str == NULL)
1655 return FALSE;
1657 wstr = FONT_mbtowc(hdc, str, i, &wlen, NULL);
1659 for(i = 0; i < wlen; i++)
1661 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1663 ret = FALSE;
1664 break;
1666 buffer++;
1669 HeapFree(GetProcessHeap(), 0, str);
1670 HeapFree(GetProcessHeap(), 0, wstr);
1672 return ret;
1676 /***********************************************************************
1677 * ExtTextOutA (GDI32.@)
1679 * See ExtTextOutW.
1681 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1682 const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1684 INT wlen;
1685 UINT codepage;
1686 LPWSTR p;
1687 BOOL ret;
1688 LPINT lpDxW = NULL;
1690 if (flags & ETO_GLYPH_INDEX)
1691 return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
1693 p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
1695 if (lpDx) {
1696 unsigned int i = 0, j = 0;
1698 /* allocate enough for a ETO_PDY */
1699 lpDxW = HeapAlloc( GetProcessHeap(), 0, 2*wlen*sizeof(INT));
1700 while(i < count) {
1701 if(IsDBCSLeadByteEx(codepage, str[i]))
1703 if(flags & ETO_PDY)
1705 lpDxW[j++] = lpDx[i * 2] + lpDx[(i + 1) * 2];
1706 lpDxW[j++] = lpDx[i * 2 + 1] + lpDx[(i + 1) * 2 + 1];
1708 else
1709 lpDxW[j++] = lpDx[i] + lpDx[i + 1];
1710 i = i + 2;
1712 else
1714 if(flags & ETO_PDY)
1716 lpDxW[j++] = lpDx[i * 2];
1717 lpDxW[j++] = lpDx[i * 2 + 1];
1719 else
1720 lpDxW[j++] = lpDx[i];
1721 i = i + 1;
1726 ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1728 HeapFree( GetProcessHeap(), 0, p );
1729 HeapFree( GetProcessHeap(), 0, lpDxW );
1730 return ret;
1734 /***********************************************************************
1735 * ExtTextOutW (GDI32.@)
1737 * Draws text using the currently selected font, background color, and text color.
1740 * PARAMS
1741 * x,y [I] coordinates of string
1742 * flags [I]
1743 * ETO_GRAYED - undocumented on MSDN
1744 * ETO_OPAQUE - use background color for fill the rectangle
1745 * ETO_CLIPPED - clipping text to the rectangle
1746 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1747 * than encoded characters. Implies ETO_IGNORELANGUAGE
1748 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1749 * Affects BiDi ordering
1750 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1751 * ETO_PDY - unimplemented
1752 * ETO_NUMERICSLATIN - unimplemented always assumed -
1753 * do not translate numbers into locale representations
1754 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1755 * lprect [I] dimensions for clipping or/and opaquing
1756 * str [I] text string
1757 * count [I] number of symbols in string
1758 * lpDx [I] optional parameter with distance between drawing characters
1760 * RETURNS
1761 * Success: TRUE
1762 * Failure: FALSE
1764 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1765 const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1767 BOOL ret = FALSE;
1768 LPWSTR reordered_str = (LPWSTR)str;
1769 WORD *glyphs = NULL;
1770 UINT align = GetTextAlign( hdc );
1771 DWORD layout = GetLayout( hdc );
1772 POINT pt;
1773 TEXTMETRICW tm;
1774 LOGFONTW lf;
1775 double cosEsc, sinEsc;
1776 INT char_extra;
1777 SIZE sz;
1778 RECT rc;
1779 BOOL done_extents = FALSE;
1780 POINT *deltas = NULL, width = {0, 0};
1781 DWORD type;
1782 DC * dc = get_dc_ptr( hdc );
1783 PHYSDEV physdev;
1784 INT breakRem;
1785 static int quietfixme = 0;
1787 if (!dc) return FALSE;
1789 breakRem = dc->breakRem;
1791 if (quietfixme == 0 && flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN))
1793 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN unimplemented\n");
1794 quietfixme = 1;
1797 update_dc( dc );
1798 physdev = GET_DC_PHYSDEV( dc, pExtTextOut );
1799 type = GetObjectType(hdc);
1800 if(type == OBJ_METADC || type == OBJ_ENHMETADC)
1802 ret = physdev->funcs->pExtTextOut( physdev, x, y, flags, lprect, str, count, lpDx );
1803 release_dc_ptr( dc );
1804 return ret;
1807 if (!lprect)
1808 flags &= ~ETO_CLIPPED;
1810 if (flags & ETO_RTLREADING) align |= TA_RTLREADING;
1811 if (layout & LAYOUT_RTL)
1813 if ((align & TA_CENTER) != TA_CENTER) align ^= TA_RIGHT;
1814 align ^= TA_RTLREADING;
1817 if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && count > 0 )
1819 INT cGlyphs;
1820 reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1822 BIDI_Reorder( hdc, str, count, GCP_REORDER,
1823 (align & TA_RTLREADING) ? WINE_GCPW_FORCE_RTL : WINE_GCPW_FORCE_LTR,
1824 reordered_str, count, NULL, &glyphs, &cGlyphs);
1826 flags |= ETO_IGNORELANGUAGE;
1827 if (glyphs)
1829 flags |= ETO_GLYPH_INDEX;
1830 if (cGlyphs != count)
1831 count = cGlyphs;
1834 else if(flags & ETO_GLYPH_INDEX)
1835 glyphs = reordered_str;
1837 TRACE("%p, %d, %d, %08x, %s, %s, %d, %p)\n", hdc, x, y, flags,
1838 wine_dbgstr_rect(lprect), debugstr_wn(str, count), count, lpDx);
1839 TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
1841 if(align & TA_UPDATECP)
1843 GetCurrentPositionEx( hdc, &pt );
1844 x = pt.x;
1845 y = pt.y;
1848 GetTextMetricsW(hdc, &tm);
1849 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1851 if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
1852 lf.lfEscapement = 0;
1854 if(lf.lfEscapement != 0)
1856 cosEsc = cos(lf.lfEscapement * M_PI / 1800);
1857 sinEsc = sin(lf.lfEscapement * M_PI / 1800);
1859 else
1861 cosEsc = 1;
1862 sinEsc = 0;
1865 if(flags & (ETO_CLIPPED | ETO_OPAQUE))
1867 if(!lprect)
1869 if(flags & ETO_GLYPH_INDEX)
1870 GetTextExtentPointI(hdc, glyphs, count, &sz);
1871 else
1872 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1874 done_extents = TRUE;
1875 rc.left = x;
1876 rc.top = y;
1877 rc.right = x + sz.cx;
1878 rc.bottom = y + sz.cy;
1880 else
1882 rc = *lprect;
1885 LPtoDP(hdc, (POINT*)&rc, 2);
1887 if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
1888 if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
1891 if ((flags & ETO_OPAQUE) && !PATH_IsPathOpen(dc->path))
1892 physdev->funcs->pExtTextOut( physdev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL );
1894 if(count == 0)
1896 ret = TRUE;
1897 goto done;
1900 pt.x = x;
1901 pt.y = y;
1902 LPtoDP(hdc, &pt, 1);
1903 x = pt.x;
1904 y = pt.y;
1906 char_extra = GetTextCharacterExtra(hdc);
1907 if(char_extra || dc->breakExtra || breakRem || lpDx || lf.lfEscapement != 0)
1909 UINT i;
1910 SIZE tmpsz;
1911 POINT total = {0, 0}, desired[2];
1913 deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
1914 for(i = 0; i < count; i++)
1916 if(lpDx)
1918 if(flags & ETO_PDY)
1920 deltas[i].x = lpDx[i * 2] + char_extra;
1921 deltas[i].y = -lpDx[i * 2 + 1];
1923 else
1925 deltas[i].x = lpDx[i] + char_extra;
1926 deltas[i].y = 0;
1930 else
1932 if(flags & ETO_GLYPH_INDEX)
1933 GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
1934 else
1935 GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
1937 deltas[i].x = tmpsz.cx;
1938 deltas[i].y = 0;
1941 if (!(flags & ETO_GLYPH_INDEX) && (dc->breakExtra || breakRem) && reordered_str[i] == tm.tmBreakChar)
1943 deltas[i].x = deltas[i].x + dc->breakExtra;
1944 if (breakRem > 0)
1946 breakRem--;
1947 deltas[i].x++;
1950 total.x += deltas[i].x;
1951 total.y += deltas[i].y;
1953 desired[0].x = desired[0].y = 0;
1955 desired[1].x = cosEsc * total.x + sinEsc * total.y;
1956 desired[1].y = -sinEsc * total.x + cosEsc * total.y;
1958 LPtoDP(hdc, desired, 2);
1959 desired[1].x -= desired[0].x;
1960 desired[1].y -= desired[0].y;
1961 if (layout & LAYOUT_RTL) desired[1].x = -desired[1].x;
1963 deltas[i].x = desired[1].x - width.x;
1964 deltas[i].y = desired[1].y - width.y;
1966 width = desired[1];
1968 flags |= ETO_PDY;
1970 else
1972 if(!done_extents)
1974 if(flags & ETO_GLYPH_INDEX)
1975 GetTextExtentPointI(hdc, glyphs, count, &sz);
1976 else
1977 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1978 done_extents = TRUE;
1980 width.x = abs(INTERNAL_XWSTODS(dc, sz.cx));
1981 width.y = 0;
1984 tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
1985 tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
1986 switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
1988 case TA_LEFT:
1989 if (align & TA_UPDATECP)
1991 pt.x = x + width.x;
1992 pt.y = y + width.y;
1993 DPtoLP(hdc, &pt, 1);
1994 MoveToEx(hdc, pt.x, pt.y, NULL);
1996 break;
1998 case TA_CENTER:
1999 x -= width.x / 2;
2000 y -= width.y / 2;
2001 break;
2003 case TA_RIGHT:
2004 x -= width.x;
2005 y -= width.y;
2006 if (align & TA_UPDATECP)
2008 pt.x = x;
2009 pt.y = y;
2010 DPtoLP(hdc, &pt, 1);
2011 MoveToEx(hdc, pt.x, pt.y, NULL);
2013 break;
2016 switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
2018 case TA_TOP:
2019 y += tm.tmAscent * cosEsc;
2020 x += tm.tmAscent * sinEsc;
2021 break;
2023 case TA_BOTTOM:
2024 y -= tm.tmDescent * cosEsc;
2025 x -= tm.tmDescent * sinEsc;
2026 break;
2028 case TA_BASELINE:
2029 break;
2032 if (GetBkMode(hdc) != TRANSPARENT && !PATH_IsPathOpen(dc->path))
2034 if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
2036 if(!(flags & ETO_OPAQUE) || x < rc.left || x + width.x >= rc.right ||
2037 y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
2039 RECT rc;
2040 rc.left = x;
2041 rc.right = x + width.x;
2042 rc.top = y - tm.tmAscent;
2043 rc.bottom = y + tm.tmDescent;
2045 if(flags & ETO_CLIPPED)
2047 rc.left = max(lprect->left, rc.left);
2048 rc.right = min(lprect->right, rc.right);
2049 rc.top = max(lprect->top, rc.top);
2050 rc.bottom = min(lprect->bottom, rc.bottom);
2052 if(rc.left < rc.right && rc.top < rc.bottom)
2053 physdev->funcs->pExtTextOut( physdev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL );
2058 if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
2060 HFONT orig_font = dc->hFont, cur_font;
2061 UINT glyph;
2062 INT span = 0;
2063 POINT *offsets = NULL;
2064 unsigned int i;
2066 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2067 for(i = 0; i < count; i++)
2069 WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
2070 if(cur_font != dc->hFont)
2072 if(!offsets)
2074 unsigned int j;
2075 offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
2076 offsets[0].x = offsets[0].y = 0;
2078 if(!deltas)
2080 SIZE tmpsz;
2081 for(j = 1; j < count; j++)
2083 GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
2084 offsets[j].x = offsets[j - 1].x + abs(INTERNAL_XWSTODS(dc, tmpsz.cx));
2085 offsets[j].y = 0;
2088 else
2090 for(j = 1; j < count; j++)
2092 offsets[j].x = offsets[j - 1].x + deltas[j].x;
2093 offsets[j].y = offsets[j - 1].y + deltas[j].y;
2097 if(span)
2099 if (PATH_IsPathOpen(dc->path))
2100 ret = PATH_ExtTextOut(dc, x + offsets[i - span].x, y + offsets[i - span].y,
2101 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2102 glyphs, span, deltas ? (INT*)(deltas + (i - span)) : NULL);
2103 else
2104 physdev->funcs->pExtTextOut( physdev, x + offsets[i - span].x,
2105 y + offsets[i - span].y,
2106 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc, glyphs,
2107 span, deltas ? (INT*)(deltas + (i - span)) : NULL);
2108 span = 0;
2110 SelectObject(hdc, cur_font);
2112 glyphs[span++] = glyph;
2114 if(i == count - 1)
2116 if (PATH_IsPathOpen(dc->path))
2117 ret = PATH_ExtTextOut(dc, x + (offsets ? offsets[count - span].x : 0),
2118 y + (offsets ? offsets[count - span].y : 0),
2119 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2120 glyphs, span, deltas ? (INT*)(deltas + (count - span)) : NULL);
2121 else
2122 ret = physdev->funcs->pExtTextOut(physdev, x + (offsets ? offsets[count - span].x : 0),
2123 y + (offsets ? offsets[count - span].y : 0),
2124 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc, glyphs,
2125 span, deltas ? (INT*)(deltas + (count - span)) : NULL);
2126 SelectObject(hdc, orig_font);
2127 HeapFree(GetProcessHeap(), 0, offsets);
2131 else
2133 if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
2135 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2136 GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
2137 flags |= ETO_GLYPH_INDEX;
2140 if (PATH_IsPathOpen(dc->path))
2141 ret = PATH_ExtTextOut(dc, x, y, (flags & ~ETO_OPAQUE), &rc,
2142 glyphs ? glyphs : reordered_str, count, (INT*)deltas);
2143 else
2144 ret = physdev->funcs->pExtTextOut( physdev, x, y, (flags & ~ETO_OPAQUE), &rc,
2145 glyphs ? glyphs : reordered_str, count, (INT*)deltas );
2148 done:
2149 HeapFree(GetProcessHeap(), 0, deltas);
2150 if(glyphs != reordered_str)
2151 HeapFree(GetProcessHeap(), 0, glyphs);
2152 if(reordered_str != str)
2153 HeapFree(GetProcessHeap(), 0, reordered_str);
2155 release_dc_ptr( dc );
2157 if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2159 int underlinePos, strikeoutPos;
2160 int underlineWidth, strikeoutWidth;
2161 UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2162 OUTLINETEXTMETRICW* otm = NULL;
2164 if(!size)
2166 underlinePos = 0;
2167 underlineWidth = tm.tmAscent / 20 + 1;
2168 strikeoutPos = tm.tmAscent / 2;
2169 strikeoutWidth = underlineWidth;
2171 else
2173 otm = HeapAlloc(GetProcessHeap(), 0, size);
2174 GetOutlineTextMetricsW(hdc, size, otm);
2175 underlinePos = otm->otmsUnderscorePosition;
2176 underlineWidth = otm->otmsUnderscoreSize;
2177 strikeoutPos = otm->otmsStrikeoutPosition;
2178 strikeoutWidth = otm->otmsStrikeoutSize;
2179 HeapFree(GetProcessHeap(), 0, otm);
2182 if (PATH_IsPathOpen(dc->path))
2184 POINT pts[5];
2185 HPEN hpen;
2186 HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2188 hbrush = SelectObject(hdc, hbrush);
2189 hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2191 if (lf.lfUnderline)
2193 pts[0].x = x - underlinePos * sinEsc;
2194 pts[0].y = y - underlinePos * cosEsc;
2195 pts[1].x = x + width.x - underlinePos * sinEsc;
2196 pts[1].y = y + width.y - underlinePos * cosEsc;
2197 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2198 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2199 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2200 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2201 pts[4].x = pts[0].x;
2202 pts[4].y = pts[0].y;
2203 DPtoLP(hdc, pts, 5);
2204 Polygon(hdc, pts, 5);
2207 if (lf.lfStrikeOut)
2209 pts[0].x = x - strikeoutPos * sinEsc;
2210 pts[0].y = y - strikeoutPos * cosEsc;
2211 pts[1].x = x + width.x - strikeoutPos * sinEsc;
2212 pts[1].y = y + width.y - strikeoutPos * cosEsc;
2213 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2214 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2215 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2216 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2217 pts[4].x = pts[0].x;
2218 pts[4].y = pts[0].y;
2219 DPtoLP(hdc, pts, 5);
2220 Polygon(hdc, pts, 5);
2223 SelectObject(hdc, hpen);
2224 hbrush = SelectObject(hdc, hbrush);
2225 DeleteObject(hbrush);
2227 else
2229 POINT pts[2], oldpt;
2230 HPEN hpen;
2232 if (lf.lfUnderline)
2234 hpen = CreatePen(PS_SOLID, underlineWidth, GetTextColor(hdc));
2235 hpen = SelectObject(hdc, hpen);
2236 pts[0].x = x;
2237 pts[0].y = y;
2238 pts[1].x = x + width.x;
2239 pts[1].y = y + width.y;
2240 DPtoLP(hdc, pts, 2);
2241 MoveToEx(hdc, pts[0].x - underlinePos * sinEsc, pts[0].y - underlinePos * cosEsc, &oldpt);
2242 LineTo(hdc, pts[1].x - underlinePos * sinEsc, pts[1].y - underlinePos * cosEsc);
2243 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2244 DeleteObject(SelectObject(hdc, hpen));
2247 if (lf.lfStrikeOut)
2249 hpen = CreatePen(PS_SOLID, strikeoutWidth, GetTextColor(hdc));
2250 hpen = SelectObject(hdc, hpen);
2251 pts[0].x = x;
2252 pts[0].y = y;
2253 pts[1].x = x + width.x;
2254 pts[1].y = y + width.y;
2255 DPtoLP(hdc, pts, 2);
2256 MoveToEx(hdc, pts[0].x - strikeoutPos * sinEsc, pts[0].y - strikeoutPos * cosEsc, &oldpt);
2257 LineTo(hdc, pts[1].x - strikeoutPos * sinEsc, pts[1].y - strikeoutPos * cosEsc);
2258 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2259 DeleteObject(SelectObject(hdc, hpen));
2264 return ret;
2268 /***********************************************************************
2269 * TextOutA (GDI32.@)
2271 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2273 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2277 /***********************************************************************
2278 * TextOutW (GDI32.@)
2280 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2282 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2286 /***********************************************************************
2287 * PolyTextOutA (GDI32.@)
2289 * See PolyTextOutW.
2291 BOOL WINAPI PolyTextOutA( HDC hdc, const POLYTEXTA *pptxt, INT cStrings )
2293 for (; cStrings>0; cStrings--, pptxt++)
2294 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2295 return FALSE;
2296 return TRUE;
2301 /***********************************************************************
2302 * PolyTextOutW (GDI32.@)
2304 * Draw several Strings
2306 * RETURNS
2307 * TRUE: Success.
2308 * FALSE: Failure.
2310 BOOL WINAPI PolyTextOutW( HDC hdc, const POLYTEXTW *pptxt, INT cStrings )
2312 for (; cStrings>0; cStrings--, pptxt++)
2313 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2314 return FALSE;
2315 return TRUE;
2319 /***********************************************************************
2320 * SetMapperFlags (GDI32.@)
2322 DWORD WINAPI SetMapperFlags( HDC hdc, DWORD flags )
2324 DC *dc = get_dc_ptr( hdc );
2325 DWORD ret = GDI_ERROR;
2327 if (dc)
2329 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetMapperFlags );
2330 flags = physdev->funcs->pSetMapperFlags( physdev, flags );
2331 if (flags != GDI_ERROR)
2333 ret = dc->mapperFlags;
2334 dc->mapperFlags = flags;
2336 release_dc_ptr( dc );
2338 return ret;
2341 /***********************************************************************
2342 * GetAspectRatioFilterEx (GDI32.@)
2344 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2346 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2347 return FALSE;
2351 /***********************************************************************
2352 * GetCharABCWidthsA (GDI32.@)
2354 * See GetCharABCWidthsW.
2356 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2357 LPABC abc )
2359 INT i, wlen;
2360 LPSTR str;
2361 LPWSTR wstr;
2362 BOOL ret = TRUE;
2364 str = FONT_GetCharsByRangeA(hdc, firstChar, lastChar, &i);
2365 if (str == NULL)
2366 return FALSE;
2368 wstr = FONT_mbtowc(hdc, str, i, &wlen, NULL);
2369 if (wstr == NULL)
2371 HeapFree(GetProcessHeap(), 0, str);
2372 return FALSE;
2375 for(i = 0; i < wlen; i++)
2377 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2379 ret = FALSE;
2380 break;
2382 abc++;
2385 HeapFree(GetProcessHeap(), 0, str);
2386 HeapFree(GetProcessHeap(), 0, wstr);
2388 return ret;
2392 /******************************************************************************
2393 * GetCharABCWidthsW [GDI32.@]
2395 * Retrieves widths of characters in range.
2397 * PARAMS
2398 * hdc [I] Handle of device context
2399 * firstChar [I] First character in range to query
2400 * lastChar [I] Last character in range to query
2401 * abc [O] Address of character-width structure
2403 * NOTES
2404 * Only works with TrueType fonts
2406 * RETURNS
2407 * Success: TRUE
2408 * Failure: FALSE
2410 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2411 LPABC abc )
2413 DC *dc = get_dc_ptr(hdc);
2414 unsigned int i;
2415 BOOL ret = FALSE;
2417 if (!dc) return FALSE;
2419 if (!abc)
2421 release_dc_ptr( dc );
2422 return FALSE;
2425 if(dc->gdiFont)
2426 ret = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
2427 else
2428 FIXME(": stub\n");
2430 if (ret)
2432 /* convert device units to logical */
2433 for( i = firstChar; i <= lastChar; i++, abc++ ) {
2434 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2435 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2436 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2438 ret = TRUE;
2441 release_dc_ptr( dc );
2442 return ret;
2446 /******************************************************************************
2447 * GetCharABCWidthsI [GDI32.@]
2449 * Retrieves widths of characters in range.
2451 * PARAMS
2452 * hdc [I] Handle of device context
2453 * firstChar [I] First glyphs in range to query
2454 * count [I] Last glyphs in range to query
2455 * pgi [i] Array of glyphs to query
2456 * abc [O] Address of character-width structure
2458 * NOTES
2459 * Only works with TrueType fonts
2461 * RETURNS
2462 * Success: TRUE
2463 * Failure: FALSE
2465 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2466 LPWORD pgi, LPABC abc)
2468 DC *dc = get_dc_ptr(hdc);
2469 unsigned int i;
2470 BOOL ret = FALSE;
2472 if (!dc) return FALSE;
2474 if (!abc)
2476 release_dc_ptr( dc );
2477 return FALSE;
2480 if(dc->gdiFont)
2481 ret = WineEngGetCharABCWidthsI( dc->gdiFont, firstChar, count, pgi, abc );
2482 else
2483 FIXME(": stub\n");
2485 if (ret)
2487 /* convert device units to logical */
2488 for( i = 0; i < count; i++, abc++ ) {
2489 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2490 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2491 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2493 ret = TRUE;
2496 release_dc_ptr( dc );
2497 return ret;
2501 /***********************************************************************
2502 * GetGlyphOutlineA (GDI32.@)
2504 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2505 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2506 LPVOID lpBuffer, const MAT2 *lpmat2 )
2508 if (!lpmat2) return GDI_ERROR;
2510 if(!(fuFormat & GGO_GLYPH_INDEX)) {
2511 UINT cp;
2512 int len;
2513 char mbchs[2];
2515 cp = GdiGetCodePage(hdc);
2516 if (IsDBCSLeadByteEx(cp, uChar >> 8)) {
2517 len = 2;
2518 mbchs[0] = (uChar & 0xff00) >> 8;
2519 mbchs[1] = (uChar & 0xff);
2520 } else {
2521 len = 1;
2522 mbchs[0] = (uChar & 0xff);
2524 MultiByteToWideChar(cp, 0, mbchs, len, (LPWSTR)&uChar, 1);
2527 return GetGlyphOutlineW(hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer,
2528 lpmat2);
2531 /***********************************************************************
2532 * GetGlyphOutlineW (GDI32.@)
2534 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2535 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2536 LPVOID lpBuffer, const MAT2 *lpmat2 )
2538 DC *dc;
2539 DWORD ret;
2541 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2542 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2544 if (!lpmat2) return GDI_ERROR;
2546 dc = get_dc_ptr(hdc);
2547 if(!dc) return GDI_ERROR;
2549 if(dc->gdiFont)
2550 ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
2551 cbBuffer, lpBuffer, lpmat2);
2552 else
2553 ret = GDI_ERROR;
2555 release_dc_ptr( dc );
2556 return ret;
2560 /***********************************************************************
2561 * CreateScalableFontResourceA (GDI32.@)
2563 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2564 LPCSTR lpszResourceFile,
2565 LPCSTR lpszFontFile,
2566 LPCSTR lpszCurrentPath )
2568 LPWSTR lpszResourceFileW = NULL;
2569 LPWSTR lpszFontFileW = NULL;
2570 LPWSTR lpszCurrentPathW = NULL;
2571 int len;
2572 BOOL ret;
2574 if (lpszResourceFile)
2576 len = MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, NULL, 0);
2577 lpszResourceFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2578 MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, lpszResourceFileW, len);
2581 if (lpszFontFile)
2583 len = MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, NULL, 0);
2584 lpszFontFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2585 MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, lpszFontFileW, len);
2588 if (lpszCurrentPath)
2590 len = MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, NULL, 0);
2591 lpszCurrentPathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2592 MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, lpszCurrentPathW, len);
2595 ret = CreateScalableFontResourceW(fHidden, lpszResourceFileW,
2596 lpszFontFileW, lpszCurrentPathW);
2598 HeapFree(GetProcessHeap(), 0, lpszResourceFileW);
2599 HeapFree(GetProcessHeap(), 0, lpszFontFileW);
2600 HeapFree(GetProcessHeap(), 0, lpszCurrentPathW);
2602 return ret;
2605 /***********************************************************************
2606 * CreateScalableFontResourceW (GDI32.@)
2608 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2609 LPCWSTR lpszResourceFile,
2610 LPCWSTR lpszFontFile,
2611 LPCWSTR lpszCurrentPath )
2613 HANDLE f;
2614 FIXME("(%d,%s,%s,%s): stub\n",
2615 fHidden, debugstr_w(lpszResourceFile), debugstr_w(lpszFontFile),
2616 debugstr_w(lpszCurrentPath) );
2618 /* fHidden=1 - only visible for the calling app, read-only, not
2619 * enumerated with EnumFonts/EnumFontFamilies
2620 * lpszCurrentPath can be NULL
2623 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2624 if ((f = CreateFileW(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2625 CloseHandle(f);
2626 SetLastError(ERROR_FILE_EXISTS);
2627 return FALSE;
2629 return FALSE; /* create failed */
2632 /*************************************************************************
2633 * GetKerningPairsA (GDI32.@)
2635 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2636 LPKERNINGPAIR kern_pairA )
2638 UINT cp;
2639 CPINFO cpi;
2640 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2641 KERNINGPAIR *kern_pairW;
2643 if (!cPairs && kern_pairA)
2645 SetLastError(ERROR_INVALID_PARAMETER);
2646 return 0;
2649 cp = GdiGetCodePage(hDC);
2651 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2652 * to fail on an invalid character for CP_SYMBOL.
2654 cpi.DefaultChar[0] = 0;
2655 if (cp != CP_SYMBOL && !GetCPInfo(cp, &cpi))
2657 FIXME("Can't find codepage %u info\n", cp);
2658 return 0;
2661 total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2662 if (!total_kern_pairs) return 0;
2664 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2665 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2667 for (i = 0; i < total_kern_pairs; i++)
2669 char first, second;
2671 if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2672 continue;
2674 if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2675 continue;
2677 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2678 continue;
2680 if (kern_pairA)
2682 if (kern_pairs_copied >= cPairs) break;
2684 kern_pairA->wFirst = (BYTE)first;
2685 kern_pairA->wSecond = (BYTE)second;
2686 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2687 kern_pairA++;
2689 kern_pairs_copied++;
2692 HeapFree(GetProcessHeap(), 0, kern_pairW);
2694 return kern_pairs_copied;
2697 /*************************************************************************
2698 * GetKerningPairsW (GDI32.@)
2700 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2701 LPKERNINGPAIR lpKerningPairs )
2703 DC *dc;
2704 DWORD ret = 0;
2706 TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2708 if (!cPairs && lpKerningPairs)
2710 SetLastError(ERROR_INVALID_PARAMETER);
2711 return 0;
2714 dc = get_dc_ptr(hDC);
2715 if (!dc) return 0;
2717 if (dc->gdiFont)
2718 ret = WineEngGetKerningPairs(dc->gdiFont, cPairs, lpKerningPairs);
2720 release_dc_ptr( dc );
2721 return ret;
2724 /*************************************************************************
2725 * TranslateCharsetInfo [GDI32.@]
2727 * Fills a CHARSETINFO structure for a character set, code page, or
2728 * font. This allows making the correspondence between different labels
2729 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2730 * of the same encoding.
2732 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2733 * only one codepage should be set in *lpSrc.
2735 * RETURNS
2736 * TRUE on success, FALSE on failure.
2739 BOOL WINAPI TranslateCharsetInfo(
2740 LPDWORD lpSrc, /* [in]
2741 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2742 if flags == TCI_SRCCHARSET: a character set value
2743 if flags == TCI_SRCCODEPAGE: a code page value
2745 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2746 DWORD flags /* [in] determines interpretation of lpSrc */)
2748 int index = 0;
2749 switch (flags) {
2750 case TCI_SRCFONTSIG:
2751 while (index < MAXTCIINDEX && !(*lpSrc>>index & 0x0001)) index++;
2752 break;
2753 case TCI_SRCCODEPAGE:
2754 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciACP) index++;
2755 break;
2756 case TCI_SRCCHARSET:
2757 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciCharset) index++;
2758 break;
2759 default:
2760 return FALSE;
2762 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2763 *lpCs = FONT_tci[index];
2764 return TRUE;
2767 /*************************************************************************
2768 * GetFontLanguageInfo (GDI32.@)
2770 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2772 FONTSIGNATURE fontsig;
2773 static const DWORD GCP_DBCS_MASK=0x003F0000,
2774 GCP_DIACRITIC_MASK=0x00000000,
2775 FLI_GLYPHS_MASK=0x00000000,
2776 GCP_GLYPHSHAPE_MASK=0x00000040,
2777 GCP_KASHIDA_MASK=0x00000000,
2778 GCP_LIGATE_MASK=0x00000000,
2779 GCP_USEKERNING_MASK=0x00000000,
2780 GCP_REORDER_MASK=0x00000060;
2782 DWORD result=0;
2784 GetTextCharsetInfo( hdc, &fontsig, 0 );
2785 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2787 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2788 result|=GCP_DBCS;
2790 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2791 result|=GCP_DIACRITIC;
2793 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2794 result|=FLI_GLYPHS;
2796 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2797 result|=GCP_GLYPHSHAPE;
2799 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2800 result|=GCP_KASHIDA;
2802 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2803 result|=GCP_LIGATE;
2805 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2806 result|=GCP_USEKERNING;
2808 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2809 if( GetTextAlign( hdc) & TA_RTLREADING )
2810 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2811 result|=GCP_REORDER;
2813 return result;
2817 /*************************************************************************
2818 * GetFontData [GDI32.@]
2820 * Retrieve data for TrueType font.
2822 * RETURNS
2824 * success: Number of bytes returned
2825 * failure: GDI_ERROR
2827 * NOTES
2829 * Calls SetLastError()
2832 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2833 LPVOID buffer, DWORD length)
2835 DC *dc = get_dc_ptr(hdc);
2836 DWORD ret = GDI_ERROR;
2838 if(!dc) return GDI_ERROR;
2840 if(dc->gdiFont)
2841 ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2843 release_dc_ptr( dc );
2844 return ret;
2847 /*************************************************************************
2848 * GetGlyphIndicesA [GDI32.@]
2850 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2851 LPWORD pgi, DWORD flags)
2853 DWORD ret;
2854 WCHAR *lpstrW;
2855 INT countW;
2857 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2858 hdc, debugstr_an(lpstr, count), count, pgi, flags);
2860 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2861 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2862 HeapFree(GetProcessHeap(), 0, lpstrW);
2864 return ret;
2867 /*************************************************************************
2868 * GetGlyphIndicesW [GDI32.@]
2870 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2871 LPWORD pgi, DWORD flags)
2873 DC *dc = get_dc_ptr(hdc);
2874 DWORD ret = GDI_ERROR;
2876 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2877 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2879 if(!dc) return GDI_ERROR;
2881 if(dc->gdiFont)
2882 ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2884 release_dc_ptr( dc );
2885 return ret;
2888 /*************************************************************************
2889 * GetCharacterPlacementA [GDI32.@]
2891 * See GetCharacterPlacementW.
2893 * NOTES:
2894 * the web browser control of ie4 calls this with dwFlags=0
2896 DWORD WINAPI
2897 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2898 INT nMaxExtent, GCP_RESULTSA *lpResults,
2899 DWORD dwFlags)
2901 WCHAR *lpStringW;
2902 INT uCountW;
2903 GCP_RESULTSW resultsW;
2904 DWORD ret;
2905 UINT font_cp;
2907 TRACE("%s, %d, %d, 0x%08x\n",
2908 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2910 /* both structs are equal in size */
2911 memcpy(&resultsW, lpResults, sizeof(resultsW));
2913 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2914 if(lpResults->lpOutString)
2915 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2917 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2919 lpResults->nGlyphs = resultsW.nGlyphs;
2920 lpResults->nMaxFit = resultsW.nMaxFit;
2922 if(lpResults->lpOutString) {
2923 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2924 lpResults->lpOutString, uCount, NULL, NULL );
2927 HeapFree(GetProcessHeap(), 0, lpStringW);
2928 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2930 return ret;
2933 /*************************************************************************
2934 * GetCharacterPlacementW [GDI32.@]
2936 * Retrieve information about a string. This includes the width, reordering,
2937 * Glyphing and so on.
2939 * RETURNS
2941 * The width and height of the string if successful, 0 if failed.
2943 * BUGS
2945 * All flags except GCP_REORDER are not yet implemented.
2946 * Reordering is not 100% compliant to the Windows BiDi method.
2947 * Caret positioning is not yet implemented for BiDi.
2948 * Classes are not yet implemented.
2951 DWORD WINAPI
2952 GetCharacterPlacementW(
2953 HDC hdc, /* [in] Device context for which the rendering is to be done */
2954 LPCWSTR lpString, /* [in] The string for which information is to be returned */
2955 INT uCount, /* [in] Number of WORDS in string. */
2956 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
2957 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2958 DWORD dwFlags /* [in] Flags specifying how to process the string */
2961 DWORD ret=0;
2962 SIZE size;
2963 UINT i, nSet;
2965 TRACE("%s, %d, %d, 0x%08x\n",
2966 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2968 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2969 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2970 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2971 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2972 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2974 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08x ignored\n", dwFlags);
2975 if(lpResults->lpClass) FIXME("classes not implemented\n");
2976 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2977 FIXME("Caret positions for complex scripts not implemented\n");
2979 nSet = (UINT)uCount;
2980 if(nSet > lpResults->nGlyphs)
2981 nSet = lpResults->nGlyphs;
2983 /* return number of initialized fields */
2984 lpResults->nGlyphs = nSet;
2986 if((dwFlags&GCP_REORDER)==0 )
2988 /* Treat the case where no special handling was requested in a fastpath way */
2989 /* copy will do if the GCP_REORDER flag is not set */
2990 if(lpResults->lpOutString)
2991 memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
2993 if(lpResults->lpOrder)
2995 for(i = 0; i < nSet; i++)
2996 lpResults->lpOrder[i] = i;
2998 } else
3000 BIDI_Reorder(NULL, lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
3001 nSet, lpResults->lpOrder, NULL, NULL );
3004 /* FIXME: Will use the placement chars */
3005 if (lpResults->lpDx)
3007 int c;
3008 for (i = 0; i < nSet; i++)
3010 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
3011 lpResults->lpDx[i]= c;
3015 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
3017 int pos = 0;
3019 lpResults->lpCaretPos[0] = 0;
3020 for (i = 1; i < nSet; i++)
3021 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
3022 lpResults->lpCaretPos[i] = (pos += size.cx);
3025 if(lpResults->lpGlyphs)
3026 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
3028 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
3029 ret = MAKELONG(size.cx, size.cy);
3031 return ret;
3034 /*************************************************************************
3035 * GetCharABCWidthsFloatA [GDI32.@]
3037 * See GetCharABCWidthsFloatW.
3039 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3041 INT i, wlen;
3042 LPSTR str;
3043 LPWSTR wstr;
3044 BOOL ret = TRUE;
3046 str = FONT_GetCharsByRangeA(hdc, first, last, &i);
3047 if (str == NULL)
3048 return FALSE;
3050 wstr = FONT_mbtowc( hdc, str, i, &wlen, NULL );
3052 for (i = 0; i < wlen; i++)
3054 if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
3056 ret = FALSE;
3057 break;
3059 abcf++;
3062 HeapFree( GetProcessHeap(), 0, str );
3063 HeapFree( GetProcessHeap(), 0, wstr );
3065 return ret;
3068 /*************************************************************************
3069 * GetCharABCWidthsFloatW [GDI32.@]
3071 * Retrieves widths of a range of characters.
3073 * PARAMS
3074 * hdc [I] Handle to device context.
3075 * first [I] First character in range to query.
3076 * last [I] Last character in range to query.
3077 * abcf [O] Array of LPABCFLOAT structures.
3079 * RETURNS
3080 * Success: TRUE
3081 * Failure: FALSE
3083 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3085 UINT i;
3086 BOOL ret = FALSE;
3087 DC *dc = get_dc_ptr( hdc );
3089 TRACE("%p, %d, %d, %p\n", hdc, first, last, abcf);
3091 if (!dc) return FALSE;
3093 if (!abcf)
3095 release_dc_ptr( dc );
3096 return FALSE;
3099 if (dc->gdiFont)
3100 ret = WineEngGetCharABCWidthsFloat( dc->gdiFont, first, last, abcf );
3101 else
3102 FIXME("stub\n");
3104 if (ret)
3106 /* convert device units to logical */
3107 for (i = first; i <= last; i++, abcf++)
3109 abcf->abcfA = abcf->abcfA * dc->xformVport2World.eM11;
3110 abcf->abcfB = abcf->abcfB * dc->xformVport2World.eM11;
3111 abcf->abcfC = abcf->abcfC * dc->xformVport2World.eM11;
3115 release_dc_ptr( dc );
3116 return ret;
3119 /*************************************************************************
3120 * GetCharWidthFloatA [GDI32.@]
3122 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
3123 UINT iLastChar, PFLOAT pxBuffer)
3125 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3126 return 0;
3129 /*************************************************************************
3130 * GetCharWidthFloatW [GDI32.@]
3132 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
3133 UINT iLastChar, PFLOAT pxBuffer)
3135 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3136 return 0;
3140 /***********************************************************************
3142 * Font Resource API *
3144 ***********************************************************************/
3146 /***********************************************************************
3147 * AddFontResourceA (GDI32.@)
3149 INT WINAPI AddFontResourceA( LPCSTR str )
3151 return AddFontResourceExA( str, 0, NULL);
3154 /***********************************************************************
3155 * AddFontResourceW (GDI32.@)
3157 INT WINAPI AddFontResourceW( LPCWSTR str )
3159 return AddFontResourceExW(str, 0, NULL);
3163 /***********************************************************************
3164 * AddFontResourceExA (GDI32.@)
3166 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3168 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3169 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3170 INT ret;
3172 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3173 ret = AddFontResourceExW(strW, fl, pdv);
3174 HeapFree(GetProcessHeap(), 0, strW);
3175 return ret;
3178 static BOOL CALLBACK load_enumed_resource(HMODULE hModule, LPCWSTR type, LPWSTR name, LONG_PTR lParam)
3180 HRSRC rsrc = FindResourceW(hModule, name, type);
3181 HGLOBAL hMem = LoadResource(hModule, rsrc);
3182 LPVOID *pMem = LockResource(hMem);
3183 int *num_total = (int *)lParam;
3184 DWORD num_in_res;
3186 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type));
3187 if (!AddFontMemResourceEx(pMem, SizeofResource(hModule, rsrc), NULL, &num_in_res))
3189 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule, hMem);
3190 return FALSE;
3193 *num_total += num_in_res;
3194 return TRUE;
3197 /***********************************************************************
3198 * AddFontResourceExW (GDI32.@)
3200 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3202 int ret = WineEngAddFontResourceEx(str, fl, pdv);
3203 if (ret == 0)
3205 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3206 HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
3207 if (hModule != NULL)
3209 int num_resources = 0;
3210 LPWSTR rt_font = (LPWSTR)((ULONG_PTR)8); /* we don't want to include winuser.h */
3212 TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3213 wine_dbgstr_w(str));
3214 if (EnumResourceNamesW(hModule, rt_font, load_enumed_resource, (LONG_PTR)&num_resources))
3215 ret = num_resources;
3216 FreeLibrary(hModule);
3219 return ret;
3222 /***********************************************************************
3223 * RemoveFontResourceA (GDI32.@)
3225 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3227 return RemoveFontResourceExA(str, 0, 0);
3230 /***********************************************************************
3231 * RemoveFontResourceW (GDI32.@)
3233 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3235 return RemoveFontResourceExW(str, 0, 0);
3238 /***********************************************************************
3239 * AddFontMemResourceEx (GDI32.@)
3241 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3243 HANDLE ret;
3244 DWORD num_fonts;
3246 if (!pbFont || !cbFont || !pcFonts)
3248 SetLastError(ERROR_INVALID_PARAMETER);
3249 return NULL;
3252 ret = WineEngAddFontMemResourceEx(pbFont, cbFont, pdv, &num_fonts);
3253 if (ret)
3255 __TRY
3257 *pcFonts = num_fonts;
3259 __EXCEPT_PAGE_FAULT
3261 WARN("page fault while writing to *pcFonts (%p)\n", pcFonts);
3262 RemoveFontMemResourceEx(ret);
3263 ret = 0;
3265 __ENDTRY
3267 return ret;
3270 /***********************************************************************
3271 * RemoveFontMemResourceEx (GDI32.@)
3273 BOOL WINAPI RemoveFontMemResourceEx( HANDLE fh )
3275 FIXME("(%p) stub\n", fh);
3276 return TRUE;
3279 /***********************************************************************
3280 * RemoveFontResourceExA (GDI32.@)
3282 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3284 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3285 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3286 INT ret;
3288 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3289 ret = RemoveFontResourceExW(strW, fl, pdv);
3290 HeapFree(GetProcessHeap(), 0, strW);
3291 return ret;
3294 /***********************************************************************
3295 * RemoveFontResourceExW (GDI32.@)
3297 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3299 return WineEngRemoveFontResourceEx(str, fl, pdv);
3302 /***********************************************************************
3303 * GetTextCharset (GDI32.@)
3305 UINT WINAPI GetTextCharset(HDC hdc)
3307 /* MSDN docs say this is equivalent */
3308 return GetTextCharsetInfo(hdc, NULL, 0);
3311 /***********************************************************************
3312 * GetTextCharsetInfo (GDI32.@)
3314 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3316 UINT ret = DEFAULT_CHARSET;
3317 DC *dc = get_dc_ptr(hdc);
3319 if (dc)
3321 if (dc->gdiFont)
3322 ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
3324 release_dc_ptr( dc );
3327 if (ret == DEFAULT_CHARSET && fs)
3328 memset(fs, 0, sizeof(FONTSIGNATURE));
3329 return ret;
3332 /***********************************************************************
3333 * GdiGetCharDimensions (GDI32.@)
3335 * Gets the average width of the characters in the English alphabet.
3337 * PARAMS
3338 * hdc [I] Handle to the device context to measure on.
3339 * lptm [O] Pointer to memory to store the text metrics into.
3340 * height [O] On exit, the maximum height of characters in the English alphabet.
3342 * RETURNS
3343 * The average width of characters in the English alphabet.
3345 * NOTES
3346 * This function is used by the dialog manager to get the size of a dialog
3347 * unit. It should also be used by other pieces of code that need to know
3348 * the size of a dialog unit in logical units without having access to the
3349 * window handle of the dialog.
3350 * Windows caches the font metrics from this function, but we don't and
3351 * there doesn't appear to be an immediate advantage to do so.
3353 * SEE ALSO
3354 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3356 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3358 SIZE sz;
3359 static const WCHAR alphabet[] = {
3360 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3361 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3362 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3364 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3366 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3368 if (height) *height = sz.cy;
3369 return (sz.cx / 26 + 1) / 2;
3372 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3374 FIXME("(%d): stub\n", fEnableEUDC);
3375 return FALSE;
3378 /***********************************************************************
3379 * GetCharWidthI (GDI32.@)
3381 * Retrieve widths of characters.
3383 * PARAMS
3384 * hdc [I] Handle to a device context.
3385 * first [I] First glyph in range to query.
3386 * count [I] Number of glyph indices to query.
3387 * glyphs [I] Array of glyphs to query.
3388 * buffer [O] Buffer to receive character widths.
3390 * NOTES
3391 * Only works with TrueType fonts.
3393 * RETURNS
3394 * Success: TRUE
3395 * Failure: FALSE
3397 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3399 ABC *abc;
3400 unsigned int i;
3402 TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3404 if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3405 return FALSE;
3407 if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3409 HeapFree(GetProcessHeap(), 0, abc);
3410 return FALSE;
3413 for (i = 0; i < count; i++)
3414 buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3416 HeapFree(GetProcessHeap(), 0, abc);
3417 return TRUE;
3420 /***********************************************************************
3421 * GetFontUnicodeRanges (GDI32.@)
3423 * Retrieve a list of supported Unicode characters in a font.
3425 * PARAMS
3426 * hdc [I] Handle to a device context.
3427 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3429 * RETURNS
3430 * Success: Number of bytes written to the buffer pointed to by lpgs.
3431 * Failure: 0
3434 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3436 DWORD ret = 0;
3437 DC *dc = get_dc_ptr(hdc);
3439 TRACE("(%p, %p)\n", hdc, lpgs);
3441 if (!dc) return 0;
3443 if (dc->gdiFont) ret = WineEngGetFontUnicodeRanges(dc->gdiFont, lpgs);
3444 release_dc_ptr(dc);
3445 return ret;
3449 /*************************************************************
3450 * FontIsLinked (GDI32.@)
3452 BOOL WINAPI FontIsLinked(HDC hdc)
3454 DC *dc = get_dc_ptr(hdc);
3455 BOOL ret = FALSE;
3457 if (!dc) return FALSE;
3458 if (dc->gdiFont) ret = WineEngFontIsLinked(dc->gdiFont);
3459 release_dc_ptr(dc);
3460 TRACE("returning %d\n", ret);
3461 return ret;
3464 /*************************************************************
3465 * GdiRealizationInfo (GDI32.@)
3467 * Returns a structure that contains some font information.
3469 BOOL WINAPI GdiRealizationInfo(HDC hdc, realization_info_t *info)
3471 DC *dc = get_dc_ptr(hdc);
3472 BOOL ret = FALSE;
3474 if (!dc) return FALSE;
3475 if (dc->gdiFont) ret = WineEngRealizationInfo(dc->gdiFont, info);
3476 release_dc_ptr(dc);
3478 return ret;