gdi32: Implement GetCharABCWidths as a standard driver entry point.
[wine/multimedia.git] / dlls / gdi32 / font.c
blobd12e73b284f469e3754fc338512c3655882a526d
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 typedef struct
105 GDIOBJHDR header;
106 LOGFONTW logfont;
107 } FONTOBJ;
109 struct font_enum
111 LPLOGFONTW lpLogFontParam;
112 FONTENUMPROCW lpEnumFunc;
113 LPARAM lpData;
114 BOOL unicode;
115 HDC hdc;
119 * For TranslateCharsetInfo
121 #define MAXTCIINDEX 32
122 static const CHARSETINFO FONT_tci[MAXTCIINDEX] = {
123 /* ANSI */
124 { ANSI_CHARSET, 1252, {{0,0,0,0},{FS_LATIN1,0}} },
125 { EASTEUROPE_CHARSET, 1250, {{0,0,0,0},{FS_LATIN2,0}} },
126 { RUSSIAN_CHARSET, 1251, {{0,0,0,0},{FS_CYRILLIC,0}} },
127 { GREEK_CHARSET, 1253, {{0,0,0,0},{FS_GREEK,0}} },
128 { TURKISH_CHARSET, 1254, {{0,0,0,0},{FS_TURKISH,0}} },
129 { HEBREW_CHARSET, 1255, {{0,0,0,0},{FS_HEBREW,0}} },
130 { ARABIC_CHARSET, 1256, {{0,0,0,0},{FS_ARABIC,0}} },
131 { BALTIC_CHARSET, 1257, {{0,0,0,0},{FS_BALTIC,0}} },
132 { VIETNAMESE_CHARSET, 1258, {{0,0,0,0},{FS_VIETNAMESE,0}} },
133 /* reserved by ANSI */
134 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
135 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
136 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
137 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
138 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
139 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
140 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
141 /* ANSI and OEM */
142 { THAI_CHARSET, 874, {{0,0,0,0},{FS_THAI,0}} },
143 { SHIFTJIS_CHARSET, 932, {{0,0,0,0},{FS_JISJAPAN,0}} },
144 { GB2312_CHARSET, 936, {{0,0,0,0},{FS_CHINESESIMP,0}} },
145 { HANGEUL_CHARSET, 949, {{0,0,0,0},{FS_WANSUNG,0}} },
146 { CHINESEBIG5_CHARSET, 950, {{0,0,0,0},{FS_CHINESETRAD,0}} },
147 { JOHAB_CHARSET, 1361, {{0,0,0,0},{FS_JOHAB,0}} },
148 /* reserved for alternate ANSI and OEM */
149 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
150 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
151 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
152 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
153 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
154 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
155 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
156 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
157 /* reserved for system */
158 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
159 { SYMBOL_CHARSET, CP_SYMBOL, {{0,0,0,0},{FS_SYMBOL,0}} }
162 static void FONT_LogFontAToW( const LOGFONTA *fontA, LPLOGFONTW fontW )
164 memcpy(fontW, fontA, sizeof(LOGFONTA) - LF_FACESIZE);
165 MultiByteToWideChar(CP_ACP, 0, fontA->lfFaceName, -1, fontW->lfFaceName,
166 LF_FACESIZE);
167 fontW->lfFaceName[LF_FACESIZE-1] = 0;
170 static void FONT_LogFontWToA( const LOGFONTW *fontW, LPLOGFONTA fontA )
172 memcpy(fontA, fontW, sizeof(LOGFONTA) - LF_FACESIZE);
173 WideCharToMultiByte(CP_ACP, 0, fontW->lfFaceName, -1, fontA->lfFaceName,
174 LF_FACESIZE, NULL, NULL);
175 fontA->lfFaceName[LF_FACESIZE-1] = 0;
178 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEXA fontA )
180 FONT_LogFontWToA( &fontW->elfLogFont, &fontA->elfLogFont );
182 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
183 (LPSTR) fontA->elfFullName, LF_FULLFACESIZE, NULL, NULL );
184 fontA->elfFullName[LF_FULLFACESIZE-1] = '\0';
185 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
186 (LPSTR) fontA->elfStyle, LF_FACESIZE, NULL, NULL );
187 fontA->elfStyle[LF_FACESIZE-1] = '\0';
188 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
189 (LPSTR) fontA->elfScript, LF_FACESIZE, NULL, NULL );
190 fontA->elfScript[LF_FACESIZE-1] = '\0';
193 static void FONT_EnumLogFontExAToW( const ENUMLOGFONTEXA *fontA, LPENUMLOGFONTEXW fontW )
195 FONT_LogFontAToW( &fontA->elfLogFont, &fontW->elfLogFont );
197 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfFullName, -1,
198 fontW->elfFullName, LF_FULLFACESIZE );
199 fontW->elfFullName[LF_FULLFACESIZE-1] = '\0';
200 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfStyle, -1,
201 fontW->elfStyle, LF_FACESIZE );
202 fontW->elfStyle[LF_FACESIZE-1] = '\0';
203 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfScript, -1,
204 fontW->elfScript, LF_FACESIZE );
205 fontW->elfScript[LF_FACESIZE-1] = '\0';
208 /***********************************************************************
209 * TEXTMETRIC conversion functions.
211 static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
213 ptmA->tmHeight = ptmW->tmHeight;
214 ptmA->tmAscent = ptmW->tmAscent;
215 ptmA->tmDescent = ptmW->tmDescent;
216 ptmA->tmInternalLeading = ptmW->tmInternalLeading;
217 ptmA->tmExternalLeading = ptmW->tmExternalLeading;
218 ptmA->tmAveCharWidth = ptmW->tmAveCharWidth;
219 ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth;
220 ptmA->tmWeight = ptmW->tmWeight;
221 ptmA->tmOverhang = ptmW->tmOverhang;
222 ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX;
223 ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
224 ptmA->tmFirstChar = min(ptmW->tmFirstChar, 255);
225 if (ptmW->tmCharSet == SYMBOL_CHARSET)
227 ptmA->tmFirstChar = 0x1e;
228 ptmA->tmLastChar = 0xff; /* win9x behaviour - we need the OS2 table data to calculate correctly */
230 else if (ptmW->tmPitchAndFamily & TMPF_TRUETYPE)
232 ptmA->tmFirstChar = ptmW->tmDefaultChar - 1;
233 ptmA->tmLastChar = min(ptmW->tmLastChar, 0xff);
235 else
237 ptmA->tmFirstChar = min(ptmW->tmFirstChar, 0xff);
238 ptmA->tmLastChar = min(ptmW->tmLastChar, 0xff);
240 ptmA->tmDefaultChar = ptmW->tmDefaultChar;
241 ptmA->tmBreakChar = ptmW->tmBreakChar;
242 ptmA->tmItalic = ptmW->tmItalic;
243 ptmA->tmUnderlined = ptmW->tmUnderlined;
244 ptmA->tmStruckOut = ptmW->tmStruckOut;
245 ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
246 ptmA->tmCharSet = ptmW->tmCharSet;
250 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW *ptmW, NEWTEXTMETRICEXA *ptmA )
252 FONT_TextMetricWToA((const TEXTMETRICW *)ptmW, (LPTEXTMETRICA)ptmA);
253 ptmA->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
254 ptmA->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
255 ptmA->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
256 ptmA->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
257 memcpy(&ptmA->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
261 /***********************************************************************
262 * GdiGetCodePage (GDI32.@)
264 DWORD WINAPI GdiGetCodePage( HDC hdc )
266 UINT cp = CP_ACP;
267 DC *dc = get_dc_ptr( hdc );
269 if (dc)
271 cp = dc->font_code_page;
272 release_dc_ptr( dc );
274 return cp;
277 /***********************************************************************
278 * FONT_mbtowc
280 * Returns a Unicode translation of str using the charset of the
281 * currently selected font in hdc. If count is -1 then str is assumed
282 * to be '\0' terminated, otherwise it contains the number of bytes to
283 * convert. If plenW is non-NULL, on return it will point to the
284 * number of WCHARs that have been written. If pCP is non-NULL, on
285 * return it will point to the codepage used in the conversion. The
286 * caller should free the returned LPWSTR from the process heap
287 * itself.
289 static LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
291 UINT cp;
292 INT lenW;
293 LPWSTR strW;
295 cp = GdiGetCodePage( hdc );
297 if(count == -1) count = strlen(str);
298 lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
299 strW = HeapAlloc(GetProcessHeap(), 0, lenW*sizeof(WCHAR));
300 MultiByteToWideChar(cp, 0, str, count, strW, lenW);
301 TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW));
302 if(plenW) *plenW = lenW;
303 if(pCP) *pCP = cp;
304 return strW;
307 /***********************************************************************
308 * CreateFontIndirectExA (GDI32.@)
310 HFONT WINAPI CreateFontIndirectExA( const ENUMLOGFONTEXDVA *penumexA )
312 ENUMLOGFONTEXDVW enumexW;
314 if (!penumexA) return 0;
316 FONT_EnumLogFontExAToW( &penumexA->elfEnumLogfontEx, &enumexW.elfEnumLogfontEx );
317 enumexW.elfDesignVector = penumexA->elfDesignVector;
318 return CreateFontIndirectExW( &enumexW );
321 /***********************************************************************
322 * CreateFontIndirectExW (GDI32.@)
324 HFONT WINAPI CreateFontIndirectExW( const ENUMLOGFONTEXDVW *penumex )
326 HFONT hFont;
327 FONTOBJ *fontPtr;
328 const LOGFONTW *plf;
330 if (!penumex) return 0;
332 if (penumex->elfEnumLogfontEx.elfFullName[0] ||
333 penumex->elfEnumLogfontEx.elfStyle[0] ||
334 penumex->elfEnumLogfontEx.elfScript[0])
336 FIXME("some fields ignored. fullname=%s, style=%s, script=%s\n",
337 debugstr_w(penumex->elfEnumLogfontEx.elfFullName),
338 debugstr_w(penumex->elfEnumLogfontEx.elfStyle),
339 debugstr_w(penumex->elfEnumLogfontEx.elfScript));
342 plf = &penumex->elfEnumLogfontEx.elfLogFont;
343 if (!(fontPtr = HeapAlloc( GetProcessHeap(), 0, sizeof(*fontPtr) ))) return 0;
345 fontPtr->logfont = *plf;
347 if (plf->lfEscapement != plf->lfOrientation)
349 /* this should really depend on whether GM_ADVANCED is set */
350 fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
351 WARN("orientation angle %f set to "
352 "escapement angle %f for new font %p\n",
353 plf->lfOrientation/10., plf->lfEscapement/10., fontPtr);
356 if (!(hFont = alloc_gdi_handle( &fontPtr->header, OBJ_FONT, &font_funcs )))
358 HeapFree( GetProcessHeap(), 0, fontPtr );
359 return 0;
362 TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
363 plf->lfHeight, plf->lfWidth,
364 plf->lfEscapement, plf->lfOrientation,
365 plf->lfPitchAndFamily,
366 plf->lfOutPrecision, plf->lfClipPrecision,
367 plf->lfQuality, plf->lfCharSet,
368 debugstr_w(plf->lfFaceName),
369 plf->lfWeight > 400 ? "Bold" : "",
370 plf->lfItalic ? "Italic" : "",
371 plf->lfUnderline ? "Underline" : "", hFont);
373 return hFont;
376 /***********************************************************************
377 * CreateFontIndirectA (GDI32.@)
379 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *plfA )
381 LOGFONTW lfW;
383 if (!plfA) return 0;
385 FONT_LogFontAToW( plfA, &lfW );
386 return CreateFontIndirectW( &lfW );
389 /***********************************************************************
390 * CreateFontIndirectW (GDI32.@)
392 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
394 ENUMLOGFONTEXDVW exdv;
396 if (!plf) return 0;
398 exdv.elfEnumLogfontEx.elfLogFont = *plf;
399 exdv.elfEnumLogfontEx.elfFullName[0] = 0;
400 exdv.elfEnumLogfontEx.elfStyle[0] = 0;
401 exdv.elfEnumLogfontEx.elfScript[0] = 0;
402 return CreateFontIndirectExW( &exdv );
405 /*************************************************************************
406 * CreateFontA (GDI32.@)
408 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
409 INT orient, INT weight, DWORD italic,
410 DWORD underline, DWORD strikeout, DWORD charset,
411 DWORD outpres, DWORD clippres, DWORD quality,
412 DWORD pitch, LPCSTR name )
414 LOGFONTA logfont;
416 logfont.lfHeight = height;
417 logfont.lfWidth = width;
418 logfont.lfEscapement = esc;
419 logfont.lfOrientation = orient;
420 logfont.lfWeight = weight;
421 logfont.lfItalic = italic;
422 logfont.lfUnderline = underline;
423 logfont.lfStrikeOut = strikeout;
424 logfont.lfCharSet = charset;
425 logfont.lfOutPrecision = outpres;
426 logfont.lfClipPrecision = clippres;
427 logfont.lfQuality = quality;
428 logfont.lfPitchAndFamily = pitch;
430 if (name)
431 lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
432 else
433 logfont.lfFaceName[0] = '\0';
435 return CreateFontIndirectA( &logfont );
438 /*************************************************************************
439 * CreateFontW (GDI32.@)
441 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
442 INT orient, INT weight, DWORD italic,
443 DWORD underline, DWORD strikeout, DWORD charset,
444 DWORD outpres, DWORD clippres, DWORD quality,
445 DWORD pitch, LPCWSTR name )
447 LOGFONTW logfont;
449 logfont.lfHeight = height;
450 logfont.lfWidth = width;
451 logfont.lfEscapement = esc;
452 logfont.lfOrientation = orient;
453 logfont.lfWeight = weight;
454 logfont.lfItalic = italic;
455 logfont.lfUnderline = underline;
456 logfont.lfStrikeOut = strikeout;
457 logfont.lfCharSet = charset;
458 logfont.lfOutPrecision = outpres;
459 logfont.lfClipPrecision = clippres;
460 logfont.lfQuality = quality;
461 logfont.lfPitchAndFamily = pitch;
463 if (name)
464 lstrcpynW(logfont.lfFaceName, name,
465 sizeof(logfont.lfFaceName) / sizeof(WCHAR));
466 else
467 logfont.lfFaceName[0] = '\0';
469 return CreateFontIndirectW( &logfont );
472 static void update_font_code_page( DC *dc )
474 CHARSETINFO csi;
475 int charset = DEFAULT_CHARSET;
477 if (dc->gdiFont)
478 charset = WineEngGetTextCharsetInfo( dc->gdiFont, NULL, 0 );
480 /* Hmm, nicely designed api this one! */
481 if (TranslateCharsetInfo( ULongToPtr(charset), &csi, TCI_SRCCHARSET) )
482 dc->font_code_page = csi.ciACP;
483 else {
484 switch(charset) {
485 case OEM_CHARSET:
486 dc->font_code_page = GetOEMCP();
487 break;
488 case DEFAULT_CHARSET:
489 dc->font_code_page = GetACP();
490 break;
492 case VISCII_CHARSET:
493 case TCVN_CHARSET:
494 case KOI8_CHARSET:
495 case ISO3_CHARSET:
496 case ISO4_CHARSET:
497 case ISO10_CHARSET:
498 case CELTIC_CHARSET:
499 /* FIXME: These have no place here, but because x11drv
500 enumerates fonts with these (made up) charsets some apps
501 might use them and then the FIXME below would become
502 annoying. Now we could pick the intended codepage for
503 each of these, but since it's broken anyway we'll just
504 use CP_ACP and hope it'll go away...
506 dc->font_code_page = CP_ACP;
507 break;
509 default:
510 FIXME("Can't find codepage for charset %d\n", charset);
511 dc->font_code_page = CP_ACP;
512 break;
516 TRACE("charset %d => cp %d\n", charset, dc->font_code_page);
519 /***********************************************************************
520 * FONT_SelectObject
522 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc )
524 HGDIOBJ ret = 0;
525 DC *dc = get_dc_ptr( hdc );
526 PHYSDEV physdev;
528 if (!dc) return 0;
530 if (!GDI_inc_ref_count( handle ))
532 release_dc_ptr( dc );
533 return 0;
536 physdev = GET_DC_PHYSDEV( dc, pSelectFont );
537 if (physdev->funcs->pSelectFont( physdev, handle ))
539 ret = dc->hFont;
540 dc->hFont = handle;
541 update_font_code_page( dc );
542 GDI_dec_ref_count( ret );
544 else GDI_dec_ref_count( handle );
546 release_dc_ptr( dc );
547 return ret;
551 /***********************************************************************
552 * FONT_GetObjectA
554 static INT FONT_GetObjectA( HGDIOBJ handle, INT count, LPVOID buffer )
556 FONTOBJ *font = GDI_GetObjPtr( handle, OBJ_FONT );
557 LOGFONTA lfA;
559 if (!font) return 0;
560 if (buffer)
562 FONT_LogFontWToA( &font->logfont, &lfA );
563 if (count > sizeof(lfA)) count = sizeof(lfA);
564 memcpy( buffer, &lfA, count );
566 else count = sizeof(lfA);
567 GDI_ReleaseObj( handle );
568 return count;
571 /***********************************************************************
572 * FONT_GetObjectW
574 static INT FONT_GetObjectW( HGDIOBJ handle, INT count, LPVOID buffer )
576 FONTOBJ *font = GDI_GetObjPtr( handle, OBJ_FONT );
578 if (!font) return 0;
579 if (buffer)
581 if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
582 memcpy( buffer, &font->logfont, count );
584 else count = sizeof(LOGFONTW);
585 GDI_ReleaseObj( handle );
586 return count;
590 /***********************************************************************
591 * FONT_DeleteObject
593 static BOOL FONT_DeleteObject( HGDIOBJ handle )
595 FONTOBJ *obj;
597 WineEngDestroyFontInstance( handle );
599 if (!(obj = free_gdi_handle( handle ))) return FALSE;
600 return HeapFree( GetProcessHeap(), 0, obj );
604 /***********************************************************************
605 * FONT_EnumInstance
607 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
608 * We have to use other types because of the FONTENUMPROCW definition.
610 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
611 DWORD fType, LPARAM lp )
613 struct font_enum *pfe = (struct font_enum *)lp;
614 INT ret = 1;
616 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
617 if ((!pfe->lpLogFontParam ||
618 pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
619 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
620 (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
622 /* convert font metrics */
623 ENUMLOGFONTEXA logfont;
624 NEWTEXTMETRICEXA tmA;
626 if (!pfe->unicode)
628 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
629 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
630 plf = (LOGFONTW *)&logfont.elfLogFont;
631 ptm = (TEXTMETRICW *)&tmA;
633 ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
635 return ret;
638 /***********************************************************************
639 * FONT_EnumFontFamiliesEx
641 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf, FONTENUMPROCW efproc,
642 LPARAM lParam, BOOL unicode )
644 INT ret = 0;
645 DC *dc = get_dc_ptr( hDC );
646 struct font_enum fe;
648 if (dc)
650 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pEnumFonts );
652 if (plf) TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName), plf->lfCharSet);
653 fe.lpLogFontParam = plf;
654 fe.lpEnumFunc = efproc;
655 fe.lpData = lParam;
656 fe.unicode = unicode;
657 fe.hdc = hDC;
658 ret = physdev->funcs->pEnumFonts( physdev, plf, FONT_EnumInstance, (LPARAM)&fe );
660 release_dc_ptr( dc );
661 return ret;
664 /***********************************************************************
665 * EnumFontFamiliesExW (GDI32.@)
667 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
668 FONTENUMPROCW efproc,
669 LPARAM lParam, DWORD dwFlags )
671 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, TRUE );
674 /***********************************************************************
675 * EnumFontFamiliesExA (GDI32.@)
677 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
678 FONTENUMPROCA efproc,
679 LPARAM lParam, DWORD dwFlags)
681 LOGFONTW lfW, *plfW;
683 if (plf)
685 FONT_LogFontAToW( plf, &lfW );
686 plfW = &lfW;
688 else plfW = NULL;
690 return FONT_EnumFontFamiliesEx( hDC, plfW, (FONTENUMPROCW)efproc, lParam, FALSE );
693 /***********************************************************************
694 * EnumFontFamiliesA (GDI32.@)
696 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
697 FONTENUMPROCA efproc, LPARAM lpData )
699 LOGFONTA lf, *plf;
701 if (lpFamily)
703 if (!*lpFamily) return 1;
704 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
705 lf.lfCharSet = DEFAULT_CHARSET;
706 lf.lfPitchAndFamily = 0;
707 plf = &lf;
709 else plf = NULL;
711 return EnumFontFamiliesExA( hDC, plf, efproc, lpData, 0 );
714 /***********************************************************************
715 * EnumFontFamiliesW (GDI32.@)
717 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
718 FONTENUMPROCW efproc, LPARAM lpData )
720 LOGFONTW lf, *plf;
722 if (lpFamily)
724 if (!*lpFamily) return 1;
725 lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
726 lf.lfCharSet = DEFAULT_CHARSET;
727 lf.lfPitchAndFamily = 0;
728 plf = &lf;
730 else plf = NULL;
732 return EnumFontFamiliesExW( hDC, plf, efproc, lpData, 0 );
735 /***********************************************************************
736 * EnumFontsA (GDI32.@)
738 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
739 LPARAM lpData )
741 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
744 /***********************************************************************
745 * EnumFontsW (GDI32.@)
747 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
748 LPARAM lpData )
750 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
754 /***********************************************************************
755 * GetTextCharacterExtra (GDI32.@)
757 INT WINAPI GetTextCharacterExtra( HDC hdc )
759 INT ret;
760 DC *dc = get_dc_ptr( hdc );
761 if (!dc) return 0x80000000;
762 ret = dc->charExtra;
763 release_dc_ptr( dc );
764 return ret;
768 /***********************************************************************
769 * SetTextCharacterExtra (GDI32.@)
771 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
773 INT ret = 0x80000000;
774 DC * dc = get_dc_ptr( hdc );
776 if (dc)
778 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetTextCharacterExtra );
779 extra = physdev->funcs->pSetTextCharacterExtra( physdev, extra );
780 if (extra != 0x80000000)
782 ret = dc->charExtra;
783 dc->charExtra = extra;
785 release_dc_ptr( dc );
787 return ret;
791 /***********************************************************************
792 * SetTextJustification (GDI32.@)
794 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
796 BOOL ret;
797 PHYSDEV physdev;
798 DC * dc = get_dc_ptr( hdc );
800 if (!dc) return FALSE;
802 physdev = GET_DC_PHYSDEV( dc, pSetTextJustification );
803 ret = physdev->funcs->pSetTextJustification( physdev, extra, breaks );
804 if (ret)
806 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
807 if (!extra) breaks = 0;
808 if (breaks)
810 dc->breakExtra = extra / breaks;
811 dc->breakRem = extra - (breaks * dc->breakExtra);
813 else
815 dc->breakExtra = 0;
816 dc->breakRem = 0;
819 release_dc_ptr( dc );
820 return ret;
824 /***********************************************************************
825 * GetTextFaceA (GDI32.@)
827 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
829 INT res = GetTextFaceW(hdc, 0, NULL);
830 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
831 GetTextFaceW( hdc, res, nameW );
833 if (name)
835 if (count)
837 res = WideCharToMultiByte(CP_ACP, 0, nameW, -1, name, count, NULL, NULL);
838 if (res == 0)
839 res = count;
840 name[count-1] = 0;
841 /* GetTextFaceA does NOT include the nul byte in the return count. */
842 res--;
844 else
845 res = 0;
847 else
848 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
849 HeapFree( GetProcessHeap(), 0, nameW );
850 return res;
853 /***********************************************************************
854 * GetTextFaceW (GDI32.@)
856 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
858 FONTOBJ *font;
859 INT ret = 0;
861 DC * dc = get_dc_ptr( hdc );
862 if (!dc) return 0;
864 if(dc->gdiFont)
865 ret = WineEngGetTextFace(dc->gdiFont, count, name);
866 else if ((font = GDI_GetObjPtr( dc->hFont, OBJ_FONT )))
868 INT n = strlenW(font->logfont.lfFaceName) + 1;
869 if (name)
871 lstrcpynW( name, font->logfont.lfFaceName, count );
872 ret = min(count, n);
874 else ret = n;
875 GDI_ReleaseObj( dc->hFont );
877 release_dc_ptr( dc );
878 return ret;
882 /***********************************************************************
883 * GetTextExtentPoint32A (GDI32.@)
885 * See GetTextExtentPoint32W.
887 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
888 LPSIZE size )
890 BOOL ret = FALSE;
891 INT wlen;
892 LPWSTR p;
894 if (count < 0) return FALSE;
896 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
898 if (p)
900 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
901 HeapFree( GetProcessHeap(), 0, p );
904 TRACE("(%p %s %d %p): returning %d x %d\n",
905 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
906 return ret;
910 /***********************************************************************
911 * GetTextExtentPoint32W [GDI32.@]
913 * Computes width/height for a string.
915 * Computes width and height of the specified string.
917 * RETURNS
918 * Success: TRUE
919 * Failure: FALSE
921 BOOL WINAPI GetTextExtentPoint32W(
922 HDC hdc, /* [in] Handle of device context */
923 LPCWSTR str, /* [in] Address of text string */
924 INT count, /* [in] Number of characters in string */
925 LPSIZE size) /* [out] Address of structure for string size */
927 return GetTextExtentExPointW(hdc, str, count, 0, NULL, NULL, size);
930 /***********************************************************************
931 * GetTextExtentExPointI [GDI32.@]
933 * Computes width and height of the array of glyph indices.
935 * PARAMS
936 * hdc [I] Handle of device context.
937 * indices [I] Glyph index array.
938 * count [I] Number of glyphs in array.
939 * max_ext [I] Maximum width in glyphs.
940 * nfit [O] Maximum number of characters.
941 * dxs [O] Partial string widths.
942 * size [O] Returned string size.
944 * RETURNS
945 * Success: TRUE
946 * Failure: FALSE
948 BOOL WINAPI GetTextExtentExPointI( HDC hdc, const WORD *indices, INT count, INT max_ext,
949 LPINT nfit, LPINT dxs, LPSIZE size )
951 BOOL ret = FALSE;
952 DC *dc;
954 if (count < 0) return FALSE;
956 dc = get_dc_ptr( hdc );
957 if (!dc) return FALSE;
959 if(dc->gdiFont)
961 ret = WineEngGetTextExtentExPointI(dc->gdiFont, indices, count, max_ext, nfit, dxs, size);
962 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
963 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
964 size->cx += count * dc->charExtra;
966 else
968 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pGetTextExtentExPoint );
969 FIXME("calling GetTextExtentExPoint\n");
970 ret = physdev->funcs->pGetTextExtentExPoint( physdev, indices, count, max_ext, nfit, dxs, size );
973 release_dc_ptr( dc );
975 TRACE("(%p %p %d %p): returning %d x %d\n",
976 hdc, indices, count, size, size->cx, size->cy );
977 return ret;
980 /***********************************************************************
981 * GetTextExtentPointI [GDI32.@]
983 * Computes width and height of the array of glyph indices.
985 * PARAMS
986 * hdc [I] Handle of device context.
987 * indices [I] Glyph index array.
988 * count [I] Number of glyphs in array.
989 * size [O] Returned string size.
991 * RETURNS
992 * Success: TRUE
993 * Failure: FALSE
995 BOOL WINAPI GetTextExtentPointI( HDC hdc, const WORD *indices, INT count, LPSIZE size )
997 return GetTextExtentExPointI( hdc, indices, count, 0, NULL, NULL, size );
1001 /***********************************************************************
1002 * GetTextExtentPointA (GDI32.@)
1004 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
1005 LPSIZE size )
1007 TRACE("not bug compatible.\n");
1008 return GetTextExtentPoint32A( hdc, str, count, size );
1011 /***********************************************************************
1012 * GetTextExtentPointW (GDI32.@)
1014 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1015 LPSIZE size )
1017 TRACE("not bug compatible.\n");
1018 return GetTextExtentPoint32W( hdc, str, count, size );
1022 /***********************************************************************
1023 * GetTextExtentExPointA (GDI32.@)
1025 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1026 INT maxExt, LPINT lpnFit,
1027 LPINT alpDx, LPSIZE size )
1029 BOOL ret;
1030 INT wlen;
1031 INT *walpDx = NULL;
1032 LPWSTR p = NULL;
1034 if (count < 0) return FALSE;
1036 if (alpDx)
1038 walpDx = HeapAlloc( GetProcessHeap(), 0, count * sizeof(INT) );
1039 if (!walpDx) return FALSE;
1042 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1043 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
1044 if (walpDx)
1046 INT n = lpnFit ? *lpnFit : wlen;
1047 INT i, j;
1048 for(i = 0, j = 0; i < n; i++, j++)
1050 alpDx[j] = walpDx[i];
1051 if (IsDBCSLeadByte(str[j])) alpDx[++j] = walpDx[i];
1054 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1055 HeapFree( GetProcessHeap(), 0, p );
1056 HeapFree( GetProcessHeap(), 0, walpDx );
1057 return ret;
1061 /***********************************************************************
1062 * GetTextExtentExPointW (GDI32.@)
1064 * Return the size of the string as it would be if it was output properly by
1065 * e.g. TextOut.
1067 * This should include
1068 * - Intercharacter spacing
1069 * - justification spacing (not yet done)
1070 * - kerning? see below
1072 * Kerning. Since kerning would be carried out by the rendering code it should
1073 * be done by the driver. However they don't support it yet. Also I am not
1074 * yet persuaded that (certainly under Win95) any kerning is actually done.
1076 * str: According to MSDN this should be null-terminated. That is not true; a
1077 * null will not terminate it early.
1078 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1079 * than count. I have seen it be either the size of the full string or
1080 * 1 less than the size of the full string. I have not seen it bear any
1081 * resemblance to the portion that would fit.
1082 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1083 * trailing intercharacter spacing and any trailing justification.
1085 * FIXME
1086 * Currently we do this by measuring each character etc. We should do it by
1087 * passing the request to the driver, perhaps by extending the
1088 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1089 * thinking about kerning issues and rounding issues in the justification.
1092 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1093 INT maxExt, LPINT lpnFit,
1094 LPINT alpDx, LPSIZE size )
1096 INT nFit = 0;
1097 LPINT dxs = NULL;
1098 DC *dc;
1099 BOOL ret = FALSE;
1100 TEXTMETRICW tm;
1101 PHYSDEV dev;
1103 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1105 if (count < 0) return FALSE;
1107 dc = get_dc_ptr(hdc);
1108 if (!dc) return FALSE;
1110 GetTextMetricsW(hdc, &tm);
1112 /* If we need to calculate nFit, then we need the partial extents even if
1113 the user hasn't provided us with an array. */
1114 if (lpnFit)
1116 dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]);
1117 if (! dxs)
1119 release_dc_ptr(dc);
1120 SetLastError(ERROR_OUTOFMEMORY);
1121 return FALSE;
1124 else
1125 dxs = alpDx;
1127 dev = GET_DC_PHYSDEV( dc, pGetTextExtentExPoint );
1128 ret = dev->funcs->pGetTextExtentExPoint(dev, str, count, 0, NULL, dxs, size);
1130 /* Perform device size to world size transformations. */
1131 if (ret)
1133 INT extra = dc->charExtra,
1134 breakExtra = dc->breakExtra,
1135 breakRem = dc->breakRem,
1138 if (dxs)
1140 for (i = 0; i < count; ++i)
1142 dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
1143 dxs[i] += (i+1) * extra;
1144 if (count > 1 && (breakExtra || breakRem) && str[i] == tm.tmBreakChar)
1146 dxs[i] += breakExtra;
1147 if (breakRem > 0)
1149 breakRem--;
1150 dxs[i]++;
1153 if (dxs[i] <= maxExt)
1154 ++nFit;
1156 breakRem = dc->breakRem;
1158 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1159 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1161 if (!dxs && count > 1 && (breakExtra || breakRem))
1163 for (i = 0; i < count; i++)
1165 if (str[i] == tm.tmBreakChar)
1167 size->cx += breakExtra;
1168 if (breakRem > 0)
1170 breakRem--;
1171 (size->cx)++;
1178 if (lpnFit)
1179 *lpnFit = nFit;
1181 if (! alpDx)
1182 HeapFree(GetProcessHeap(), 0, dxs);
1184 release_dc_ptr( dc );
1186 TRACE("returning %d %d x %d\n",nFit,size->cx,size->cy);
1187 return ret;
1190 /***********************************************************************
1191 * GetTextMetricsA (GDI32.@)
1193 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1195 TEXTMETRICW tm32;
1197 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1198 FONT_TextMetricWToA( &tm32, metrics );
1199 return TRUE;
1202 /***********************************************************************
1203 * GetTextMetricsW (GDI32.@)
1205 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1207 PHYSDEV physdev;
1208 BOOL ret = FALSE;
1209 DC * dc = get_dc_ptr( hdc );
1210 if (!dc) return FALSE;
1212 physdev = GET_DC_PHYSDEV( dc, pGetTextMetrics );
1213 ret = physdev->funcs->pGetTextMetrics( physdev, metrics );
1215 if (ret)
1217 /* device layer returns values in device units
1218 * therefore we have to convert them to logical */
1220 metrics->tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1221 metrics->tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1223 #define WDPTOLP(x) ((x<0)? \
1224 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1225 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1226 #define HDPTOLP(y) ((y<0)? \
1227 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1228 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1230 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1231 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1232 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1233 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1234 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1235 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1236 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1237 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1238 ret = TRUE;
1239 #undef WDPTOLP
1240 #undef HDPTOLP
1241 TRACE("text metrics:\n"
1242 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1243 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1244 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1245 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1246 " PitchAndFamily = %02x\n"
1247 " --------------------\n"
1248 " InternalLeading = %i\n"
1249 " Ascent = %i\n"
1250 " Descent = %i\n"
1251 " Height = %i\n",
1252 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1253 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1254 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1255 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1256 metrics->tmPitchAndFamily,
1257 metrics->tmInternalLeading,
1258 metrics->tmAscent,
1259 metrics->tmDescent,
1260 metrics->tmHeight );
1262 release_dc_ptr( dc );
1263 return ret;
1267 /***********************************************************************
1268 * GetOutlineTextMetricsA (GDI32.@)
1269 * Gets metrics for TrueType fonts.
1271 * NOTES
1272 * If the supplied buffer isn't big enough Windows partially fills it up to
1273 * its given length and returns that length.
1275 * RETURNS
1276 * Success: Non-zero or size of required buffer
1277 * Failure: 0
1279 UINT WINAPI GetOutlineTextMetricsA(
1280 HDC hdc, /* [in] Handle of device context */
1281 UINT cbData, /* [in] Size of metric data array */
1282 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1284 char buf[512], *ptr;
1285 UINT ret, needed;
1286 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1287 OUTLINETEXTMETRICA *output = lpOTM;
1288 INT left, len;
1290 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1291 return 0;
1292 if(ret > sizeof(buf))
1293 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1294 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1296 needed = sizeof(OUTLINETEXTMETRICA);
1297 if(lpOTMW->otmpFamilyName)
1298 needed += WideCharToMultiByte(CP_ACP, 0,
1299 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1300 NULL, 0, NULL, NULL);
1301 if(lpOTMW->otmpFaceName)
1302 needed += WideCharToMultiByte(CP_ACP, 0,
1303 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1304 NULL, 0, NULL, NULL);
1305 if(lpOTMW->otmpStyleName)
1306 needed += WideCharToMultiByte(CP_ACP, 0,
1307 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1308 NULL, 0, NULL, NULL);
1309 if(lpOTMW->otmpFullName)
1310 needed += WideCharToMultiByte(CP_ACP, 0,
1311 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1312 NULL, 0, NULL, NULL);
1314 if(!lpOTM) {
1315 ret = needed;
1316 goto end;
1319 TRACE("needed = %d\n", needed);
1320 if(needed > cbData)
1321 /* Since the supplied buffer isn't big enough, we'll alloc one
1322 that is and memcpy the first cbData bytes into the lpOTM at
1323 the end. */
1324 output = HeapAlloc(GetProcessHeap(), 0, needed);
1326 ret = output->otmSize = min(needed, cbData);
1327 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1328 output->otmFiller = 0;
1329 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1330 output->otmfsSelection = lpOTMW->otmfsSelection;
1331 output->otmfsType = lpOTMW->otmfsType;
1332 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1333 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1334 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1335 output->otmEMSquare = lpOTMW->otmEMSquare;
1336 output->otmAscent = lpOTMW->otmAscent;
1337 output->otmDescent = lpOTMW->otmDescent;
1338 output->otmLineGap = lpOTMW->otmLineGap;
1339 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1340 output->otmsXHeight = lpOTMW->otmsXHeight;
1341 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1342 output->otmMacAscent = lpOTMW->otmMacAscent;
1343 output->otmMacDescent = lpOTMW->otmMacDescent;
1344 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1345 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1346 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1347 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1348 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1349 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1350 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1351 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1352 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1353 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1356 ptr = (char*)(output + 1);
1357 left = needed - sizeof(*output);
1359 if(lpOTMW->otmpFamilyName) {
1360 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1361 len = WideCharToMultiByte(CP_ACP, 0,
1362 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1363 ptr, left, NULL, NULL);
1364 left -= len;
1365 ptr += len;
1366 } else
1367 output->otmpFamilyName = 0;
1369 if(lpOTMW->otmpFaceName) {
1370 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1371 len = WideCharToMultiByte(CP_ACP, 0,
1372 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1373 ptr, left, NULL, NULL);
1374 left -= len;
1375 ptr += len;
1376 } else
1377 output->otmpFaceName = 0;
1379 if(lpOTMW->otmpStyleName) {
1380 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1381 len = WideCharToMultiByte(CP_ACP, 0,
1382 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1383 ptr, left, NULL, NULL);
1384 left -= len;
1385 ptr += len;
1386 } else
1387 output->otmpStyleName = 0;
1389 if(lpOTMW->otmpFullName) {
1390 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1391 len = WideCharToMultiByte(CP_ACP, 0,
1392 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1393 ptr, left, NULL, NULL);
1394 left -= len;
1395 } else
1396 output->otmpFullName = 0;
1398 assert(left == 0);
1400 if(output != lpOTM) {
1401 memcpy(lpOTM, output, cbData);
1402 HeapFree(GetProcessHeap(), 0, output);
1404 /* check if the string offsets really fit into the provided size */
1405 /* FIXME: should we check string length as well? */
1406 /* make sure that we don't read/write beyond the provided buffer */
1407 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(LPSTR))
1409 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1410 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1413 /* make sure that we don't read/write beyond the provided buffer */
1414 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(LPSTR))
1416 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1417 lpOTM->otmpFaceName = 0; /* doesn't fit */
1420 /* make sure that we don't read/write beyond the provided buffer */
1421 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(LPSTR))
1423 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1424 lpOTM->otmpStyleName = 0; /* doesn't fit */
1427 /* make sure that we don't read/write beyond the provided buffer */
1428 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(LPSTR))
1430 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1431 lpOTM->otmpFullName = 0; /* doesn't fit */
1435 end:
1436 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1437 HeapFree(GetProcessHeap(), 0, lpOTMW);
1439 return ret;
1443 /***********************************************************************
1444 * GetOutlineTextMetricsW [GDI32.@]
1446 UINT WINAPI GetOutlineTextMetricsW(
1447 HDC hdc, /* [in] Handle of device context */
1448 UINT cbData, /* [in] Size of metric data array */
1449 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1451 DC *dc = get_dc_ptr( hdc );
1452 OUTLINETEXTMETRICW *output = lpOTM;
1453 UINT ret;
1455 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1456 if(!dc) return 0;
1458 if(dc->gdiFont) {
1459 ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, output);
1460 if(lpOTM && ret) {
1461 if(ret > cbData) {
1462 output = HeapAlloc(GetProcessHeap(), 0, ret);
1463 WineEngGetOutlineTextMetrics(dc->gdiFont, ret, output);
1466 output->otmTextMetrics.tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1467 output->otmTextMetrics.tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1469 #define WDPTOLP(x) ((x<0)? \
1470 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1471 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1472 #define HDPTOLP(y) ((y<0)? \
1473 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1474 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1476 output->otmTextMetrics.tmHeight = HDPTOLP(output->otmTextMetrics.tmHeight);
1477 output->otmTextMetrics.tmAscent = HDPTOLP(output->otmTextMetrics.tmAscent);
1478 output->otmTextMetrics.tmDescent = HDPTOLP(output->otmTextMetrics.tmDescent);
1479 output->otmTextMetrics.tmInternalLeading = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1480 output->otmTextMetrics.tmExternalLeading = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1481 output->otmTextMetrics.tmAveCharWidth = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1482 output->otmTextMetrics.tmMaxCharWidth = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1483 output->otmTextMetrics.tmOverhang = WDPTOLP(output->otmTextMetrics.tmOverhang);
1484 output->otmAscent = HDPTOLP(output->otmAscent);
1485 output->otmDescent = HDPTOLP(output->otmDescent);
1486 output->otmLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmLineGap));
1487 output->otmsCapEmHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsCapEmHeight));
1488 output->otmsXHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsXHeight));
1489 output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1490 output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1491 output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1492 output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1493 output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1494 output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1495 output->otmMacLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmMacLineGap));
1496 output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1497 output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1498 output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1499 output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1500 output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1501 output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1502 output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1503 output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1504 output->otmsStrikeoutSize = abs(INTERNAL_YDSTOWS(dc,output->otmsStrikeoutSize));
1505 output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1506 output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1507 output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1508 #undef WDPTOLP
1509 #undef HDPTOLP
1510 if(output != lpOTM) {
1511 memcpy(lpOTM, output, cbData);
1512 HeapFree(GetProcessHeap(), 0, output);
1513 ret = cbData;
1518 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1519 but really this should just be a return 0. */
1521 ret = sizeof(*lpOTM);
1522 if (lpOTM) {
1523 if(cbData < ret)
1524 ret = 0;
1525 else {
1526 memset(lpOTM, 0, ret);
1527 lpOTM->otmSize = sizeof(*lpOTM);
1528 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1530 Further fill of the structure not implemented,
1531 Needs real values for the structure members
1536 release_dc_ptr(dc);
1537 return ret;
1540 static LPSTR FONT_GetCharsByRangeA(HDC hdc, UINT firstChar, UINT lastChar, PINT pByteLen)
1542 INT i, count = lastChar - firstChar + 1;
1543 UINT c;
1544 LPSTR str;
1546 if (count <= 0)
1547 return NULL;
1549 switch (GdiGetCodePage(hdc))
1551 case 932:
1552 case 936:
1553 case 949:
1554 case 950:
1555 case 1361:
1556 if (lastChar > 0xffff)
1557 return NULL;
1558 if ((firstChar ^ lastChar) > 0xff)
1559 return NULL;
1560 break;
1561 default:
1562 if (lastChar > 0xff)
1563 return NULL;
1564 break;
1567 str = HeapAlloc(GetProcessHeap(), 0, count * 2 + 1);
1568 if (str == NULL)
1569 return NULL;
1571 for(i = 0, c = firstChar; c <= lastChar; i++, c++)
1573 if (c > 0xff)
1574 str[i++] = (BYTE)(c >> 8);
1575 str[i] = (BYTE)c;
1577 str[i] = '\0';
1579 *pByteLen = i;
1581 return str;
1584 /***********************************************************************
1585 * GetCharWidthW (GDI32.@)
1586 * GetCharWidth32W (GDI32.@)
1588 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1589 LPINT buffer )
1591 UINT i;
1592 BOOL ret;
1593 PHYSDEV dev;
1594 DC * dc = get_dc_ptr( hdc );
1596 if (!dc) return FALSE;
1598 dev = GET_DC_PHYSDEV( dc, pGetCharWidth );
1599 ret = dev->funcs->pGetCharWidth( dev, firstChar, lastChar, buffer );
1601 if (ret)
1603 /* convert device units to logical */
1604 for( i = firstChar; i <= lastChar; i++, buffer++ )
1605 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1607 release_dc_ptr( dc );
1608 return ret;
1612 /***********************************************************************
1613 * GetCharWidthA (GDI32.@)
1614 * GetCharWidth32A (GDI32.@)
1616 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1617 LPINT buffer )
1619 INT i, wlen;
1620 LPSTR str;
1621 LPWSTR wstr;
1622 BOOL ret = TRUE;
1624 str = FONT_GetCharsByRangeA(hdc, firstChar, lastChar, &i);
1625 if(str == NULL)
1626 return FALSE;
1628 wstr = FONT_mbtowc(hdc, str, i, &wlen, NULL);
1630 for(i = 0; i < wlen; i++)
1632 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1634 ret = FALSE;
1635 break;
1637 buffer++;
1640 HeapFree(GetProcessHeap(), 0, str);
1641 HeapFree(GetProcessHeap(), 0, wstr);
1643 return ret;
1647 /***********************************************************************
1648 * ExtTextOutA (GDI32.@)
1650 * See ExtTextOutW.
1652 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1653 const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1655 INT wlen;
1656 UINT codepage;
1657 LPWSTR p;
1658 BOOL ret;
1659 LPINT lpDxW = NULL;
1661 if (flags & ETO_GLYPH_INDEX)
1662 return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
1664 p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
1666 if (lpDx) {
1667 unsigned int i = 0, j = 0;
1669 /* allocate enough for a ETO_PDY */
1670 lpDxW = HeapAlloc( GetProcessHeap(), 0, 2*wlen*sizeof(INT));
1671 while(i < count) {
1672 if(IsDBCSLeadByteEx(codepage, str[i]))
1674 if(flags & ETO_PDY)
1676 lpDxW[j++] = lpDx[i * 2] + lpDx[(i + 1) * 2];
1677 lpDxW[j++] = lpDx[i * 2 + 1] + lpDx[(i + 1) * 2 + 1];
1679 else
1680 lpDxW[j++] = lpDx[i] + lpDx[i + 1];
1681 i = i + 2;
1683 else
1685 if(flags & ETO_PDY)
1687 lpDxW[j++] = lpDx[i * 2];
1688 lpDxW[j++] = lpDx[i * 2 + 1];
1690 else
1691 lpDxW[j++] = lpDx[i];
1692 i = i + 1;
1697 ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1699 HeapFree( GetProcessHeap(), 0, p );
1700 HeapFree( GetProcessHeap(), 0, lpDxW );
1701 return ret;
1705 /***********************************************************************
1706 * ExtTextOutW (GDI32.@)
1708 * Draws text using the currently selected font, background color, and text color.
1711 * PARAMS
1712 * x,y [I] coordinates of string
1713 * flags [I]
1714 * ETO_GRAYED - undocumented on MSDN
1715 * ETO_OPAQUE - use background color for fill the rectangle
1716 * ETO_CLIPPED - clipping text to the rectangle
1717 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1718 * than encoded characters. Implies ETO_IGNORELANGUAGE
1719 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1720 * Affects BiDi ordering
1721 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1722 * ETO_PDY - unimplemented
1723 * ETO_NUMERICSLATIN - unimplemented always assumed -
1724 * do not translate numbers into locale representations
1725 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1726 * lprect [I] dimensions for clipping or/and opaquing
1727 * str [I] text string
1728 * count [I] number of symbols in string
1729 * lpDx [I] optional parameter with distance between drawing characters
1731 * RETURNS
1732 * Success: TRUE
1733 * Failure: FALSE
1735 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1736 const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1738 BOOL ret = FALSE;
1739 LPWSTR reordered_str = (LPWSTR)str;
1740 WORD *glyphs = NULL;
1741 UINT align = GetTextAlign( hdc );
1742 DWORD layout = GetLayout( hdc );
1743 POINT pt;
1744 TEXTMETRICW tm;
1745 LOGFONTW lf;
1746 double cosEsc, sinEsc;
1747 INT char_extra;
1748 SIZE sz;
1749 RECT rc;
1750 BOOL done_extents = FALSE;
1751 POINT *deltas = NULL, width = {0, 0};
1752 DWORD type;
1753 DC * dc = get_dc_ptr( hdc );
1754 PHYSDEV physdev;
1755 INT breakRem;
1756 static int quietfixme = 0;
1758 if (!dc) return FALSE;
1760 breakRem = dc->breakRem;
1762 if (quietfixme == 0 && flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN))
1764 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN unimplemented\n");
1765 quietfixme = 1;
1768 update_dc( dc );
1769 physdev = GET_DC_PHYSDEV( dc, pExtTextOut );
1770 type = GetObjectType(hdc);
1771 if(type == OBJ_METADC || type == OBJ_ENHMETADC)
1773 ret = physdev->funcs->pExtTextOut( physdev, x, y, flags, lprect, str, count, lpDx );
1774 release_dc_ptr( dc );
1775 return ret;
1778 if (!lprect)
1779 flags &= ~ETO_CLIPPED;
1781 if (flags & ETO_RTLREADING) align |= TA_RTLREADING;
1782 if (layout & LAYOUT_RTL)
1784 if ((align & TA_CENTER) != TA_CENTER) align ^= TA_RIGHT;
1785 align ^= TA_RTLREADING;
1788 if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && count > 0 )
1790 INT cGlyphs;
1791 reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1793 BIDI_Reorder( hdc, str, count, GCP_REORDER,
1794 (align & TA_RTLREADING) ? WINE_GCPW_FORCE_RTL : WINE_GCPW_FORCE_LTR,
1795 reordered_str, count, NULL, &glyphs, &cGlyphs);
1797 flags |= ETO_IGNORELANGUAGE;
1798 if (glyphs)
1800 flags |= ETO_GLYPH_INDEX;
1801 if (cGlyphs != count)
1802 count = cGlyphs;
1805 else if(flags & ETO_GLYPH_INDEX)
1806 glyphs = reordered_str;
1808 TRACE("%p, %d, %d, %08x, %s, %s, %d, %p)\n", hdc, x, y, flags,
1809 wine_dbgstr_rect(lprect), debugstr_wn(str, count), count, lpDx);
1810 TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
1812 if(align & TA_UPDATECP)
1814 GetCurrentPositionEx( hdc, &pt );
1815 x = pt.x;
1816 y = pt.y;
1819 GetTextMetricsW(hdc, &tm);
1820 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1822 if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
1823 lf.lfEscapement = 0;
1825 if(lf.lfEscapement != 0)
1827 cosEsc = cos(lf.lfEscapement * M_PI / 1800);
1828 sinEsc = sin(lf.lfEscapement * M_PI / 1800);
1830 else
1832 cosEsc = 1;
1833 sinEsc = 0;
1836 if(flags & (ETO_CLIPPED | ETO_OPAQUE))
1838 if(!lprect)
1840 if(flags & ETO_GLYPH_INDEX)
1841 GetTextExtentPointI(hdc, glyphs, count, &sz);
1842 else
1843 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1845 done_extents = TRUE;
1846 rc.left = x;
1847 rc.top = y;
1848 rc.right = x + sz.cx;
1849 rc.bottom = y + sz.cy;
1851 else
1853 rc = *lprect;
1856 LPtoDP(hdc, (POINT*)&rc, 2);
1858 if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
1859 if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
1862 if ((flags & ETO_OPAQUE) && !PATH_IsPathOpen(dc->path))
1863 physdev->funcs->pExtTextOut( physdev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL );
1865 if(count == 0)
1867 ret = TRUE;
1868 goto done;
1871 pt.x = x;
1872 pt.y = y;
1873 LPtoDP(hdc, &pt, 1);
1874 x = pt.x;
1875 y = pt.y;
1877 char_extra = GetTextCharacterExtra(hdc);
1878 if(char_extra || dc->breakExtra || breakRem || lpDx || lf.lfEscapement != 0)
1880 UINT i;
1881 SIZE tmpsz;
1882 POINT total = {0, 0}, desired[2];
1884 deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
1885 for(i = 0; i < count; i++)
1887 if(lpDx)
1889 if(flags & ETO_PDY)
1891 deltas[i].x = lpDx[i * 2] + char_extra;
1892 deltas[i].y = -lpDx[i * 2 + 1];
1894 else
1896 deltas[i].x = lpDx[i] + char_extra;
1897 deltas[i].y = 0;
1901 else
1903 if(flags & ETO_GLYPH_INDEX)
1904 GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
1905 else
1906 GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
1908 deltas[i].x = tmpsz.cx;
1909 deltas[i].y = 0;
1912 if (!(flags & ETO_GLYPH_INDEX) && (dc->breakExtra || breakRem) && reordered_str[i] == tm.tmBreakChar)
1914 deltas[i].x = deltas[i].x + dc->breakExtra;
1915 if (breakRem > 0)
1917 breakRem--;
1918 deltas[i].x++;
1921 total.x += deltas[i].x;
1922 total.y += deltas[i].y;
1924 desired[0].x = desired[0].y = 0;
1926 desired[1].x = cosEsc * total.x + sinEsc * total.y;
1927 desired[1].y = -sinEsc * total.x + cosEsc * total.y;
1929 LPtoDP(hdc, desired, 2);
1930 desired[1].x -= desired[0].x;
1931 desired[1].y -= desired[0].y;
1932 if (layout & LAYOUT_RTL) desired[1].x = -desired[1].x;
1934 deltas[i].x = desired[1].x - width.x;
1935 deltas[i].y = desired[1].y - width.y;
1937 width = desired[1];
1939 flags |= ETO_PDY;
1941 else
1943 if(!done_extents)
1945 if(flags & ETO_GLYPH_INDEX)
1946 GetTextExtentPointI(hdc, glyphs, count, &sz);
1947 else
1948 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1949 done_extents = TRUE;
1951 width.x = abs(INTERNAL_XWSTODS(dc, sz.cx));
1952 width.y = 0;
1955 tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
1956 tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
1957 switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
1959 case TA_LEFT:
1960 if (align & TA_UPDATECP)
1962 pt.x = x + width.x;
1963 pt.y = y + width.y;
1964 DPtoLP(hdc, &pt, 1);
1965 MoveToEx(hdc, pt.x, pt.y, NULL);
1967 break;
1969 case TA_CENTER:
1970 x -= width.x / 2;
1971 y -= width.y / 2;
1972 break;
1974 case TA_RIGHT:
1975 x -= width.x;
1976 y -= width.y;
1977 if (align & TA_UPDATECP)
1979 pt.x = x;
1980 pt.y = y;
1981 DPtoLP(hdc, &pt, 1);
1982 MoveToEx(hdc, pt.x, pt.y, NULL);
1984 break;
1987 switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
1989 case TA_TOP:
1990 y += tm.tmAscent * cosEsc;
1991 x += tm.tmAscent * sinEsc;
1992 break;
1994 case TA_BOTTOM:
1995 y -= tm.tmDescent * cosEsc;
1996 x -= tm.tmDescent * sinEsc;
1997 break;
1999 case TA_BASELINE:
2000 break;
2003 if (GetBkMode(hdc) != TRANSPARENT && !PATH_IsPathOpen(dc->path))
2005 if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
2007 if(!(flags & ETO_OPAQUE) || x < rc.left || x + width.x >= rc.right ||
2008 y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
2010 RECT rc;
2011 rc.left = x;
2012 rc.right = x + width.x;
2013 rc.top = y - tm.tmAscent;
2014 rc.bottom = y + tm.tmDescent;
2016 if(flags & ETO_CLIPPED)
2018 rc.left = max(lprect->left, rc.left);
2019 rc.right = min(lprect->right, rc.right);
2020 rc.top = max(lprect->top, rc.top);
2021 rc.bottom = min(lprect->bottom, rc.bottom);
2023 if(rc.left < rc.right && rc.top < rc.bottom)
2024 physdev->funcs->pExtTextOut( physdev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL );
2029 if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
2031 HFONT orig_font = dc->hFont, cur_font;
2032 UINT glyph;
2033 INT span = 0;
2034 POINT *offsets = NULL;
2035 unsigned int i;
2037 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2038 for(i = 0; i < count; i++)
2040 WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
2041 if(cur_font != dc->hFont)
2043 if(!offsets)
2045 unsigned int j;
2046 offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
2047 offsets[0].x = offsets[0].y = 0;
2049 if(!deltas)
2051 SIZE tmpsz;
2052 for(j = 1; j < count; j++)
2054 GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
2055 offsets[j].x = offsets[j - 1].x + abs(INTERNAL_XWSTODS(dc, tmpsz.cx));
2056 offsets[j].y = 0;
2059 else
2061 for(j = 1; j < count; j++)
2063 offsets[j].x = offsets[j - 1].x + deltas[j].x;
2064 offsets[j].y = offsets[j - 1].y + deltas[j].y;
2068 if(span)
2070 if (PATH_IsPathOpen(dc->path))
2071 ret = PATH_ExtTextOut(dc, x + offsets[i - span].x, y + offsets[i - span].y,
2072 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2073 glyphs, span, deltas ? (INT*)(deltas + (i - span)) : NULL);
2074 else
2075 physdev->funcs->pExtTextOut( physdev, x + offsets[i - span].x,
2076 y + offsets[i - span].y,
2077 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc, glyphs,
2078 span, deltas ? (INT*)(deltas + (i - span)) : NULL);
2079 span = 0;
2081 SelectObject(hdc, cur_font);
2083 glyphs[span++] = glyph;
2085 if(i == count - 1)
2087 if (PATH_IsPathOpen(dc->path))
2088 ret = PATH_ExtTextOut(dc, x + (offsets ? offsets[count - span].x : 0),
2089 y + (offsets ? offsets[count - span].y : 0),
2090 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2091 glyphs, span, deltas ? (INT*)(deltas + (count - span)) : NULL);
2092 else
2093 ret = physdev->funcs->pExtTextOut(physdev, x + (offsets ? offsets[count - span].x : 0),
2094 y + (offsets ? offsets[count - span].y : 0),
2095 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc, glyphs,
2096 span, deltas ? (INT*)(deltas + (count - span)) : NULL);
2097 SelectObject(hdc, orig_font);
2098 HeapFree(GetProcessHeap(), 0, offsets);
2102 else
2104 if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
2106 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2107 GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
2108 flags |= ETO_GLYPH_INDEX;
2111 if (PATH_IsPathOpen(dc->path))
2112 ret = PATH_ExtTextOut(dc, x, y, (flags & ~ETO_OPAQUE), &rc,
2113 glyphs ? glyphs : reordered_str, count, (INT*)deltas);
2114 else
2115 ret = physdev->funcs->pExtTextOut( physdev, x, y, (flags & ~ETO_OPAQUE), &rc,
2116 glyphs ? glyphs : reordered_str, count, (INT*)deltas );
2119 done:
2120 HeapFree(GetProcessHeap(), 0, deltas);
2121 if(glyphs != reordered_str)
2122 HeapFree(GetProcessHeap(), 0, glyphs);
2123 if(reordered_str != str)
2124 HeapFree(GetProcessHeap(), 0, reordered_str);
2126 release_dc_ptr( dc );
2128 if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2130 int underlinePos, strikeoutPos;
2131 int underlineWidth, strikeoutWidth;
2132 UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2133 OUTLINETEXTMETRICW* otm = NULL;
2135 if(!size)
2137 underlinePos = 0;
2138 underlineWidth = tm.tmAscent / 20 + 1;
2139 strikeoutPos = tm.tmAscent / 2;
2140 strikeoutWidth = underlineWidth;
2142 else
2144 otm = HeapAlloc(GetProcessHeap(), 0, size);
2145 GetOutlineTextMetricsW(hdc, size, otm);
2146 underlinePos = otm->otmsUnderscorePosition;
2147 underlineWidth = otm->otmsUnderscoreSize;
2148 strikeoutPos = otm->otmsStrikeoutPosition;
2149 strikeoutWidth = otm->otmsStrikeoutSize;
2150 HeapFree(GetProcessHeap(), 0, otm);
2153 if (PATH_IsPathOpen(dc->path))
2155 POINT pts[5];
2156 HPEN hpen;
2157 HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2159 hbrush = SelectObject(hdc, hbrush);
2160 hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2162 if (lf.lfUnderline)
2164 pts[0].x = x - underlinePos * sinEsc;
2165 pts[0].y = y - underlinePos * cosEsc;
2166 pts[1].x = x + width.x - underlinePos * sinEsc;
2167 pts[1].y = y + width.y - underlinePos * cosEsc;
2168 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2169 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2170 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2171 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2172 pts[4].x = pts[0].x;
2173 pts[4].y = pts[0].y;
2174 DPtoLP(hdc, pts, 5);
2175 Polygon(hdc, pts, 5);
2178 if (lf.lfStrikeOut)
2180 pts[0].x = x - strikeoutPos * sinEsc;
2181 pts[0].y = y - strikeoutPos * cosEsc;
2182 pts[1].x = x + width.x - strikeoutPos * sinEsc;
2183 pts[1].y = y + width.y - strikeoutPos * cosEsc;
2184 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2185 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2186 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2187 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2188 pts[4].x = pts[0].x;
2189 pts[4].y = pts[0].y;
2190 DPtoLP(hdc, pts, 5);
2191 Polygon(hdc, pts, 5);
2194 SelectObject(hdc, hpen);
2195 hbrush = SelectObject(hdc, hbrush);
2196 DeleteObject(hbrush);
2198 else
2200 POINT pts[2], oldpt;
2201 HPEN hpen;
2203 if (lf.lfUnderline)
2205 hpen = CreatePen(PS_SOLID, underlineWidth, GetTextColor(hdc));
2206 hpen = SelectObject(hdc, hpen);
2207 pts[0].x = x;
2208 pts[0].y = y;
2209 pts[1].x = x + width.x;
2210 pts[1].y = y + width.y;
2211 DPtoLP(hdc, pts, 2);
2212 MoveToEx(hdc, pts[0].x - underlinePos * sinEsc, pts[0].y - underlinePos * cosEsc, &oldpt);
2213 LineTo(hdc, pts[1].x - underlinePos * sinEsc, pts[1].y - underlinePos * cosEsc);
2214 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2215 DeleteObject(SelectObject(hdc, hpen));
2218 if (lf.lfStrikeOut)
2220 hpen = CreatePen(PS_SOLID, strikeoutWidth, GetTextColor(hdc));
2221 hpen = SelectObject(hdc, hpen);
2222 pts[0].x = x;
2223 pts[0].y = y;
2224 pts[1].x = x + width.x;
2225 pts[1].y = y + width.y;
2226 DPtoLP(hdc, pts, 2);
2227 MoveToEx(hdc, pts[0].x - strikeoutPos * sinEsc, pts[0].y - strikeoutPos * cosEsc, &oldpt);
2228 LineTo(hdc, pts[1].x - strikeoutPos * sinEsc, pts[1].y - strikeoutPos * cosEsc);
2229 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2230 DeleteObject(SelectObject(hdc, hpen));
2235 return ret;
2239 /***********************************************************************
2240 * TextOutA (GDI32.@)
2242 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2244 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2248 /***********************************************************************
2249 * TextOutW (GDI32.@)
2251 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2253 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2257 /***********************************************************************
2258 * PolyTextOutA (GDI32.@)
2260 * See PolyTextOutW.
2262 BOOL WINAPI PolyTextOutA( HDC hdc, const POLYTEXTA *pptxt, INT cStrings )
2264 for (; cStrings>0; cStrings--, pptxt++)
2265 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2266 return FALSE;
2267 return TRUE;
2272 /***********************************************************************
2273 * PolyTextOutW (GDI32.@)
2275 * Draw several Strings
2277 * RETURNS
2278 * TRUE: Success.
2279 * FALSE: Failure.
2281 BOOL WINAPI PolyTextOutW( HDC hdc, const POLYTEXTW *pptxt, INT cStrings )
2283 for (; cStrings>0; cStrings--, pptxt++)
2284 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2285 return FALSE;
2286 return TRUE;
2290 /***********************************************************************
2291 * SetMapperFlags (GDI32.@)
2293 DWORD WINAPI SetMapperFlags( HDC hdc, DWORD flags )
2295 DC *dc = get_dc_ptr( hdc );
2296 DWORD ret = GDI_ERROR;
2298 if (dc)
2300 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetMapperFlags );
2301 flags = physdev->funcs->pSetMapperFlags( physdev, flags );
2302 if (flags != GDI_ERROR)
2304 ret = dc->mapperFlags;
2305 dc->mapperFlags = flags;
2307 release_dc_ptr( dc );
2309 return ret;
2312 /***********************************************************************
2313 * GetAspectRatioFilterEx (GDI32.@)
2315 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2317 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2318 return FALSE;
2322 /***********************************************************************
2323 * GetCharABCWidthsA (GDI32.@)
2325 * See GetCharABCWidthsW.
2327 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2328 LPABC abc )
2330 INT i, wlen;
2331 LPSTR str;
2332 LPWSTR wstr;
2333 BOOL ret = TRUE;
2335 str = FONT_GetCharsByRangeA(hdc, firstChar, lastChar, &i);
2336 if (str == NULL)
2337 return FALSE;
2339 wstr = FONT_mbtowc(hdc, str, i, &wlen, NULL);
2340 if (wstr == NULL)
2342 HeapFree(GetProcessHeap(), 0, str);
2343 return FALSE;
2346 for(i = 0; i < wlen; i++)
2348 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2350 ret = FALSE;
2351 break;
2353 abc++;
2356 HeapFree(GetProcessHeap(), 0, str);
2357 HeapFree(GetProcessHeap(), 0, wstr);
2359 return ret;
2363 /******************************************************************************
2364 * GetCharABCWidthsW [GDI32.@]
2366 * Retrieves widths of characters in range.
2368 * PARAMS
2369 * hdc [I] Handle of device context
2370 * firstChar [I] First character in range to query
2371 * lastChar [I] Last character in range to query
2372 * abc [O] Address of character-width structure
2374 * NOTES
2375 * Only works with TrueType fonts
2377 * RETURNS
2378 * Success: TRUE
2379 * Failure: FALSE
2381 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2382 LPABC abc )
2384 DC *dc = get_dc_ptr(hdc);
2385 PHYSDEV dev;
2386 unsigned int i;
2387 BOOL ret;
2389 if (!dc) return FALSE;
2391 if (!abc)
2393 release_dc_ptr( dc );
2394 return FALSE;
2397 dev = GET_DC_PHYSDEV( dc, pGetCharABCWidths );
2398 ret = dev->funcs->pGetCharABCWidths( dev, firstChar, lastChar, abc );
2399 if (ret)
2401 /* convert device units to logical */
2402 for( i = firstChar; i <= lastChar; i++, abc++ ) {
2403 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2404 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2405 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2409 release_dc_ptr( dc );
2410 return ret;
2414 /******************************************************************************
2415 * GetCharABCWidthsI [GDI32.@]
2417 * Retrieves widths of characters in range.
2419 * PARAMS
2420 * hdc [I] Handle of device context
2421 * firstChar [I] First glyphs in range to query
2422 * count [I] Last glyphs in range to query
2423 * pgi [i] Array of glyphs to query
2424 * abc [O] Address of character-width structure
2426 * NOTES
2427 * Only works with TrueType fonts
2429 * RETURNS
2430 * Success: TRUE
2431 * Failure: FALSE
2433 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2434 LPWORD pgi, LPABC abc)
2436 DC *dc = get_dc_ptr(hdc);
2437 unsigned int i;
2438 BOOL ret = FALSE;
2440 if (!dc) return FALSE;
2442 if (!abc)
2444 release_dc_ptr( dc );
2445 return FALSE;
2448 if(dc->gdiFont)
2449 ret = WineEngGetCharABCWidthsI( dc->gdiFont, firstChar, count, pgi, abc );
2450 else
2451 FIXME(": stub\n");
2453 if (ret)
2455 /* convert device units to logical */
2456 for( i = 0; i < count; i++, abc++ ) {
2457 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2458 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2459 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2461 ret = TRUE;
2464 release_dc_ptr( dc );
2465 return ret;
2469 /***********************************************************************
2470 * GetGlyphOutlineA (GDI32.@)
2472 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2473 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2474 LPVOID lpBuffer, const MAT2 *lpmat2 )
2476 if (!lpmat2) return GDI_ERROR;
2478 if(!(fuFormat & GGO_GLYPH_INDEX)) {
2479 UINT cp;
2480 int len;
2481 char mbchs[2];
2483 cp = GdiGetCodePage(hdc);
2484 if (IsDBCSLeadByteEx(cp, uChar >> 8)) {
2485 len = 2;
2486 mbchs[0] = (uChar & 0xff00) >> 8;
2487 mbchs[1] = (uChar & 0xff);
2488 } else {
2489 len = 1;
2490 mbchs[0] = (uChar & 0xff);
2492 uChar = 0;
2493 MultiByteToWideChar(cp, 0, mbchs, len, (LPWSTR)&uChar, 1);
2496 return GetGlyphOutlineW(hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer,
2497 lpmat2);
2500 /***********************************************************************
2501 * GetGlyphOutlineW (GDI32.@)
2503 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2504 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2505 LPVOID lpBuffer, const MAT2 *lpmat2 )
2507 DC *dc;
2508 DWORD ret;
2510 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2511 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2513 if (!lpmat2) return GDI_ERROR;
2515 dc = get_dc_ptr(hdc);
2516 if(!dc) return GDI_ERROR;
2518 if(dc->gdiFont)
2519 ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
2520 cbBuffer, lpBuffer, lpmat2);
2521 else
2522 ret = GDI_ERROR;
2524 release_dc_ptr( dc );
2525 return ret;
2529 /***********************************************************************
2530 * CreateScalableFontResourceA (GDI32.@)
2532 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2533 LPCSTR lpszResourceFile,
2534 LPCSTR lpszFontFile,
2535 LPCSTR lpszCurrentPath )
2537 LPWSTR lpszResourceFileW = NULL;
2538 LPWSTR lpszFontFileW = NULL;
2539 LPWSTR lpszCurrentPathW = NULL;
2540 int len;
2541 BOOL ret;
2543 if (lpszResourceFile)
2545 len = MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, NULL, 0);
2546 lpszResourceFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2547 MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, lpszResourceFileW, len);
2550 if (lpszFontFile)
2552 len = MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, NULL, 0);
2553 lpszFontFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2554 MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, lpszFontFileW, len);
2557 if (lpszCurrentPath)
2559 len = MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, NULL, 0);
2560 lpszCurrentPathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2561 MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, lpszCurrentPathW, len);
2564 ret = CreateScalableFontResourceW(fHidden, lpszResourceFileW,
2565 lpszFontFileW, lpszCurrentPathW);
2567 HeapFree(GetProcessHeap(), 0, lpszResourceFileW);
2568 HeapFree(GetProcessHeap(), 0, lpszFontFileW);
2569 HeapFree(GetProcessHeap(), 0, lpszCurrentPathW);
2571 return ret;
2574 /***********************************************************************
2575 * CreateScalableFontResourceW (GDI32.@)
2577 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2578 LPCWSTR lpszResourceFile,
2579 LPCWSTR lpszFontFile,
2580 LPCWSTR lpszCurrentPath )
2582 HANDLE f;
2583 FIXME("(%d,%s,%s,%s): stub\n",
2584 fHidden, debugstr_w(lpszResourceFile), debugstr_w(lpszFontFile),
2585 debugstr_w(lpszCurrentPath) );
2587 /* fHidden=1 - only visible for the calling app, read-only, not
2588 * enumerated with EnumFonts/EnumFontFamilies
2589 * lpszCurrentPath can be NULL
2592 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2593 if ((f = CreateFileW(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2594 CloseHandle(f);
2595 SetLastError(ERROR_FILE_EXISTS);
2596 return FALSE;
2598 return FALSE; /* create failed */
2601 /*************************************************************************
2602 * GetKerningPairsA (GDI32.@)
2604 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2605 LPKERNINGPAIR kern_pairA )
2607 UINT cp;
2608 CPINFO cpi;
2609 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2610 KERNINGPAIR *kern_pairW;
2612 if (!cPairs && kern_pairA)
2614 SetLastError(ERROR_INVALID_PARAMETER);
2615 return 0;
2618 cp = GdiGetCodePage(hDC);
2620 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2621 * to fail on an invalid character for CP_SYMBOL.
2623 cpi.DefaultChar[0] = 0;
2624 if (cp != CP_SYMBOL && !GetCPInfo(cp, &cpi))
2626 FIXME("Can't find codepage %u info\n", cp);
2627 return 0;
2630 total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2631 if (!total_kern_pairs) return 0;
2633 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2634 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2636 for (i = 0; i < total_kern_pairs; i++)
2638 char first, second;
2640 if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2641 continue;
2643 if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2644 continue;
2646 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2647 continue;
2649 if (kern_pairA)
2651 if (kern_pairs_copied >= cPairs) break;
2653 kern_pairA->wFirst = (BYTE)first;
2654 kern_pairA->wSecond = (BYTE)second;
2655 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2656 kern_pairA++;
2658 kern_pairs_copied++;
2661 HeapFree(GetProcessHeap(), 0, kern_pairW);
2663 return kern_pairs_copied;
2666 /*************************************************************************
2667 * GetKerningPairsW (GDI32.@)
2669 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2670 LPKERNINGPAIR lpKerningPairs )
2672 DC *dc;
2673 DWORD ret = 0;
2675 TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2677 if (!cPairs && lpKerningPairs)
2679 SetLastError(ERROR_INVALID_PARAMETER);
2680 return 0;
2683 dc = get_dc_ptr(hDC);
2684 if (!dc) return 0;
2686 if (dc->gdiFont)
2687 ret = WineEngGetKerningPairs(dc->gdiFont, cPairs, lpKerningPairs);
2689 release_dc_ptr( dc );
2690 return ret;
2693 /*************************************************************************
2694 * TranslateCharsetInfo [GDI32.@]
2696 * Fills a CHARSETINFO structure for a character set, code page, or
2697 * font. This allows making the correspondence between different labels
2698 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2699 * of the same encoding.
2701 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2702 * only one codepage should be set in *lpSrc.
2704 * RETURNS
2705 * TRUE on success, FALSE on failure.
2708 BOOL WINAPI TranslateCharsetInfo(
2709 LPDWORD lpSrc, /* [in]
2710 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2711 if flags == TCI_SRCCHARSET: a character set value
2712 if flags == TCI_SRCCODEPAGE: a code page value
2714 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2715 DWORD flags /* [in] determines interpretation of lpSrc */)
2717 int index = 0;
2718 switch (flags) {
2719 case TCI_SRCFONTSIG:
2720 while (index < MAXTCIINDEX && !(*lpSrc>>index & 0x0001)) index++;
2721 break;
2722 case TCI_SRCCODEPAGE:
2723 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciACP) index++;
2724 break;
2725 case TCI_SRCCHARSET:
2726 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciCharset) index++;
2727 break;
2728 default:
2729 return FALSE;
2731 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2732 *lpCs = FONT_tci[index];
2733 return TRUE;
2736 /*************************************************************************
2737 * GetFontLanguageInfo (GDI32.@)
2739 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2741 FONTSIGNATURE fontsig;
2742 static const DWORD GCP_DBCS_MASK=0x003F0000,
2743 GCP_DIACRITIC_MASK=0x00000000,
2744 FLI_GLYPHS_MASK=0x00000000,
2745 GCP_GLYPHSHAPE_MASK=0x00000040,
2746 GCP_KASHIDA_MASK=0x00000000,
2747 GCP_LIGATE_MASK=0x00000000,
2748 GCP_USEKERNING_MASK=0x00000000,
2749 GCP_REORDER_MASK=0x00000060;
2751 DWORD result=0;
2753 GetTextCharsetInfo( hdc, &fontsig, 0 );
2754 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2756 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2757 result|=GCP_DBCS;
2759 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2760 result|=GCP_DIACRITIC;
2762 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2763 result|=FLI_GLYPHS;
2765 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2766 result|=GCP_GLYPHSHAPE;
2768 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2769 result|=GCP_KASHIDA;
2771 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2772 result|=GCP_LIGATE;
2774 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2775 result|=GCP_USEKERNING;
2777 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2778 if( GetTextAlign( hdc) & TA_RTLREADING )
2779 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2780 result|=GCP_REORDER;
2782 return result;
2786 /*************************************************************************
2787 * GetFontData [GDI32.@]
2789 * Retrieve data for TrueType font.
2791 * RETURNS
2793 * success: Number of bytes returned
2794 * failure: GDI_ERROR
2796 * NOTES
2798 * Calls SetLastError()
2801 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2802 LPVOID buffer, DWORD length)
2804 DC *dc = get_dc_ptr(hdc);
2805 DWORD ret = GDI_ERROR;
2807 if(!dc) return GDI_ERROR;
2809 if(dc->gdiFont)
2810 ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2812 release_dc_ptr( dc );
2813 return ret;
2816 /*************************************************************************
2817 * GetGlyphIndicesA [GDI32.@]
2819 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2820 LPWORD pgi, DWORD flags)
2822 DWORD ret;
2823 WCHAR *lpstrW;
2824 INT countW;
2826 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2827 hdc, debugstr_an(lpstr, count), count, pgi, flags);
2829 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2830 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2831 HeapFree(GetProcessHeap(), 0, lpstrW);
2833 return ret;
2836 /*************************************************************************
2837 * GetGlyphIndicesW [GDI32.@]
2839 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2840 LPWORD pgi, DWORD flags)
2842 DC *dc = get_dc_ptr(hdc);
2843 DWORD ret = GDI_ERROR;
2845 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2846 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2848 if(!dc) return GDI_ERROR;
2850 if(dc->gdiFont)
2851 ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2853 release_dc_ptr( dc );
2854 return ret;
2857 /*************************************************************************
2858 * GetCharacterPlacementA [GDI32.@]
2860 * See GetCharacterPlacementW.
2862 * NOTES:
2863 * the web browser control of ie4 calls this with dwFlags=0
2865 DWORD WINAPI
2866 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2867 INT nMaxExtent, GCP_RESULTSA *lpResults,
2868 DWORD dwFlags)
2870 WCHAR *lpStringW;
2871 INT uCountW;
2872 GCP_RESULTSW resultsW;
2873 DWORD ret;
2874 UINT font_cp;
2876 TRACE("%s, %d, %d, 0x%08x\n",
2877 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2879 /* both structs are equal in size */
2880 memcpy(&resultsW, lpResults, sizeof(resultsW));
2882 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2883 if(lpResults->lpOutString)
2884 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2886 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2888 lpResults->nGlyphs = resultsW.nGlyphs;
2889 lpResults->nMaxFit = resultsW.nMaxFit;
2891 if(lpResults->lpOutString) {
2892 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2893 lpResults->lpOutString, uCount, NULL, NULL );
2896 HeapFree(GetProcessHeap(), 0, lpStringW);
2897 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2899 return ret;
2902 /*************************************************************************
2903 * GetCharacterPlacementW [GDI32.@]
2905 * Retrieve information about a string. This includes the width, reordering,
2906 * Glyphing and so on.
2908 * RETURNS
2910 * The width and height of the string if successful, 0 if failed.
2912 * BUGS
2914 * All flags except GCP_REORDER are not yet implemented.
2915 * Reordering is not 100% compliant to the Windows BiDi method.
2916 * Caret positioning is not yet implemented for BiDi.
2917 * Classes are not yet implemented.
2920 DWORD WINAPI
2921 GetCharacterPlacementW(
2922 HDC hdc, /* [in] Device context for which the rendering is to be done */
2923 LPCWSTR lpString, /* [in] The string for which information is to be returned */
2924 INT uCount, /* [in] Number of WORDS in string. */
2925 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
2926 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2927 DWORD dwFlags /* [in] Flags specifying how to process the string */
2930 DWORD ret=0;
2931 SIZE size;
2932 UINT i, nSet;
2934 TRACE("%s, %d, %d, 0x%08x\n",
2935 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2937 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2938 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2939 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2940 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2941 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2943 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08x ignored\n", dwFlags);
2944 if(lpResults->lpClass) FIXME("classes not implemented\n");
2945 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2946 FIXME("Caret positions for complex scripts not implemented\n");
2948 nSet = (UINT)uCount;
2949 if(nSet > lpResults->nGlyphs)
2950 nSet = lpResults->nGlyphs;
2952 /* return number of initialized fields */
2953 lpResults->nGlyphs = nSet;
2955 if((dwFlags&GCP_REORDER)==0 )
2957 /* Treat the case where no special handling was requested in a fastpath way */
2958 /* copy will do if the GCP_REORDER flag is not set */
2959 if(lpResults->lpOutString)
2960 memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
2962 if(lpResults->lpOrder)
2964 for(i = 0; i < nSet; i++)
2965 lpResults->lpOrder[i] = i;
2967 } else
2969 BIDI_Reorder(NULL, lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
2970 nSet, lpResults->lpOrder, NULL, NULL );
2973 /* FIXME: Will use the placement chars */
2974 if (lpResults->lpDx)
2976 int c;
2977 for (i = 0; i < nSet; i++)
2979 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
2980 lpResults->lpDx[i]= c;
2984 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
2986 int pos = 0;
2988 lpResults->lpCaretPos[0] = 0;
2989 for (i = 1; i < nSet; i++)
2990 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
2991 lpResults->lpCaretPos[i] = (pos += size.cx);
2994 if(lpResults->lpGlyphs)
2995 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
2997 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
2998 ret = MAKELONG(size.cx, size.cy);
3000 return ret;
3003 /*************************************************************************
3004 * GetCharABCWidthsFloatA [GDI32.@]
3006 * See GetCharABCWidthsFloatW.
3008 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3010 INT i, wlen;
3011 LPSTR str;
3012 LPWSTR wstr;
3013 BOOL ret = TRUE;
3015 str = FONT_GetCharsByRangeA(hdc, first, last, &i);
3016 if (str == NULL)
3017 return FALSE;
3019 wstr = FONT_mbtowc( hdc, str, i, &wlen, NULL );
3021 for (i = 0; i < wlen; i++)
3023 if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
3025 ret = FALSE;
3026 break;
3028 abcf++;
3031 HeapFree( GetProcessHeap(), 0, str );
3032 HeapFree( GetProcessHeap(), 0, wstr );
3034 return ret;
3037 /*************************************************************************
3038 * GetCharABCWidthsFloatW [GDI32.@]
3040 * Retrieves widths of a range of characters.
3042 * PARAMS
3043 * hdc [I] Handle to device context.
3044 * first [I] First character in range to query.
3045 * last [I] Last character in range to query.
3046 * abcf [O] Array of LPABCFLOAT structures.
3048 * RETURNS
3049 * Success: TRUE
3050 * Failure: FALSE
3052 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3054 UINT i;
3055 BOOL ret = FALSE;
3056 DC *dc = get_dc_ptr( hdc );
3058 TRACE("%p, %d, %d, %p\n", hdc, first, last, abcf);
3060 if (!dc) return FALSE;
3062 if (!abcf)
3064 release_dc_ptr( dc );
3065 return FALSE;
3068 if (dc->gdiFont)
3069 ret = WineEngGetCharABCWidthsFloat( dc->gdiFont, first, last, abcf );
3070 else
3071 FIXME("stub\n");
3073 if (ret)
3075 /* convert device units to logical */
3076 for (i = first; i <= last; i++, abcf++)
3078 abcf->abcfA = abcf->abcfA * dc->xformVport2World.eM11;
3079 abcf->abcfB = abcf->abcfB * dc->xformVport2World.eM11;
3080 abcf->abcfC = abcf->abcfC * dc->xformVport2World.eM11;
3084 release_dc_ptr( dc );
3085 return ret;
3088 /*************************************************************************
3089 * GetCharWidthFloatA [GDI32.@]
3091 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
3092 UINT iLastChar, PFLOAT pxBuffer)
3094 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3095 return 0;
3098 /*************************************************************************
3099 * GetCharWidthFloatW [GDI32.@]
3101 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
3102 UINT iLastChar, PFLOAT pxBuffer)
3104 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3105 return 0;
3109 /***********************************************************************
3111 * Font Resource API *
3113 ***********************************************************************/
3115 /***********************************************************************
3116 * AddFontResourceA (GDI32.@)
3118 INT WINAPI AddFontResourceA( LPCSTR str )
3120 return AddFontResourceExA( str, 0, NULL);
3123 /***********************************************************************
3124 * AddFontResourceW (GDI32.@)
3126 INT WINAPI AddFontResourceW( LPCWSTR str )
3128 return AddFontResourceExW(str, 0, NULL);
3132 /***********************************************************************
3133 * AddFontResourceExA (GDI32.@)
3135 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3137 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3138 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3139 INT ret;
3141 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3142 ret = AddFontResourceExW(strW, fl, pdv);
3143 HeapFree(GetProcessHeap(), 0, strW);
3144 return ret;
3147 static BOOL CALLBACK load_enumed_resource(HMODULE hModule, LPCWSTR type, LPWSTR name, LONG_PTR lParam)
3149 HRSRC rsrc = FindResourceW(hModule, name, type);
3150 HGLOBAL hMem = LoadResource(hModule, rsrc);
3151 LPVOID *pMem = LockResource(hMem);
3152 int *num_total = (int *)lParam;
3153 DWORD num_in_res;
3155 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type));
3156 if (!AddFontMemResourceEx(pMem, SizeofResource(hModule, rsrc), NULL, &num_in_res))
3158 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule, hMem);
3159 return FALSE;
3162 *num_total += num_in_res;
3163 return TRUE;
3166 /***********************************************************************
3167 * AddFontResourceExW (GDI32.@)
3169 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3171 int ret = WineEngAddFontResourceEx(str, fl, pdv);
3172 if (ret == 0)
3174 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3175 HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
3176 if (hModule != NULL)
3178 int num_resources = 0;
3179 LPWSTR rt_font = (LPWSTR)((ULONG_PTR)8); /* we don't want to include winuser.h */
3181 TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3182 wine_dbgstr_w(str));
3183 if (EnumResourceNamesW(hModule, rt_font, load_enumed_resource, (LONG_PTR)&num_resources))
3184 ret = num_resources;
3185 FreeLibrary(hModule);
3188 return ret;
3191 /***********************************************************************
3192 * RemoveFontResourceA (GDI32.@)
3194 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3196 return RemoveFontResourceExA(str, 0, 0);
3199 /***********************************************************************
3200 * RemoveFontResourceW (GDI32.@)
3202 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3204 return RemoveFontResourceExW(str, 0, 0);
3207 /***********************************************************************
3208 * AddFontMemResourceEx (GDI32.@)
3210 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3212 HANDLE ret;
3213 DWORD num_fonts;
3215 if (!pbFont || !cbFont || !pcFonts)
3217 SetLastError(ERROR_INVALID_PARAMETER);
3218 return NULL;
3221 ret = WineEngAddFontMemResourceEx(pbFont, cbFont, pdv, &num_fonts);
3222 if (ret)
3224 __TRY
3226 *pcFonts = num_fonts;
3228 __EXCEPT_PAGE_FAULT
3230 WARN("page fault while writing to *pcFonts (%p)\n", pcFonts);
3231 RemoveFontMemResourceEx(ret);
3232 ret = 0;
3234 __ENDTRY
3236 return ret;
3239 /***********************************************************************
3240 * RemoveFontMemResourceEx (GDI32.@)
3242 BOOL WINAPI RemoveFontMemResourceEx( HANDLE fh )
3244 FIXME("(%p) stub\n", fh);
3245 return TRUE;
3248 /***********************************************************************
3249 * RemoveFontResourceExA (GDI32.@)
3251 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3253 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3254 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3255 INT ret;
3257 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3258 ret = RemoveFontResourceExW(strW, fl, pdv);
3259 HeapFree(GetProcessHeap(), 0, strW);
3260 return ret;
3263 /***********************************************************************
3264 * RemoveFontResourceExW (GDI32.@)
3266 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3268 return WineEngRemoveFontResourceEx(str, fl, pdv);
3271 /***********************************************************************
3272 * GetTextCharset (GDI32.@)
3274 UINT WINAPI GetTextCharset(HDC hdc)
3276 /* MSDN docs say this is equivalent */
3277 return GetTextCharsetInfo(hdc, NULL, 0);
3280 /***********************************************************************
3281 * GetTextCharsetInfo (GDI32.@)
3283 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3285 UINT ret = DEFAULT_CHARSET;
3286 DC *dc = get_dc_ptr(hdc);
3288 if (dc)
3290 if (dc->gdiFont)
3291 ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
3293 release_dc_ptr( dc );
3296 if (ret == DEFAULT_CHARSET && fs)
3297 memset(fs, 0, sizeof(FONTSIGNATURE));
3298 return ret;
3301 /***********************************************************************
3302 * GdiGetCharDimensions (GDI32.@)
3304 * Gets the average width of the characters in the English alphabet.
3306 * PARAMS
3307 * hdc [I] Handle to the device context to measure on.
3308 * lptm [O] Pointer to memory to store the text metrics into.
3309 * height [O] On exit, the maximum height of characters in the English alphabet.
3311 * RETURNS
3312 * The average width of characters in the English alphabet.
3314 * NOTES
3315 * This function is used by the dialog manager to get the size of a dialog
3316 * unit. It should also be used by other pieces of code that need to know
3317 * the size of a dialog unit in logical units without having access to the
3318 * window handle of the dialog.
3319 * Windows caches the font metrics from this function, but we don't and
3320 * there doesn't appear to be an immediate advantage to do so.
3322 * SEE ALSO
3323 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3325 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3327 SIZE sz;
3328 static const WCHAR alphabet[] = {
3329 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3330 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3331 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3333 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3335 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3337 if (height) *height = sz.cy;
3338 return (sz.cx / 26 + 1) / 2;
3341 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3343 FIXME("(%d): stub\n", fEnableEUDC);
3344 return FALSE;
3347 /***********************************************************************
3348 * GetCharWidthI (GDI32.@)
3350 * Retrieve widths of characters.
3352 * PARAMS
3353 * hdc [I] Handle to a device context.
3354 * first [I] First glyph in range to query.
3355 * count [I] Number of glyph indices to query.
3356 * glyphs [I] Array of glyphs to query.
3357 * buffer [O] Buffer to receive character widths.
3359 * NOTES
3360 * Only works with TrueType fonts.
3362 * RETURNS
3363 * Success: TRUE
3364 * Failure: FALSE
3366 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3368 ABC *abc;
3369 unsigned int i;
3371 TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3373 if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3374 return FALSE;
3376 if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3378 HeapFree(GetProcessHeap(), 0, abc);
3379 return FALSE;
3382 for (i = 0; i < count; i++)
3383 buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3385 HeapFree(GetProcessHeap(), 0, abc);
3386 return TRUE;
3389 /***********************************************************************
3390 * GetFontUnicodeRanges (GDI32.@)
3392 * Retrieve a list of supported Unicode characters in a font.
3394 * PARAMS
3395 * hdc [I] Handle to a device context.
3396 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3398 * RETURNS
3399 * Success: Number of bytes written to the buffer pointed to by lpgs.
3400 * Failure: 0
3403 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3405 DWORD ret = 0;
3406 DC *dc = get_dc_ptr(hdc);
3408 TRACE("(%p, %p)\n", hdc, lpgs);
3410 if (!dc) return 0;
3412 if (dc->gdiFont) ret = WineEngGetFontUnicodeRanges(dc->gdiFont, lpgs);
3413 release_dc_ptr(dc);
3414 return ret;
3418 /*************************************************************
3419 * FontIsLinked (GDI32.@)
3421 BOOL WINAPI FontIsLinked(HDC hdc)
3423 DC *dc = get_dc_ptr(hdc);
3424 BOOL ret = FALSE;
3426 if (!dc) return FALSE;
3427 if (dc->gdiFont) ret = WineEngFontIsLinked(dc->gdiFont);
3428 release_dc_ptr(dc);
3429 TRACE("returning %d\n", ret);
3430 return ret;
3433 /*************************************************************
3434 * GdiRealizationInfo (GDI32.@)
3436 * Returns a structure that contains some font information.
3438 BOOL WINAPI GdiRealizationInfo(HDC hdc, realization_info_t *info)
3440 DC *dc = get_dc_ptr(hdc);
3441 BOOL ret = FALSE;
3443 if (!dc) return FALSE;
3444 if (dc->gdiFont) ret = WineEngRealizationInfo(dc->gdiFont, info);
3445 release_dc_ptr(dc);
3447 return ret;