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