Release 1.3.7.
[wine/gsoc-2012-control.git] / dlls / gdi32 / font.c
blobfe68893b63862456dcb090f848b9bcf7455797bc
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 );
533 if (!dc) return 0;
535 if (!GDI_inc_ref_count( handle ))
537 release_dc_ptr( dc );
538 return 0;
541 if (GetDeviceCaps( dc->hSelf, TEXTCAPS ) & TC_VA_ABLE)
542 dc->gdiFont = WineEngCreateFontInstance( dc, handle );
544 if (dc->funcs->pSelectFont) ret = dc->funcs->pSelectFont( dc->physDev, handle, dc->gdiFont );
546 if (ret && dc->gdiFont) dc->gdiFont = 0;
548 if (ret == HGDI_ERROR)
550 GDI_dec_ref_count( handle );
551 ret = 0; /* SelectObject returns 0 on error */
553 else
555 ret = dc->hFont;
556 dc->hFont = handle;
557 update_font_code_page( dc );
558 GDI_dec_ref_count( ret );
560 release_dc_ptr( dc );
561 return ret;
565 /***********************************************************************
566 * FONT_GetObjectA
568 static INT FONT_GetObjectA( HGDIOBJ handle, INT count, LPVOID buffer )
570 FONTOBJ *font = GDI_GetObjPtr( handle, OBJ_FONT );
571 LOGFONTA lfA;
573 if (!font) return 0;
574 if (buffer)
576 FONT_LogFontWToA( &font->logfont, &lfA );
577 if (count > sizeof(lfA)) count = sizeof(lfA);
578 memcpy( buffer, &lfA, count );
580 else count = sizeof(lfA);
581 GDI_ReleaseObj( handle );
582 return count;
585 /***********************************************************************
586 * FONT_GetObjectW
588 static INT FONT_GetObjectW( HGDIOBJ handle, INT count, LPVOID buffer )
590 FONTOBJ *font = GDI_GetObjPtr( handle, OBJ_FONT );
592 if (!font) return 0;
593 if (buffer)
595 if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
596 memcpy( buffer, &font->logfont, count );
598 else count = sizeof(LOGFONTW);
599 GDI_ReleaseObj( handle );
600 return count;
604 /***********************************************************************
605 * FONT_DeleteObject
607 static BOOL FONT_DeleteObject( HGDIOBJ handle )
609 FONTOBJ *obj;
611 WineEngDestroyFontInstance( handle );
613 if (!(obj = free_gdi_handle( handle ))) return FALSE;
614 return HeapFree( GetProcessHeap(), 0, obj );
618 /***********************************************************************
619 * FONT_EnumInstance
621 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
622 * We have to use other types because of the FONTENUMPROCW definition.
624 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
625 DWORD fType, LPARAM lp )
627 fontEnum32 *pfe = (fontEnum32*)lp;
628 INT ret = 1;
630 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
631 if ((!pfe->lpLogFontParam ||
632 pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
633 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
634 (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
636 /* convert font metrics */
637 ENUMLOGFONTEXA logfont;
638 NEWTEXTMETRICEXA tmA;
640 pfe->dwFlags |= ENUM_CALLED;
641 if (!(pfe->dwFlags & ENUM_UNICODE))
643 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
644 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
645 plf = (LOGFONTW *)&logfont.elfLogFont;
646 ptm = (TEXTMETRICW *)&tmA;
649 ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
651 return ret;
654 /***********************************************************************
655 * FONT_EnumFontFamiliesEx
657 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf,
658 FONTENUMPROCW efproc,
659 LPARAM lParam, DWORD dwUnicode)
661 INT ret = 1, ret2;
662 DC *dc = get_dc_ptr( hDC );
663 fontEnum32 fe32;
664 BOOL enum_gdi_fonts;
666 if (!dc) return 0;
668 if (plf)
669 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName),
670 plf->lfCharSet);
671 fe32.lpLogFontParam = plf;
672 fe32.lpEnumFunc = efproc;
673 fe32.lpData = lParam;
674 fe32.dwFlags = dwUnicode;
675 fe32.hdc = hDC;
677 enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE;
679 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
681 ret = 0;
682 goto done;
685 if (enum_gdi_fonts)
686 ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
687 fe32.dwFlags &= ~ENUM_CALLED;
688 if (ret && dc->funcs->pEnumDeviceFonts) {
689 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, plf, FONT_EnumInstance, (LPARAM)&fe32 );
690 if(fe32.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
691 ret = ret2;
693 done:
694 release_dc_ptr( dc );
695 return ret;
698 /***********************************************************************
699 * EnumFontFamiliesExW (GDI32.@)
701 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
702 FONTENUMPROCW efproc,
703 LPARAM lParam, DWORD dwFlags )
705 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, ENUM_UNICODE );
708 /***********************************************************************
709 * EnumFontFamiliesExA (GDI32.@)
711 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
712 FONTENUMPROCA efproc,
713 LPARAM lParam, DWORD dwFlags)
715 LOGFONTW lfW, *plfW;
717 if (plf)
719 FONT_LogFontAToW( plf, &lfW );
720 plfW = &lfW;
722 else plfW = NULL;
724 return FONT_EnumFontFamiliesEx( hDC, plfW, (FONTENUMPROCW)efproc, lParam, 0);
727 /***********************************************************************
728 * EnumFontFamiliesA (GDI32.@)
730 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
731 FONTENUMPROCA efproc, LPARAM lpData )
733 LOGFONTA lf, *plf;
735 if (lpFamily)
737 if (!*lpFamily) return 1;
738 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
739 lf.lfCharSet = DEFAULT_CHARSET;
740 lf.lfPitchAndFamily = 0;
741 plf = &lf;
743 else plf = NULL;
745 return EnumFontFamiliesExA( hDC, plf, efproc, lpData, 0 );
748 /***********************************************************************
749 * EnumFontFamiliesW (GDI32.@)
751 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
752 FONTENUMPROCW efproc, LPARAM lpData )
754 LOGFONTW lf, *plf;
756 if (lpFamily)
758 if (!*lpFamily) return 1;
759 lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
760 lf.lfCharSet = DEFAULT_CHARSET;
761 lf.lfPitchAndFamily = 0;
762 plf = &lf;
764 else plf = NULL;
766 return EnumFontFamiliesExW( hDC, plf, efproc, lpData, 0 );
769 /***********************************************************************
770 * EnumFontsA (GDI32.@)
772 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
773 LPARAM lpData )
775 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
778 /***********************************************************************
779 * EnumFontsW (GDI32.@)
781 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
782 LPARAM lpData )
784 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
788 /***********************************************************************
789 * GetTextCharacterExtra (GDI32.@)
791 INT WINAPI GetTextCharacterExtra( HDC hdc )
793 INT ret;
794 DC *dc = get_dc_ptr( hdc );
795 if (!dc) return 0x80000000;
796 ret = dc->charExtra;
797 release_dc_ptr( dc );
798 return ret;
802 /***********************************************************************
803 * SetTextCharacterExtra (GDI32.@)
805 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
807 INT prev;
808 DC * dc = get_dc_ptr( hdc );
809 if (!dc) return 0x80000000;
810 if (dc->funcs->pSetTextCharacterExtra)
811 prev = dc->funcs->pSetTextCharacterExtra( dc->physDev, extra );
812 else
814 prev = dc->charExtra;
815 dc->charExtra = extra;
817 release_dc_ptr( dc );
818 return prev;
822 /***********************************************************************
823 * SetTextJustification (GDI32.@)
825 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
827 BOOL ret = TRUE;
828 DC * dc = get_dc_ptr( hdc );
829 if (!dc) return FALSE;
830 if (dc->funcs->pSetTextJustification)
831 ret = dc->funcs->pSetTextJustification( dc->physDev, extra, breaks );
832 else
834 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
835 if (!extra) breaks = 0;
836 if (breaks)
838 dc->breakExtra = extra / breaks;
839 dc->breakRem = extra - (breaks * dc->breakExtra);
841 else
843 dc->breakExtra = 0;
844 dc->breakRem = 0;
847 release_dc_ptr( dc );
848 return ret;
852 /***********************************************************************
853 * GetTextFaceA (GDI32.@)
855 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
857 INT res = GetTextFaceW(hdc, 0, NULL);
858 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
859 GetTextFaceW( hdc, res, nameW );
861 if (name)
863 if (count)
865 res = WideCharToMultiByte(CP_ACP, 0, nameW, -1, name, count, NULL, NULL);
866 if (res == 0)
867 res = count;
868 name[count-1] = 0;
869 /* GetTextFaceA does NOT include the nul byte in the return count. */
870 res--;
872 else
873 res = 0;
875 else
876 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
877 HeapFree( GetProcessHeap(), 0, nameW );
878 return res;
881 /***********************************************************************
882 * GetTextFaceW (GDI32.@)
884 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
886 FONTOBJ *font;
887 INT ret = 0;
889 DC * dc = get_dc_ptr( hdc );
890 if (!dc) return 0;
892 if(dc->gdiFont)
893 ret = WineEngGetTextFace(dc->gdiFont, count, name);
894 else if ((font = GDI_GetObjPtr( dc->hFont, OBJ_FONT )))
896 INT n = strlenW(font->logfont.lfFaceName) + 1;
897 if (name)
899 lstrcpynW( name, font->logfont.lfFaceName, count );
900 ret = min(count, n);
902 else ret = n;
903 GDI_ReleaseObj( dc->hFont );
905 release_dc_ptr( dc );
906 return ret;
910 /***********************************************************************
911 * GetTextExtentPoint32A (GDI32.@)
913 * See GetTextExtentPoint32W.
915 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
916 LPSIZE size )
918 BOOL ret = FALSE;
919 INT wlen;
920 LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
922 if (p) {
923 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
924 HeapFree( GetProcessHeap(), 0, p );
927 TRACE("(%p %s %d %p): returning %d x %d\n",
928 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
929 return ret;
933 /***********************************************************************
934 * GetTextExtentPoint32W [GDI32.@]
936 * Computes width/height for a string.
938 * Computes width and height of the specified string.
940 * RETURNS
941 * Success: TRUE
942 * Failure: FALSE
944 BOOL WINAPI GetTextExtentPoint32W(
945 HDC hdc, /* [in] Handle of device context */
946 LPCWSTR str, /* [in] Address of text string */
947 INT count, /* [in] Number of characters in string */
948 LPSIZE size) /* [out] Address of structure for string size */
950 return GetTextExtentExPointW(hdc, str, count, 0, NULL, NULL, size);
953 /***********************************************************************
954 * GetTextExtentExPointI [GDI32.@]
956 * Computes width and height of the array of glyph indices.
958 * PARAMS
959 * hdc [I] Handle of device context.
960 * indices [I] Glyph index array.
961 * count [I] Number of glyphs in array.
962 * max_ext [I] Maximum width in glyphs.
963 * nfit [O] Maximum number of characters.
964 * dxs [O] Partial string widths.
965 * size [O] Returned string size.
967 * RETURNS
968 * Success: TRUE
969 * Failure: FALSE
971 BOOL WINAPI GetTextExtentExPointI( HDC hdc, const WORD *indices, INT count, INT max_ext,
972 LPINT nfit, LPINT dxs, LPSIZE size )
974 BOOL ret = FALSE;
975 DC * dc = get_dc_ptr( hdc );
976 if (!dc) return FALSE;
978 if(dc->gdiFont) {
979 ret = WineEngGetTextExtentExPointI(dc->gdiFont, indices, count, max_ext, nfit, dxs, size);
980 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
981 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
982 size->cx += count * dc->charExtra;
984 else if(dc->funcs->pGetTextExtentExPoint) {
985 FIXME("calling GetTextExtentExPoint\n");
986 ret = dc->funcs->pGetTextExtentExPoint( dc->physDev, indices, count,
987 max_ext, nfit, dxs, size );
990 release_dc_ptr( dc );
992 TRACE("(%p %p %d %p): returning %d x %d\n",
993 hdc, indices, count, size, size->cx, size->cy );
994 return ret;
997 /***********************************************************************
998 * GetTextExtentPointI [GDI32.@]
1000 * Computes width and height of the array of glyph indices.
1002 * PARAMS
1003 * hdc [I] Handle of device context.
1004 * indices [I] Glyph index array.
1005 * count [I] Number of glyphs in array.
1006 * size [O] Returned string size.
1008 * RETURNS
1009 * Success: TRUE
1010 * Failure: FALSE
1012 BOOL WINAPI GetTextExtentPointI( HDC hdc, const WORD *indices, INT count, LPSIZE size )
1014 return GetTextExtentExPointI( hdc, indices, count, 0, NULL, NULL, size );
1018 /***********************************************************************
1019 * GetTextExtentPointA (GDI32.@)
1021 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
1022 LPSIZE size )
1024 TRACE("not bug compatible.\n");
1025 return GetTextExtentPoint32A( hdc, str, count, size );
1028 /***********************************************************************
1029 * GetTextExtentPointW (GDI32.@)
1031 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1032 LPSIZE size )
1034 TRACE("not bug compatible.\n");
1035 return GetTextExtentPoint32W( hdc, str, count, size );
1039 /***********************************************************************
1040 * GetTextExtentExPointA (GDI32.@)
1042 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1043 INT maxExt, LPINT lpnFit,
1044 LPINT alpDx, LPSIZE size )
1046 BOOL ret;
1047 INT wlen;
1048 INT *walpDx = NULL;
1049 LPWSTR p = NULL;
1051 if (alpDx &&
1052 NULL == (walpDx = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT))))
1053 return FALSE;
1055 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1056 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
1057 if (walpDx)
1059 INT n = lpnFit ? *lpnFit : wlen;
1060 INT i, j;
1061 for(i = 0, j = 0; i < n; i++, j++)
1063 alpDx[j] = walpDx[i];
1064 if (IsDBCSLeadByte(str[j])) alpDx[++j] = walpDx[i];
1067 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1068 HeapFree( GetProcessHeap(), 0, p );
1069 HeapFree( GetProcessHeap(), 0, walpDx );
1070 return ret;
1074 /***********************************************************************
1075 * GetTextExtentExPointW (GDI32.@)
1077 * Return the size of the string as it would be if it was output properly by
1078 * e.g. TextOut.
1080 * This should include
1081 * - Intercharacter spacing
1082 * - justification spacing (not yet done)
1083 * - kerning? see below
1085 * Kerning. Since kerning would be carried out by the rendering code it should
1086 * be done by the driver. However they don't support it yet. Also I am not
1087 * yet persuaded that (certainly under Win95) any kerning is actually done.
1089 * str: According to MSDN this should be null-terminated. That is not true; a
1090 * null will not terminate it early.
1091 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1092 * than count. I have seen it be either the size of the full string or
1093 * 1 less than the size of the full string. I have not seen it bear any
1094 * resemblance to the portion that would fit.
1095 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1096 * trailing intercharacter spacing and any trailing justification.
1098 * FIXME
1099 * Currently we do this by measuring each character etc. We should do it by
1100 * passing the request to the driver, perhaps by extending the
1101 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1102 * thinking about kerning issues and rounding issues in the justification.
1105 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1106 INT maxExt, LPINT lpnFit,
1107 LPINT alpDx, LPSIZE size )
1109 INT nFit = 0;
1110 LPINT dxs = NULL;
1111 DC *dc;
1112 BOOL ret = FALSE;
1113 TEXTMETRICW tm;
1115 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1117 dc = get_dc_ptr(hdc);
1118 if (! dc)
1119 return FALSE;
1121 GetTextMetricsW(hdc, &tm);
1123 /* If we need to calculate nFit, then we need the partial extents even if
1124 the user hasn't provided us with an array. */
1125 if (lpnFit)
1127 dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]);
1128 if (! dxs)
1130 release_dc_ptr(dc);
1131 SetLastError(ERROR_OUTOFMEMORY);
1132 return FALSE;
1135 else
1136 dxs = alpDx;
1138 if (dc->gdiFont)
1139 ret = WineEngGetTextExtentExPoint(dc->gdiFont, str, count,
1140 0, NULL, dxs, size);
1141 else if (dc->funcs->pGetTextExtentExPoint)
1142 ret = dc->funcs->pGetTextExtentExPoint(dc->physDev, str, count,
1143 0, NULL, dxs, size);
1145 /* Perform device size to world size transformations. */
1146 if (ret)
1148 INT extra = dc->charExtra,
1149 breakExtra = dc->breakExtra,
1150 breakRem = dc->breakRem,
1153 if (dxs)
1155 for (i = 0; i < count; ++i)
1157 dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
1158 dxs[i] += (i+1) * extra;
1159 if (count > 1 && (breakExtra || breakRem) && str[i] == tm.tmBreakChar)
1161 dxs[i] += breakExtra;
1162 if (breakRem > 0)
1164 breakRem--;
1165 dxs[i]++;
1168 if (dxs[i] <= maxExt)
1169 ++nFit;
1171 breakRem = dc->breakRem;
1173 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1174 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1176 if (!dxs && count > 1 && (breakExtra || breakRem))
1178 for (i = 0; i < count; i++)
1180 if (str[i] == tm.tmBreakChar)
1182 size->cx += breakExtra;
1183 if (breakRem > 0)
1185 breakRem--;
1186 (size->cx)++;
1193 if (lpnFit)
1194 *lpnFit = nFit;
1196 if (! alpDx)
1197 HeapFree(GetProcessHeap(), 0, dxs);
1199 release_dc_ptr( dc );
1201 TRACE("returning %d %d x %d\n",nFit,size->cx,size->cy);
1202 return ret;
1205 /***********************************************************************
1206 * GetTextMetricsA (GDI32.@)
1208 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1210 TEXTMETRICW tm32;
1212 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1213 FONT_TextMetricWToA( &tm32, metrics );
1214 return TRUE;
1217 /***********************************************************************
1218 * GetTextMetricsW (GDI32.@)
1220 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1222 BOOL ret = FALSE;
1223 DC * dc = get_dc_ptr( hdc );
1224 if (!dc) return FALSE;
1226 if (dc->gdiFont)
1227 ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1228 else if (dc->funcs->pGetTextMetrics)
1229 ret = dc->funcs->pGetTextMetrics( dc->physDev, metrics );
1231 if (ret)
1233 /* device layer returns values in device units
1234 * therefore we have to convert them to logical */
1236 metrics->tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1237 metrics->tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1239 #define WDPTOLP(x) ((x<0)? \
1240 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1241 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1242 #define HDPTOLP(y) ((y<0)? \
1243 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1244 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1246 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1247 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1248 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1249 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1250 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1251 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1252 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1253 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1254 ret = TRUE;
1255 #undef WDPTOLP
1256 #undef HDPTOLP
1257 TRACE("text metrics:\n"
1258 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1259 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1260 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1261 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1262 " PitchAndFamily = %02x\n"
1263 " --------------------\n"
1264 " InternalLeading = %i\n"
1265 " Ascent = %i\n"
1266 " Descent = %i\n"
1267 " Height = %i\n",
1268 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1269 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1270 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1271 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1272 metrics->tmPitchAndFamily,
1273 metrics->tmInternalLeading,
1274 metrics->tmAscent,
1275 metrics->tmDescent,
1276 metrics->tmHeight );
1278 release_dc_ptr( dc );
1279 return ret;
1283 /***********************************************************************
1284 * GetOutlineTextMetricsA (GDI32.@)
1285 * Gets metrics for TrueType fonts.
1287 * NOTES
1288 * If the supplied buffer isn't big enough Windows partially fills it up to
1289 * its given length and returns that length.
1291 * RETURNS
1292 * Success: Non-zero or size of required buffer
1293 * Failure: 0
1295 UINT WINAPI GetOutlineTextMetricsA(
1296 HDC hdc, /* [in] Handle of device context */
1297 UINT cbData, /* [in] Size of metric data array */
1298 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1300 char buf[512], *ptr;
1301 UINT ret, needed;
1302 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1303 OUTLINETEXTMETRICA *output = lpOTM;
1304 INT left, len;
1306 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1307 return 0;
1308 if(ret > sizeof(buf))
1309 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1310 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1312 needed = sizeof(OUTLINETEXTMETRICA);
1313 if(lpOTMW->otmpFamilyName)
1314 needed += WideCharToMultiByte(CP_ACP, 0,
1315 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1316 NULL, 0, NULL, NULL);
1317 if(lpOTMW->otmpFaceName)
1318 needed += WideCharToMultiByte(CP_ACP, 0,
1319 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1320 NULL, 0, NULL, NULL);
1321 if(lpOTMW->otmpStyleName)
1322 needed += WideCharToMultiByte(CP_ACP, 0,
1323 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1324 NULL, 0, NULL, NULL);
1325 if(lpOTMW->otmpFullName)
1326 needed += WideCharToMultiByte(CP_ACP, 0,
1327 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1328 NULL, 0, NULL, NULL);
1330 if(!lpOTM) {
1331 ret = needed;
1332 goto end;
1335 TRACE("needed = %d\n", needed);
1336 if(needed > cbData)
1337 /* Since the supplied buffer isn't big enough, we'll alloc one
1338 that is and memcpy the first cbData bytes into the lpOTM at
1339 the end. */
1340 output = HeapAlloc(GetProcessHeap(), 0, needed);
1342 ret = output->otmSize = min(needed, cbData);
1343 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1344 output->otmFiller = 0;
1345 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1346 output->otmfsSelection = lpOTMW->otmfsSelection;
1347 output->otmfsType = lpOTMW->otmfsType;
1348 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1349 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1350 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1351 output->otmEMSquare = lpOTMW->otmEMSquare;
1352 output->otmAscent = lpOTMW->otmAscent;
1353 output->otmDescent = lpOTMW->otmDescent;
1354 output->otmLineGap = lpOTMW->otmLineGap;
1355 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1356 output->otmsXHeight = lpOTMW->otmsXHeight;
1357 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1358 output->otmMacAscent = lpOTMW->otmMacAscent;
1359 output->otmMacDescent = lpOTMW->otmMacDescent;
1360 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1361 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1362 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1363 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1364 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1365 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1366 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1367 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1368 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1369 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1372 ptr = (char*)(output + 1);
1373 left = needed - sizeof(*output);
1375 if(lpOTMW->otmpFamilyName) {
1376 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1377 len = WideCharToMultiByte(CP_ACP, 0,
1378 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1379 ptr, left, NULL, NULL);
1380 left -= len;
1381 ptr += len;
1382 } else
1383 output->otmpFamilyName = 0;
1385 if(lpOTMW->otmpFaceName) {
1386 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1387 len = WideCharToMultiByte(CP_ACP, 0,
1388 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1389 ptr, left, NULL, NULL);
1390 left -= len;
1391 ptr += len;
1392 } else
1393 output->otmpFaceName = 0;
1395 if(lpOTMW->otmpStyleName) {
1396 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1397 len = WideCharToMultiByte(CP_ACP, 0,
1398 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1399 ptr, left, NULL, NULL);
1400 left -= len;
1401 ptr += len;
1402 } else
1403 output->otmpStyleName = 0;
1405 if(lpOTMW->otmpFullName) {
1406 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1407 len = WideCharToMultiByte(CP_ACP, 0,
1408 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1409 ptr, left, NULL, NULL);
1410 left -= len;
1411 } else
1412 output->otmpFullName = 0;
1414 assert(left == 0);
1416 if(output != lpOTM) {
1417 memcpy(lpOTM, output, cbData);
1418 HeapFree(GetProcessHeap(), 0, output);
1420 /* check if the string offsets really fit into the provided size */
1421 /* FIXME: should we check string length as well? */
1422 /* make sure that we don't read/write beyond the provided buffer */
1423 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(LPSTR))
1425 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1426 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1429 /* make sure that we don't read/write beyond the provided buffer */
1430 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(LPSTR))
1432 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1433 lpOTM->otmpFaceName = 0; /* doesn't fit */
1436 /* make sure that we don't read/write beyond the provided buffer */
1437 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(LPSTR))
1439 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1440 lpOTM->otmpStyleName = 0; /* doesn't fit */
1443 /* make sure that we don't read/write beyond the provided buffer */
1444 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(LPSTR))
1446 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1447 lpOTM->otmpFullName = 0; /* doesn't fit */
1451 end:
1452 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1453 HeapFree(GetProcessHeap(), 0, lpOTMW);
1455 return ret;
1459 /***********************************************************************
1460 * GetOutlineTextMetricsW [GDI32.@]
1462 UINT WINAPI GetOutlineTextMetricsW(
1463 HDC hdc, /* [in] Handle of device context */
1464 UINT cbData, /* [in] Size of metric data array */
1465 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1467 DC *dc = get_dc_ptr( hdc );
1468 OUTLINETEXTMETRICW *output = lpOTM;
1469 UINT ret;
1471 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1472 if(!dc) return 0;
1474 if(dc->gdiFont) {
1475 ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, output);
1476 if(lpOTM && ret) {
1477 if(ret > cbData) {
1478 output = HeapAlloc(GetProcessHeap(), 0, ret);
1479 WineEngGetOutlineTextMetrics(dc->gdiFont, ret, output);
1482 output->otmTextMetrics.tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1483 output->otmTextMetrics.tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1485 #define WDPTOLP(x) ((x<0)? \
1486 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1487 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1488 #define HDPTOLP(y) ((y<0)? \
1489 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1490 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1492 output->otmTextMetrics.tmHeight = HDPTOLP(output->otmTextMetrics.tmHeight);
1493 output->otmTextMetrics.tmAscent = HDPTOLP(output->otmTextMetrics.tmAscent);
1494 output->otmTextMetrics.tmDescent = HDPTOLP(output->otmTextMetrics.tmDescent);
1495 output->otmTextMetrics.tmInternalLeading = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1496 output->otmTextMetrics.tmExternalLeading = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1497 output->otmTextMetrics.tmAveCharWidth = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1498 output->otmTextMetrics.tmMaxCharWidth = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1499 output->otmTextMetrics.tmOverhang = WDPTOLP(output->otmTextMetrics.tmOverhang);
1500 output->otmAscent = HDPTOLP(output->otmAscent);
1501 output->otmDescent = HDPTOLP(output->otmDescent);
1502 output->otmLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmLineGap));
1503 output->otmsCapEmHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsCapEmHeight));
1504 output->otmsXHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsXHeight));
1505 output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1506 output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1507 output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1508 output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1509 output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1510 output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1511 output->otmMacLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmMacLineGap));
1512 output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1513 output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1514 output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1515 output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1516 output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1517 output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1518 output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1519 output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1520 output->otmsStrikeoutSize = abs(INTERNAL_YDSTOWS(dc,output->otmsStrikeoutSize));
1521 output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1522 output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1523 output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1524 #undef WDPTOLP
1525 #undef HDPTOLP
1526 if(output != lpOTM) {
1527 memcpy(lpOTM, output, cbData);
1528 HeapFree(GetProcessHeap(), 0, output);
1529 ret = cbData;
1534 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1535 but really this should just be a return 0. */
1537 ret = sizeof(*lpOTM);
1538 if (lpOTM) {
1539 if(cbData < ret)
1540 ret = 0;
1541 else {
1542 memset(lpOTM, 0, ret);
1543 lpOTM->otmSize = sizeof(*lpOTM);
1544 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1546 Further fill of the structure not implemented,
1547 Needs real values for the structure members
1552 release_dc_ptr(dc);
1553 return ret;
1557 /***********************************************************************
1558 * GetCharWidthW (GDI32.@)
1559 * GetCharWidth32W (GDI32.@)
1561 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1562 LPINT buffer )
1564 UINT i;
1565 BOOL ret = FALSE;
1566 DC * dc = get_dc_ptr( hdc );
1567 if (!dc) return FALSE;
1569 if (dc->gdiFont)
1570 ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1571 else if (dc->funcs->pGetCharWidth)
1572 ret = dc->funcs->pGetCharWidth( dc->physDev, firstChar, lastChar, buffer);
1574 if (ret)
1576 /* convert device units to logical */
1577 for( i = firstChar; i <= lastChar; i++, buffer++ )
1578 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1579 ret = TRUE;
1581 release_dc_ptr( dc );
1582 return ret;
1586 /***********************************************************************
1587 * GetCharWidthA (GDI32.@)
1588 * GetCharWidth32A (GDI32.@)
1590 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1591 LPINT buffer )
1593 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1594 LPSTR str;
1595 LPWSTR wstr;
1596 BOOL ret = TRUE;
1598 if(count <= 0) return FALSE;
1600 str = HeapAlloc(GetProcessHeap(), 0, count);
1601 for(i = 0; i < count; i++)
1602 str[i] = (BYTE)(firstChar + i);
1604 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1606 for(i = 0; i < wlen; i++)
1608 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1610 ret = FALSE;
1611 break;
1613 buffer++;
1616 HeapFree(GetProcessHeap(), 0, str);
1617 HeapFree(GetProcessHeap(), 0, wstr);
1619 return ret;
1623 /***********************************************************************
1624 * ExtTextOutA (GDI32.@)
1626 * See ExtTextOutW.
1628 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1629 const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1631 INT wlen;
1632 UINT codepage;
1633 LPWSTR p;
1634 BOOL ret;
1635 LPINT lpDxW = NULL;
1637 if (flags & ETO_GLYPH_INDEX)
1638 return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
1640 p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
1642 if (lpDx) {
1643 unsigned int i = 0, j = 0;
1645 /* allocate enough for a ETO_PDY */
1646 lpDxW = HeapAlloc( GetProcessHeap(), 0, 2*wlen*sizeof(INT));
1647 while(i < count) {
1648 if(IsDBCSLeadByteEx(codepage, str[i]))
1650 if(flags & ETO_PDY)
1652 lpDxW[j++] = lpDx[i * 2] + lpDx[(i + 1) * 2];
1653 lpDxW[j++] = lpDx[i * 2 + 1] + lpDx[(i + 1) * 2 + 1];
1655 else
1656 lpDxW[j++] = lpDx[i] + lpDx[i + 1];
1657 i = i + 2;
1659 else
1661 if(flags & ETO_PDY)
1663 lpDxW[j++] = lpDx[i * 2];
1664 lpDxW[j++] = lpDx[i * 2 + 1];
1666 else
1667 lpDxW[j++] = lpDx[i];
1668 i = i + 1;
1673 ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1675 HeapFree( GetProcessHeap(), 0, p );
1676 HeapFree( GetProcessHeap(), 0, lpDxW );
1677 return ret;
1681 /***********************************************************************
1682 * ExtTextOutW (GDI32.@)
1684 * Draws text using the currently selected font, background color, and text color.
1687 * PARAMS
1688 * x,y [I] coordinates of string
1689 * flags [I]
1690 * ETO_GRAYED - undocumented on MSDN
1691 * ETO_OPAQUE - use background color for fill the rectangle
1692 * ETO_CLIPPED - clipping text to the rectangle
1693 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1694 * than encoded characters. Implies ETO_IGNORELANGUAGE
1695 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1696 * Affects BiDi ordering
1697 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1698 * ETO_PDY - unimplemented
1699 * ETO_NUMERICSLATIN - unimplemented always assumed -
1700 * do not translate numbers into locale representations
1701 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1702 * lprect [I] dimensions for clipping or/and opaquing
1703 * str [I] text string
1704 * count [I] number of symbols in string
1705 * lpDx [I] optional parameter with distance between drawing characters
1707 * RETURNS
1708 * Success: TRUE
1709 * Failure: FALSE
1711 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1712 const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1714 BOOL ret = FALSE;
1715 LPWSTR reordered_str = (LPWSTR)str;
1716 WORD *glyphs = NULL;
1717 UINT align = GetTextAlign( hdc );
1718 DWORD layout = GetLayout( hdc );
1719 POINT pt;
1720 TEXTMETRICW tm;
1721 LOGFONTW lf;
1722 double cosEsc, sinEsc;
1723 INT char_extra;
1724 SIZE sz;
1725 RECT rc;
1726 BOOL done_extents = FALSE;
1727 POINT *deltas = NULL, width = {0, 0};
1728 DWORD type;
1729 DC * dc = get_dc_ptr( hdc );
1730 INT breakRem;
1731 static int quietfixme = 0;
1733 if (!dc) return FALSE;
1735 breakRem = dc->breakRem;
1737 if (quietfixme == 0 && flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN))
1739 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN unimplemented\n");
1740 quietfixme = 1;
1742 if (!dc->funcs->pExtTextOut && !PATH_IsPathOpen(dc->path))
1744 release_dc_ptr( dc );
1745 return ret;
1748 update_dc( dc );
1749 type = GetObjectType(hdc);
1750 if(type == OBJ_METADC || type == OBJ_ENHMETADC)
1752 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, flags, lprect, str, count, lpDx);
1753 release_dc_ptr( dc );
1754 return ret;
1757 if (!lprect)
1758 flags &= ~ETO_CLIPPED;
1760 if (flags & ETO_RTLREADING) align |= TA_RTLREADING;
1761 if (layout & LAYOUT_RTL)
1763 if ((align & TA_CENTER) != TA_CENTER) align ^= TA_RIGHT;
1764 align ^= TA_RTLREADING;
1767 if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && count > 0 )
1769 INT cGlyphs;
1770 reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1772 BIDI_Reorder( hdc, str, count, GCP_REORDER,
1773 (align & TA_RTLREADING) ? WINE_GCPW_FORCE_RTL : WINE_GCPW_FORCE_LTR,
1774 reordered_str, count, NULL, &glyphs, &cGlyphs);
1776 flags |= ETO_IGNORELANGUAGE;
1777 if (glyphs)
1779 flags |= ETO_GLYPH_INDEX;
1780 if (cGlyphs != count)
1781 count = cGlyphs;
1784 else if(flags & ETO_GLYPH_INDEX)
1785 glyphs = reordered_str;
1787 TRACE("%p, %d, %d, %08x, %s, %s, %d, %p)\n", hdc, x, y, flags,
1788 wine_dbgstr_rect(lprect), debugstr_wn(str, count), count, lpDx);
1789 TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
1791 if(align & TA_UPDATECP)
1793 GetCurrentPositionEx( hdc, &pt );
1794 x = pt.x;
1795 y = pt.y;
1798 GetTextMetricsW(hdc, &tm);
1799 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1801 if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
1802 lf.lfEscapement = 0;
1804 if(lf.lfEscapement != 0)
1806 cosEsc = cos(lf.lfEscapement * M_PI / 1800);
1807 sinEsc = sin(lf.lfEscapement * M_PI / 1800);
1809 else
1811 cosEsc = 1;
1812 sinEsc = 0;
1815 if(flags & (ETO_CLIPPED | ETO_OPAQUE))
1817 if(!lprect)
1819 if(flags & ETO_GLYPH_INDEX)
1820 GetTextExtentPointI(hdc, glyphs, count, &sz);
1821 else
1822 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1824 done_extents = TRUE;
1825 rc.left = x;
1826 rc.top = y;
1827 rc.right = x + sz.cx;
1828 rc.bottom = y + sz.cy;
1830 else
1832 rc = *lprect;
1835 LPtoDP(hdc, (POINT*)&rc, 2);
1837 if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
1838 if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
1841 if ((flags & ETO_OPAQUE) && !PATH_IsPathOpen(dc->path))
1842 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1844 if(count == 0)
1846 ret = TRUE;
1847 goto done;
1850 pt.x = x;
1851 pt.y = y;
1852 LPtoDP(hdc, &pt, 1);
1853 x = pt.x;
1854 y = pt.y;
1856 char_extra = GetTextCharacterExtra(hdc);
1857 if(char_extra || dc->breakExtra || breakRem || lpDx || lf.lfEscapement != 0)
1859 UINT i;
1860 SIZE tmpsz;
1861 POINT total = {0, 0}, desired[2];
1863 deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
1864 for(i = 0; i < count; i++)
1866 if(lpDx)
1868 if(flags & ETO_PDY)
1870 deltas[i].x = lpDx[i * 2] + char_extra;
1871 deltas[i].y = -lpDx[i * 2 + 1];
1873 else
1875 deltas[i].x = lpDx[i] + char_extra;
1876 deltas[i].y = 0;
1880 else
1882 if(flags & ETO_GLYPH_INDEX)
1883 GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
1884 else
1885 GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
1887 deltas[i].x = tmpsz.cx;
1888 deltas[i].y = 0;
1891 if (!(flags & ETO_GLYPH_INDEX) && (dc->breakExtra || breakRem) && reordered_str[i] == tm.tmBreakChar)
1893 deltas[i].x = deltas[i].x + dc->breakExtra;
1894 if (breakRem > 0)
1896 breakRem--;
1897 deltas[i].x++;
1900 total.x += deltas[i].x;
1901 total.y += deltas[i].y;
1903 desired[0].x = desired[0].y = 0;
1905 desired[1].x = cosEsc * total.x + sinEsc * total.y;
1906 desired[1].y = -sinEsc * total.x + cosEsc * total.y;
1908 LPtoDP(hdc, desired, 2);
1909 desired[1].x -= desired[0].x;
1910 desired[1].y -= desired[0].y;
1911 if (layout & LAYOUT_RTL) desired[1].x = -desired[1].x;
1913 deltas[i].x = desired[1].x - width.x;
1914 deltas[i].y = desired[1].y - width.y;
1916 width = desired[1];
1918 flags |= ETO_PDY;
1920 else
1922 if(!done_extents)
1924 if(flags & ETO_GLYPH_INDEX)
1925 GetTextExtentPointI(hdc, glyphs, count, &sz);
1926 else
1927 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1928 done_extents = TRUE;
1930 width.x = abs(INTERNAL_XWSTODS(dc, sz.cx));
1931 width.y = 0;
1934 tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
1935 tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
1936 switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
1938 case TA_LEFT:
1939 if (align & TA_UPDATECP)
1941 pt.x = x + width.x;
1942 pt.y = y + width.y;
1943 DPtoLP(hdc, &pt, 1);
1944 MoveToEx(hdc, pt.x, pt.y, NULL);
1946 break;
1948 case TA_CENTER:
1949 x -= width.x / 2;
1950 y -= width.y / 2;
1951 break;
1953 case TA_RIGHT:
1954 x -= width.x;
1955 y -= width.y;
1956 if (align & TA_UPDATECP)
1958 pt.x = x;
1959 pt.y = y;
1960 DPtoLP(hdc, &pt, 1);
1961 MoveToEx(hdc, pt.x, pt.y, NULL);
1963 break;
1966 switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
1968 case TA_TOP:
1969 y += tm.tmAscent * cosEsc;
1970 x += tm.tmAscent * sinEsc;
1971 break;
1973 case TA_BOTTOM:
1974 y -= tm.tmDescent * cosEsc;
1975 x -= tm.tmDescent * sinEsc;
1976 break;
1978 case TA_BASELINE:
1979 break;
1982 if (GetBkMode(hdc) != TRANSPARENT && !PATH_IsPathOpen(dc->path))
1984 if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
1986 if(!(flags & ETO_OPAQUE) || x < rc.left || x + width.x >= rc.right ||
1987 y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
1989 RECT rc;
1990 rc.left = x;
1991 rc.right = x + width.x;
1992 rc.top = y - tm.tmAscent;
1993 rc.bottom = y + tm.tmDescent;
1994 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1999 if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
2001 HFONT orig_font = dc->hFont, cur_font;
2002 UINT glyph;
2003 INT span = 0;
2004 POINT *offsets = NULL;
2005 unsigned int i;
2007 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2008 for(i = 0; i < count; i++)
2010 WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
2011 if(cur_font != dc->hFont)
2013 if(!offsets)
2015 unsigned int j;
2016 offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
2017 offsets[0].x = offsets[0].y = 0;
2019 if(!deltas)
2021 SIZE tmpsz;
2022 for(j = 1; j < count; j++)
2024 GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
2025 offsets[j].x = offsets[j - 1].x + abs(INTERNAL_XWSTODS(dc, tmpsz.cx));
2026 offsets[j].y = 0;
2029 else
2031 for(j = 1; j < count; j++)
2033 offsets[j].x = offsets[j - 1].x + deltas[j].x;
2034 offsets[j].y = offsets[j - 1].y + deltas[j].y;
2038 if(span)
2040 if (PATH_IsPathOpen(dc->path))
2041 ret = PATH_ExtTextOut(dc, x + offsets[i - span].x, y + offsets[i - span].y,
2042 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2043 glyphs, span, deltas ? (INT*)(deltas + (i - span)) : NULL);
2044 else
2045 dc->funcs->pExtTextOut(dc->physDev, x + offsets[i - span].x, y + offsets[i - span].y,
2046 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2047 glyphs, span, deltas ? (INT*)(deltas + (i - span)) : NULL);
2048 span = 0;
2050 SelectObject(hdc, cur_font);
2052 glyphs[span++] = glyph;
2054 if(i == count - 1)
2056 if (PATH_IsPathOpen(dc->path))
2057 ret = PATH_ExtTextOut(dc, x + (offsets ? offsets[count - span].x : 0),
2058 y + (offsets ? offsets[count - span].y : 0),
2059 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2060 glyphs, span, deltas ? (INT*)(deltas + (count - span)) : NULL);
2061 else
2062 ret = dc->funcs->pExtTextOut(dc->physDev, x + (offsets ? offsets[count - span].x : 0),
2063 y + (offsets ? offsets[count - span].y : 0),
2064 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2065 glyphs, span, deltas ? (INT*)(deltas + (count - span)) : NULL);
2066 SelectObject(hdc, orig_font);
2067 HeapFree(GetProcessHeap(), 0, offsets);
2071 else
2073 if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
2075 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2076 GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
2077 flags |= ETO_GLYPH_INDEX;
2080 if (PATH_IsPathOpen(dc->path))
2081 ret = PATH_ExtTextOut(dc, x, y, (flags & ~ETO_OPAQUE), &rc,
2082 glyphs ? glyphs : reordered_str, count, (INT*)deltas);
2083 else
2084 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, (flags & ~ETO_OPAQUE), &rc,
2085 glyphs ? glyphs : reordered_str, count, (INT*)deltas);
2088 done:
2089 HeapFree(GetProcessHeap(), 0, deltas);
2090 if(glyphs != reordered_str)
2091 HeapFree(GetProcessHeap(), 0, glyphs);
2092 if(reordered_str != str)
2093 HeapFree(GetProcessHeap(), 0, reordered_str);
2095 release_dc_ptr( dc );
2097 if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2099 int underlinePos, strikeoutPos;
2100 int underlineWidth, strikeoutWidth;
2101 UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2102 OUTLINETEXTMETRICW* otm = NULL;
2104 if(!size)
2106 underlinePos = 0;
2107 underlineWidth = tm.tmAscent / 20 + 1;
2108 strikeoutPos = tm.tmAscent / 2;
2109 strikeoutWidth = underlineWidth;
2111 else
2113 otm = HeapAlloc(GetProcessHeap(), 0, size);
2114 GetOutlineTextMetricsW(hdc, size, otm);
2115 underlinePos = otm->otmsUnderscorePosition;
2116 underlineWidth = otm->otmsUnderscoreSize;
2117 strikeoutPos = otm->otmsStrikeoutPosition;
2118 strikeoutWidth = otm->otmsStrikeoutSize;
2119 HeapFree(GetProcessHeap(), 0, otm);
2122 if (PATH_IsPathOpen(dc->path))
2124 POINT pts[5];
2125 HPEN hpen;
2126 HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2128 hbrush = SelectObject(hdc, hbrush);
2129 hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2131 if (lf.lfUnderline)
2133 pts[0].x = x - underlinePos * sinEsc;
2134 pts[0].y = y - underlinePos * cosEsc;
2135 pts[1].x = x + width.x - underlinePos * sinEsc;
2136 pts[1].y = y + width.y - underlinePos * cosEsc;
2137 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2138 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2139 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2140 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2141 pts[4].x = pts[0].x;
2142 pts[4].y = pts[0].y;
2143 DPtoLP(hdc, pts, 5);
2144 Polygon(hdc, pts, 5);
2147 if (lf.lfStrikeOut)
2149 pts[0].x = x - strikeoutPos * sinEsc;
2150 pts[0].y = y - strikeoutPos * cosEsc;
2151 pts[1].x = x + width.x - strikeoutPos * sinEsc;
2152 pts[1].y = y + width.y - strikeoutPos * cosEsc;
2153 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2154 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2155 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2156 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2157 pts[4].x = pts[0].x;
2158 pts[4].y = pts[0].y;
2159 DPtoLP(hdc, pts, 5);
2160 Polygon(hdc, pts, 5);
2163 SelectObject(hdc, hpen);
2164 hbrush = SelectObject(hdc, hbrush);
2165 DeleteObject(hbrush);
2167 else
2169 POINT pts[2], oldpt;
2170 HPEN hpen;
2172 if (lf.lfUnderline)
2174 hpen = CreatePen(PS_SOLID, underlineWidth, GetTextColor(hdc));
2175 hpen = SelectObject(hdc, hpen);
2176 pts[0].x = x;
2177 pts[0].y = y;
2178 pts[1].x = x + width.x;
2179 pts[1].y = y + width.y;
2180 DPtoLP(hdc, pts, 2);
2181 MoveToEx(hdc, pts[0].x - underlinePos * sinEsc, pts[0].y - underlinePos * cosEsc, &oldpt);
2182 LineTo(hdc, pts[1].x - underlinePos * sinEsc, pts[1].y - underlinePos * cosEsc);
2183 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2184 DeleteObject(SelectObject(hdc, hpen));
2187 if (lf.lfStrikeOut)
2189 hpen = CreatePen(PS_SOLID, strikeoutWidth, GetTextColor(hdc));
2190 hpen = SelectObject(hdc, hpen);
2191 pts[0].x = x;
2192 pts[0].y = y;
2193 pts[1].x = x + width.x;
2194 pts[1].y = y + width.y;
2195 DPtoLP(hdc, pts, 2);
2196 MoveToEx(hdc, pts[0].x - strikeoutPos * sinEsc, pts[0].y - strikeoutPos * cosEsc, &oldpt);
2197 LineTo(hdc, pts[1].x - strikeoutPos * sinEsc, pts[1].y - strikeoutPos * cosEsc);
2198 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2199 DeleteObject(SelectObject(hdc, hpen));
2204 return ret;
2208 /***********************************************************************
2209 * TextOutA (GDI32.@)
2211 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2213 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2217 /***********************************************************************
2218 * TextOutW (GDI32.@)
2220 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2222 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2226 /***********************************************************************
2227 * PolyTextOutA (GDI32.@)
2229 * See PolyTextOutW.
2231 BOOL WINAPI PolyTextOutA( HDC hdc, const POLYTEXTA *pptxt, INT cStrings )
2233 for (; cStrings>0; cStrings--, pptxt++)
2234 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2235 return FALSE;
2236 return TRUE;
2241 /***********************************************************************
2242 * PolyTextOutW (GDI32.@)
2244 * Draw several Strings
2246 * RETURNS
2247 * TRUE: Success.
2248 * FALSE: Failure.
2250 BOOL WINAPI PolyTextOutW( HDC hdc, const POLYTEXTW *pptxt, INT cStrings )
2252 for (; cStrings>0; cStrings--, pptxt++)
2253 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2254 return FALSE;
2255 return TRUE;
2259 /* FIXME: all following APIs ******************************************/
2262 /***********************************************************************
2263 * SetMapperFlags (GDI32.@)
2265 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
2267 DC *dc = get_dc_ptr( hDC );
2268 DWORD ret = 0;
2269 if(!dc) return 0;
2270 if(dc->funcs->pSetMapperFlags)
2272 ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
2273 /* FIXME: ret is just a success flag, we should return a proper value */
2275 else
2276 FIXME("(%p, 0x%08x): stub - harmless\n", hDC, dwFlag);
2277 release_dc_ptr( dc );
2278 return ret;
2281 /***********************************************************************
2282 * GetAspectRatioFilterEx (GDI32.@)
2284 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2286 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2287 return FALSE;
2291 /***********************************************************************
2292 * GetCharABCWidthsA (GDI32.@)
2294 * See GetCharABCWidthsW.
2296 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2297 LPABC abc )
2299 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
2300 LPSTR str;
2301 LPWSTR wstr;
2302 BOOL ret = TRUE;
2304 if(count <= 0) return FALSE;
2306 str = HeapAlloc(GetProcessHeap(), 0, count);
2307 for(i = 0; i < count; i++)
2308 str[i] = (BYTE)(firstChar + i);
2310 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
2312 for(i = 0; i < wlen; i++)
2314 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2316 ret = FALSE;
2317 break;
2319 abc++;
2322 HeapFree(GetProcessHeap(), 0, str);
2323 HeapFree(GetProcessHeap(), 0, wstr);
2325 return ret;
2329 /******************************************************************************
2330 * GetCharABCWidthsW [GDI32.@]
2332 * Retrieves widths of characters in range.
2334 * PARAMS
2335 * hdc [I] Handle of device context
2336 * firstChar [I] First character in range to query
2337 * lastChar [I] Last character in range to query
2338 * abc [O] Address of character-width structure
2340 * NOTES
2341 * Only works with TrueType fonts
2343 * RETURNS
2344 * Success: TRUE
2345 * Failure: FALSE
2347 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2348 LPABC abc )
2350 DC *dc = get_dc_ptr(hdc);
2351 unsigned int i;
2352 BOOL ret = FALSE;
2354 if (!dc) return FALSE;
2356 if (!abc)
2358 release_dc_ptr( dc );
2359 return FALSE;
2362 if(dc->gdiFont)
2363 ret = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
2364 else
2365 FIXME(": stub\n");
2367 if (ret)
2369 /* convert device units to logical */
2370 for( i = firstChar; i <= lastChar; i++, abc++ ) {
2371 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2372 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2373 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2375 ret = TRUE;
2378 release_dc_ptr( dc );
2379 return ret;
2383 /******************************************************************************
2384 * GetCharABCWidthsI [GDI32.@]
2386 * Retrieves widths of characters in range.
2388 * PARAMS
2389 * hdc [I] Handle of device context
2390 * firstChar [I] First glyphs in range to query
2391 * count [I] Last glyphs in range to query
2392 * pgi [i] Array of glyphs to query
2393 * abc [O] Address of character-width structure
2395 * NOTES
2396 * Only works with TrueType fonts
2398 * RETURNS
2399 * Success: TRUE
2400 * Failure: FALSE
2402 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2403 LPWORD pgi, LPABC abc)
2405 DC *dc = get_dc_ptr(hdc);
2406 unsigned int i;
2407 BOOL ret = FALSE;
2409 if (!dc) return FALSE;
2411 if (!abc)
2413 release_dc_ptr( dc );
2414 return FALSE;
2417 if(dc->gdiFont)
2418 ret = WineEngGetCharABCWidthsI( dc->gdiFont, firstChar, count, pgi, abc );
2419 else
2420 FIXME(": stub\n");
2422 if (ret)
2424 /* convert device units to logical */
2425 for( i = 0; i < count; i++, abc++ ) {
2426 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2427 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2428 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2430 ret = TRUE;
2433 release_dc_ptr( dc );
2434 return ret;
2438 /***********************************************************************
2439 * GetGlyphOutlineA (GDI32.@)
2441 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2442 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2443 LPVOID lpBuffer, const MAT2 *lpmat2 )
2445 LPWSTR p = NULL;
2446 DWORD ret;
2447 UINT c;
2449 if (!lpmat2) return GDI_ERROR;
2451 if(!(fuFormat & GGO_GLYPH_INDEX)) {
2452 int len;
2453 char mbchs[2];
2454 if(uChar > 0xff) { /* but, 2 bytes character only */
2455 len = 2;
2456 mbchs[0] = (uChar & 0xff00) >> 8;
2457 mbchs[1] = (uChar & 0xff);
2458 } else {
2459 len = 1;
2460 mbchs[0] = (uChar & 0xff);
2462 p = FONT_mbtowc(hdc, mbchs, len, NULL, NULL);
2463 c = p[0];
2464 } else
2465 c = uChar;
2466 ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
2467 lpmat2);
2468 HeapFree(GetProcessHeap(), 0, p);
2469 return ret;
2472 /***********************************************************************
2473 * GetGlyphOutlineW (GDI32.@)
2475 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2476 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2477 LPVOID lpBuffer, const MAT2 *lpmat2 )
2479 DC *dc;
2480 DWORD ret;
2482 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2483 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2485 if (!lpmat2) return GDI_ERROR;
2487 dc = get_dc_ptr(hdc);
2488 if(!dc) return GDI_ERROR;
2490 if(dc->gdiFont)
2491 ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
2492 cbBuffer, lpBuffer, lpmat2);
2493 else
2494 ret = GDI_ERROR;
2496 release_dc_ptr( dc );
2497 return ret;
2501 /***********************************************************************
2502 * CreateScalableFontResourceA (GDI32.@)
2504 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2505 LPCSTR lpszResourceFile,
2506 LPCSTR lpszFontFile,
2507 LPCSTR lpszCurrentPath )
2509 LPWSTR lpszResourceFileW = NULL;
2510 LPWSTR lpszFontFileW = NULL;
2511 LPWSTR lpszCurrentPathW = NULL;
2512 int len;
2513 BOOL ret;
2515 if (lpszResourceFile)
2517 len = MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, NULL, 0);
2518 lpszResourceFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2519 MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, lpszResourceFileW, len);
2522 if (lpszFontFile)
2524 len = MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, NULL, 0);
2525 lpszFontFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2526 MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, lpszFontFileW, len);
2529 if (lpszCurrentPath)
2531 len = MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, NULL, 0);
2532 lpszCurrentPathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2533 MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, lpszCurrentPathW, len);
2536 ret = CreateScalableFontResourceW(fHidden, lpszResourceFileW,
2537 lpszFontFileW, lpszCurrentPathW);
2539 HeapFree(GetProcessHeap(), 0, lpszResourceFileW);
2540 HeapFree(GetProcessHeap(), 0, lpszFontFileW);
2541 HeapFree(GetProcessHeap(), 0, lpszCurrentPathW);
2543 return ret;
2546 /***********************************************************************
2547 * CreateScalableFontResourceW (GDI32.@)
2549 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2550 LPCWSTR lpszResourceFile,
2551 LPCWSTR lpszFontFile,
2552 LPCWSTR lpszCurrentPath )
2554 HANDLE f;
2555 FIXME("(%d,%s,%s,%s): stub\n",
2556 fHidden, debugstr_w(lpszResourceFile), debugstr_w(lpszFontFile),
2557 debugstr_w(lpszCurrentPath) );
2559 /* fHidden=1 - only visible for the calling app, read-only, not
2560 * enumerated with EnumFonts/EnumFontFamilies
2561 * lpszCurrentPath can be NULL
2564 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2565 if ((f = CreateFileW(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2566 CloseHandle(f);
2567 SetLastError(ERROR_FILE_EXISTS);
2568 return FALSE;
2570 return FALSE; /* create failed */
2573 /*************************************************************************
2574 * GetKerningPairsA (GDI32.@)
2576 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2577 LPKERNINGPAIR kern_pairA )
2579 UINT cp;
2580 CPINFO cpi;
2581 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2582 KERNINGPAIR *kern_pairW;
2584 if (!cPairs && kern_pairA)
2586 SetLastError(ERROR_INVALID_PARAMETER);
2587 return 0;
2590 cp = GdiGetCodePage(hDC);
2592 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2593 * to fail on an invalid character for CP_SYMBOL.
2595 cpi.DefaultChar[0] = 0;
2596 if (cp != CP_SYMBOL && !GetCPInfo(cp, &cpi))
2598 FIXME("Can't find codepage %u info\n", cp);
2599 return 0;
2602 total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2603 if (!total_kern_pairs) return 0;
2605 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2606 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2608 for (i = 0; i < total_kern_pairs; i++)
2610 char first, second;
2612 if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2613 continue;
2615 if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2616 continue;
2618 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2619 continue;
2621 if (kern_pairA)
2623 if (kern_pairs_copied >= cPairs) break;
2625 kern_pairA->wFirst = (BYTE)first;
2626 kern_pairA->wSecond = (BYTE)second;
2627 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2628 kern_pairA++;
2630 kern_pairs_copied++;
2633 HeapFree(GetProcessHeap(), 0, kern_pairW);
2635 return kern_pairs_copied;
2638 /*************************************************************************
2639 * GetKerningPairsW (GDI32.@)
2641 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2642 LPKERNINGPAIR lpKerningPairs )
2644 DC *dc;
2645 DWORD ret = 0;
2647 TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2649 if (!cPairs && lpKerningPairs)
2651 SetLastError(ERROR_INVALID_PARAMETER);
2652 return 0;
2655 dc = get_dc_ptr(hDC);
2656 if (!dc) return 0;
2658 if (dc->gdiFont)
2659 ret = WineEngGetKerningPairs(dc->gdiFont, cPairs, lpKerningPairs);
2661 release_dc_ptr( dc );
2662 return ret;
2665 /*************************************************************************
2666 * TranslateCharsetInfo [GDI32.@]
2668 * Fills a CHARSETINFO structure for a character set, code page, or
2669 * font. This allows making the correspondence between different labels
2670 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2671 * of the same encoding.
2673 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2674 * only one codepage should be set in *lpSrc.
2676 * RETURNS
2677 * TRUE on success, FALSE on failure.
2680 BOOL WINAPI TranslateCharsetInfo(
2681 LPDWORD lpSrc, /* [in]
2682 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2683 if flags == TCI_SRCCHARSET: a character set value
2684 if flags == TCI_SRCCODEPAGE: a code page value
2686 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2687 DWORD flags /* [in] determines interpretation of lpSrc */)
2689 int index = 0;
2690 switch (flags) {
2691 case TCI_SRCFONTSIG:
2692 while (index < MAXTCIINDEX && !(*lpSrc>>index & 0x0001)) index++;
2693 break;
2694 case TCI_SRCCODEPAGE:
2695 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciACP) index++;
2696 break;
2697 case TCI_SRCCHARSET:
2698 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciCharset) index++;
2699 break;
2700 default:
2701 return FALSE;
2703 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2704 *lpCs = FONT_tci[index];
2705 return TRUE;
2708 /*************************************************************************
2709 * GetFontLanguageInfo (GDI32.@)
2711 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2713 FONTSIGNATURE fontsig;
2714 static const DWORD GCP_DBCS_MASK=0x003F0000,
2715 GCP_DIACRITIC_MASK=0x00000000,
2716 FLI_GLYPHS_MASK=0x00000000,
2717 GCP_GLYPHSHAPE_MASK=0x00000040,
2718 GCP_KASHIDA_MASK=0x00000000,
2719 GCP_LIGATE_MASK=0x00000000,
2720 GCP_USEKERNING_MASK=0x00000000,
2721 GCP_REORDER_MASK=0x00000060;
2723 DWORD result=0;
2725 GetTextCharsetInfo( hdc, &fontsig, 0 );
2726 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2728 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2729 result|=GCP_DBCS;
2731 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2732 result|=GCP_DIACRITIC;
2734 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2735 result|=FLI_GLYPHS;
2737 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2738 result|=GCP_GLYPHSHAPE;
2740 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2741 result|=GCP_KASHIDA;
2743 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2744 result|=GCP_LIGATE;
2746 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2747 result|=GCP_USEKERNING;
2749 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2750 if( GetTextAlign( hdc) & TA_RTLREADING )
2751 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2752 result|=GCP_REORDER;
2754 return result;
2758 /*************************************************************************
2759 * GetFontData [GDI32.@]
2761 * Retrieve data for TrueType font.
2763 * RETURNS
2765 * success: Number of bytes returned
2766 * failure: GDI_ERROR
2768 * NOTES
2770 * Calls SetLastError()
2773 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2774 LPVOID buffer, DWORD length)
2776 DC *dc = get_dc_ptr(hdc);
2777 DWORD ret = GDI_ERROR;
2779 if(!dc) return GDI_ERROR;
2781 if(dc->gdiFont)
2782 ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2784 release_dc_ptr( dc );
2785 return ret;
2788 /*************************************************************************
2789 * GetGlyphIndicesA [GDI32.@]
2791 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2792 LPWORD pgi, DWORD flags)
2794 DWORD ret;
2795 WCHAR *lpstrW;
2796 INT countW;
2798 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2799 hdc, debugstr_an(lpstr, count), count, pgi, flags);
2801 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2802 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2803 HeapFree(GetProcessHeap(), 0, lpstrW);
2805 return ret;
2808 /*************************************************************************
2809 * GetGlyphIndicesW [GDI32.@]
2811 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2812 LPWORD pgi, DWORD flags)
2814 DC *dc = get_dc_ptr(hdc);
2815 DWORD ret = GDI_ERROR;
2817 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2818 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2820 if(!dc) return GDI_ERROR;
2822 if(dc->gdiFont)
2823 ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2825 release_dc_ptr( dc );
2826 return ret;
2829 /*************************************************************************
2830 * GetCharacterPlacementA [GDI32.@]
2832 * See GetCharacterPlacementW.
2834 * NOTES:
2835 * the web browser control of ie4 calls this with dwFlags=0
2837 DWORD WINAPI
2838 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2839 INT nMaxExtent, GCP_RESULTSA *lpResults,
2840 DWORD dwFlags)
2842 WCHAR *lpStringW;
2843 INT uCountW;
2844 GCP_RESULTSW resultsW;
2845 DWORD ret;
2846 UINT font_cp;
2848 TRACE("%s, %d, %d, 0x%08x\n",
2849 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2851 /* both structs are equal in size */
2852 memcpy(&resultsW, lpResults, sizeof(resultsW));
2854 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2855 if(lpResults->lpOutString)
2856 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2858 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2860 lpResults->nGlyphs = resultsW.nGlyphs;
2861 lpResults->nMaxFit = resultsW.nMaxFit;
2863 if(lpResults->lpOutString) {
2864 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2865 lpResults->lpOutString, uCount, NULL, NULL );
2868 HeapFree(GetProcessHeap(), 0, lpStringW);
2869 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2871 return ret;
2874 /*************************************************************************
2875 * GetCharacterPlacementW [GDI32.@]
2877 * Retrieve information about a string. This includes the width, reordering,
2878 * Glyphing and so on.
2880 * RETURNS
2882 * The width and height of the string if successful, 0 if failed.
2884 * BUGS
2886 * All flags except GCP_REORDER are not yet implemented.
2887 * Reordering is not 100% compliant to the Windows BiDi method.
2888 * Caret positioning is not yet implemented for BiDi.
2889 * Classes are not yet implemented.
2892 DWORD WINAPI
2893 GetCharacterPlacementW(
2894 HDC hdc, /* [in] Device context for which the rendering is to be done */
2895 LPCWSTR lpString, /* [in] The string for which information is to be returned */
2896 INT uCount, /* [in] Number of WORDS in string. */
2897 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
2898 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2899 DWORD dwFlags /* [in] Flags specifying how to process the string */
2902 DWORD ret=0;
2903 SIZE size;
2904 UINT i, nSet;
2906 TRACE("%s, %d, %d, 0x%08x\n",
2907 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2909 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2910 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2911 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2912 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2913 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2915 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08x ignored\n", dwFlags);
2916 if(lpResults->lpClass) FIXME("classes not implemented\n");
2917 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2918 FIXME("Caret positions for complex scripts not implemented\n");
2920 nSet = (UINT)uCount;
2921 if(nSet > lpResults->nGlyphs)
2922 nSet = lpResults->nGlyphs;
2924 /* return number of initialized fields */
2925 lpResults->nGlyphs = nSet;
2927 if((dwFlags&GCP_REORDER)==0 )
2929 /* Treat the case where no special handling was requested in a fastpath way */
2930 /* copy will do if the GCP_REORDER flag is not set */
2931 if(lpResults->lpOutString)
2932 memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
2934 if(lpResults->lpOrder)
2936 for(i = 0; i < nSet; i++)
2937 lpResults->lpOrder[i] = i;
2939 } else
2941 BIDI_Reorder(NULL, lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
2942 nSet, lpResults->lpOrder, NULL, NULL );
2945 /* FIXME: Will use the placement chars */
2946 if (lpResults->lpDx)
2948 int c;
2949 for (i = 0; i < nSet; i++)
2951 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
2952 lpResults->lpDx[i]= c;
2956 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
2958 int pos = 0;
2960 lpResults->lpCaretPos[0] = 0;
2961 for (i = 1; i < nSet; i++)
2962 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
2963 lpResults->lpCaretPos[i] = (pos += size.cx);
2966 if(lpResults->lpGlyphs)
2967 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
2969 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
2970 ret = MAKELONG(size.cx, size.cy);
2972 return ret;
2975 /*************************************************************************
2976 * GetCharABCWidthsFloatA [GDI32.@]
2978 * See GetCharABCWidthsFloatW.
2980 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
2982 INT i, wlen, count = (INT)(last - first + 1);
2983 LPSTR str;
2984 LPWSTR wstr;
2985 BOOL ret = TRUE;
2987 if (count <= 0) return FALSE;
2989 str = HeapAlloc(GetProcessHeap(), 0, count);
2991 for(i = 0; i < count; i++)
2992 str[i] = (BYTE)(first + i);
2994 wstr = FONT_mbtowc( hdc, str, count, &wlen, NULL );
2996 for (i = 0; i < wlen; i++)
2998 if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
3000 ret = FALSE;
3001 break;
3003 abcf++;
3006 HeapFree( GetProcessHeap(), 0, str );
3007 HeapFree( GetProcessHeap(), 0, wstr );
3009 return ret;
3012 /*************************************************************************
3013 * GetCharABCWidthsFloatW [GDI32.@]
3015 * Retrieves widths of a range of characters.
3017 * PARAMS
3018 * hdc [I] Handle to device context.
3019 * first [I] First character in range to query.
3020 * last [I] Last character in range to query.
3021 * abcf [O] Array of LPABCFLOAT structures.
3023 * RETURNS
3024 * Success: TRUE
3025 * Failure: FALSE
3027 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3029 UINT i;
3030 BOOL ret = FALSE;
3031 DC *dc = get_dc_ptr( hdc );
3033 TRACE("%p, %d, %d, %p\n", hdc, first, last, abcf);
3035 if (!dc) return FALSE;
3037 if (!abcf)
3039 release_dc_ptr( dc );
3040 return FALSE;
3043 if (dc->gdiFont)
3044 ret = WineEngGetCharABCWidthsFloat( dc->gdiFont, first, last, abcf );
3045 else
3046 FIXME("stub\n");
3048 if (ret)
3050 /* convert device units to logical */
3051 for (i = first; i <= last; i++, abcf++)
3053 abcf->abcfA = abcf->abcfA * dc->xformVport2World.eM11;
3054 abcf->abcfB = abcf->abcfB * dc->xformVport2World.eM11;
3055 abcf->abcfC = abcf->abcfC * dc->xformVport2World.eM11;
3059 release_dc_ptr( dc );
3060 return ret;
3063 /*************************************************************************
3064 * GetCharWidthFloatA [GDI32.@]
3066 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
3067 UINT iLastChar, PFLOAT pxBuffer)
3069 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3070 return 0;
3073 /*************************************************************************
3074 * GetCharWidthFloatW [GDI32.@]
3076 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
3077 UINT iLastChar, PFLOAT pxBuffer)
3079 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3080 return 0;
3084 /***********************************************************************
3086 * Font Resource API *
3088 ***********************************************************************/
3090 /***********************************************************************
3091 * AddFontResourceA (GDI32.@)
3093 INT WINAPI AddFontResourceA( LPCSTR str )
3095 return AddFontResourceExA( str, 0, NULL);
3098 /***********************************************************************
3099 * AddFontResourceW (GDI32.@)
3101 INT WINAPI AddFontResourceW( LPCWSTR str )
3103 return AddFontResourceExW(str, 0, NULL);
3107 /***********************************************************************
3108 * AddFontResourceExA (GDI32.@)
3110 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3112 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3113 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3114 INT ret;
3116 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3117 ret = AddFontResourceExW(strW, fl, pdv);
3118 HeapFree(GetProcessHeap(), 0, strW);
3119 return ret;
3122 static BOOL CALLBACK load_enumed_resource(HMODULE hModule, LPCWSTR type, LPWSTR name, LONG_PTR lParam)
3124 HRSRC rsrc = FindResourceW(hModule, name, type);
3125 HGLOBAL hMem = LoadResource(hModule, rsrc);
3126 LPVOID *pMem = LockResource(hMem);
3127 int *num_total = (int *)lParam;
3128 DWORD num_in_res;
3130 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type));
3131 if (!AddFontMemResourceEx(pMem, SizeofResource(hModule, rsrc), NULL, &num_in_res))
3133 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule, hMem);
3134 return FALSE;
3137 *num_total += num_in_res;
3138 return TRUE;
3141 /***********************************************************************
3142 * AddFontResourceExW (GDI32.@)
3144 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3146 int ret = WineEngAddFontResourceEx(str, fl, pdv);
3147 if (ret == 0)
3149 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3150 HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
3151 if (hModule != NULL)
3153 int num_resources = 0;
3154 LPWSTR rt_font = (LPWSTR)((ULONG_PTR)8); /* we don't want to include winuser.h */
3156 TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3157 wine_dbgstr_w(str));
3158 if (EnumResourceNamesW(hModule, rt_font, load_enumed_resource, (LONG_PTR)&num_resources))
3159 ret = num_resources;
3160 FreeLibrary(hModule);
3163 return ret;
3166 /***********************************************************************
3167 * RemoveFontResourceA (GDI32.@)
3169 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3171 return RemoveFontResourceExA(str, 0, 0);
3174 /***********************************************************************
3175 * RemoveFontResourceW (GDI32.@)
3177 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3179 return RemoveFontResourceExW(str, 0, 0);
3182 /***********************************************************************
3183 * AddFontMemResourceEx (GDI32.@)
3185 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3187 HANDLE ret;
3188 DWORD num_fonts;
3190 if (!pbFont || !cbFont || !pcFonts)
3192 SetLastError(ERROR_INVALID_PARAMETER);
3193 return NULL;
3196 ret = WineEngAddFontMemResourceEx(pbFont, cbFont, pdv, &num_fonts);
3197 if (ret)
3199 __TRY
3201 *pcFonts = num_fonts;
3203 __EXCEPT_PAGE_FAULT
3205 WARN("page fault while writing to *pcFonts (%p)\n", pcFonts);
3206 RemoveFontMemResourceEx(ret);
3207 ret = 0;
3209 __ENDTRY
3211 return ret;
3214 /***********************************************************************
3215 * RemoveFontMemResourceEx (GDI32.@)
3217 BOOL WINAPI RemoveFontMemResourceEx( HANDLE fh )
3219 FIXME("(%p) stub\n", fh);
3220 return TRUE;
3223 /***********************************************************************
3224 * RemoveFontResourceExA (GDI32.@)
3226 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3228 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3229 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3230 INT ret;
3232 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3233 ret = RemoveFontResourceExW(strW, fl, pdv);
3234 HeapFree(GetProcessHeap(), 0, strW);
3235 return ret;
3238 /***********************************************************************
3239 * RemoveFontResourceExW (GDI32.@)
3241 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3243 return WineEngRemoveFontResourceEx(str, fl, pdv);
3246 /***********************************************************************
3247 * GetTextCharset (GDI32.@)
3249 UINT WINAPI GetTextCharset(HDC hdc)
3251 /* MSDN docs say this is equivalent */
3252 return GetTextCharsetInfo(hdc, NULL, 0);
3255 /***********************************************************************
3256 * GetTextCharsetInfo (GDI32.@)
3258 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3260 UINT ret = DEFAULT_CHARSET;
3261 DC *dc = get_dc_ptr(hdc);
3263 if (dc)
3265 if (dc->gdiFont)
3266 ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
3268 release_dc_ptr( dc );
3271 if (ret == DEFAULT_CHARSET && fs)
3272 memset(fs, 0, sizeof(FONTSIGNATURE));
3273 return ret;
3276 /***********************************************************************
3277 * GdiGetCharDimensions (GDI32.@)
3279 * Gets the average width of the characters in the English alphabet.
3281 * PARAMS
3282 * hdc [I] Handle to the device context to measure on.
3283 * lptm [O] Pointer to memory to store the text metrics into.
3284 * height [O] On exit, the maximum height of characters in the English alphabet.
3286 * RETURNS
3287 * The average width of characters in the English alphabet.
3289 * NOTES
3290 * This function is used by the dialog manager to get the size of a dialog
3291 * unit. It should also be used by other pieces of code that need to know
3292 * the size of a dialog unit in logical units without having access to the
3293 * window handle of the dialog.
3294 * Windows caches the font metrics from this function, but we don't and
3295 * there doesn't appear to be an immediate advantage to do so.
3297 * SEE ALSO
3298 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3300 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3302 SIZE sz;
3303 static const WCHAR alphabet[] = {
3304 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3305 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3306 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3308 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3310 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3312 if (height) *height = sz.cy;
3313 return (sz.cx / 26 + 1) / 2;
3316 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3318 FIXME("(%d): stub\n", fEnableEUDC);
3319 return FALSE;
3322 /***********************************************************************
3323 * GetCharWidthI (GDI32.@)
3325 * Retrieve widths of characters.
3327 * PARAMS
3328 * hdc [I] Handle to a device context.
3329 * first [I] First glyph in range to query.
3330 * count [I] Number of glyph indices to query.
3331 * glyphs [I] Array of glyphs to query.
3332 * buffer [O] Buffer to receive character widths.
3334 * NOTES
3335 * Only works with TrueType fonts.
3337 * RETURNS
3338 * Success: TRUE
3339 * Failure: FALSE
3341 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3343 ABC *abc;
3344 unsigned int i;
3346 TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3348 if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3349 return FALSE;
3351 if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3353 HeapFree(GetProcessHeap(), 0, abc);
3354 return FALSE;
3357 for (i = 0; i < count; i++)
3358 buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3360 HeapFree(GetProcessHeap(), 0, abc);
3361 return TRUE;
3364 /***********************************************************************
3365 * GetFontUnicodeRanges (GDI32.@)
3367 * Retrieve a list of supported Unicode characters in a font.
3369 * PARAMS
3370 * hdc [I] Handle to a device context.
3371 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3373 * RETURNS
3374 * Success: Number of bytes written to the buffer pointed to by lpgs.
3375 * Failure: 0
3378 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3380 DWORD ret = 0;
3381 DC *dc = get_dc_ptr(hdc);
3383 TRACE("(%p, %p)\n", hdc, lpgs);
3385 if (!dc) return 0;
3387 if (dc->gdiFont) ret = WineEngGetFontUnicodeRanges(dc->gdiFont, lpgs);
3388 release_dc_ptr(dc);
3389 return ret;
3393 /*************************************************************
3394 * FontIsLinked (GDI32.@)
3396 BOOL WINAPI FontIsLinked(HDC hdc)
3398 DC *dc = get_dc_ptr(hdc);
3399 BOOL ret = FALSE;
3401 if (!dc) return FALSE;
3402 if (dc->gdiFont) ret = WineEngFontIsLinked(dc->gdiFont);
3403 release_dc_ptr(dc);
3404 TRACE("returning %d\n", ret);
3405 return ret;
3408 /*************************************************************
3409 * GdiRealizationInfo (GDI32.@)
3411 * Returns a structure that contains some font information.
3413 BOOL WINAPI GdiRealizationInfo(HDC hdc, realization_info_t *info)
3415 DC *dc = get_dc_ptr(hdc);
3416 BOOL ret = FALSE;
3418 if (!dc) return FALSE;
3419 if (dc->gdiFont) ret = WineEngRealizationInfo(dc->gdiFont, info);
3420 release_dc_ptr(dc);
3422 return ret;