gdi32: Implement GetTextExtentExPointW as a standard driver entry point.
[wine/multimedia.git] / dlls / gdi32 / font.c
blob72d9f83c58cd842b469f2c49b76eda557cdf95cc
1 /*
2 * GDI font objects
4 * Copyright 1993 Alexandre Julliard
5 * 1997 Alex Korobka
6 * Copyright 2002,2003 Shachar Shemesh
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "config.h"
24 #include "wine/port.h"
26 #include <stdarg.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <assert.h>
30 #include "winerror.h"
31 #include "windef.h"
32 #include "winbase.h"
33 #include "winnls.h"
34 #include "gdi_private.h"
35 #include "wine/exception.h"
36 #include "wine/unicode.h"
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(font);
41 /* Device -> World size conversion */
43 /* Performs a device to world transformation on the specified width (which
44 * is in integer format).
46 static inline INT INTERNAL_XDSTOWS(DC *dc, INT width)
48 double floatWidth;
50 /* Perform operation with floating point */
51 floatWidth = (double)width * dc->xformVport2World.eM11;
52 /* Round to integers */
53 return GDI_ROUND(floatWidth);
56 /* Performs a device to world transformation on the specified size (which
57 * is in integer format).
59 static inline INT INTERNAL_YDSTOWS(DC *dc, INT height)
61 double floatHeight;
63 /* Perform operation with floating point */
64 floatHeight = (double)height * dc->xformVport2World.eM22;
65 /* Round to integers */
66 return GDI_ROUND(floatHeight);
69 static inline INT INTERNAL_XWSTODS(DC *dc, INT width)
71 POINT pt[2];
72 pt[0].x = pt[0].y = 0;
73 pt[1].x = width;
74 pt[1].y = 0;
75 LPtoDP(dc->hSelf, pt, 2);
76 return pt[1].x - pt[0].x;
79 static inline INT INTERNAL_YWSTODS(DC *dc, INT height)
81 POINT pt[2];
82 pt[0].x = pt[0].y = 0;
83 pt[1].x = 0;
84 pt[1].y = height;
85 LPtoDP(dc->hSelf, pt, 2);
86 return pt[1].y - pt[0].y;
89 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc );
90 static INT FONT_GetObjectA( HGDIOBJ handle, INT count, LPVOID buffer );
91 static INT FONT_GetObjectW( HGDIOBJ handle, INT count, LPVOID buffer );
92 static BOOL FONT_DeleteObject( HGDIOBJ handle );
94 static const struct gdi_obj_funcs font_funcs =
96 FONT_SelectObject, /* pSelectObject */
97 FONT_GetObjectA, /* pGetObjectA */
98 FONT_GetObjectW, /* pGetObjectW */
99 NULL, /* pUnrealizeObject */
100 FONT_DeleteObject /* pDeleteObject */
103 #define ENUM_UNICODE 0x00000001
104 #define ENUM_CALLED 0x00000002
106 typedef struct
108 GDIOBJHDR header;
109 LOGFONTW logfont;
110 } FONTOBJ;
112 typedef struct
114 LPLOGFONTW lpLogFontParam;
115 FONTENUMPROCW lpEnumFunc;
116 LPARAM lpData;
117 DWORD dwFlags;
118 HDC hdc;
119 } fontEnum32;
122 * For TranslateCharsetInfo
124 #define MAXTCIINDEX 32
125 static const CHARSETINFO FONT_tci[MAXTCIINDEX] = {
126 /* ANSI */
127 { ANSI_CHARSET, 1252, {{0,0,0,0},{FS_LATIN1,0}} },
128 { EASTEUROPE_CHARSET, 1250, {{0,0,0,0},{FS_LATIN2,0}} },
129 { RUSSIAN_CHARSET, 1251, {{0,0,0,0},{FS_CYRILLIC,0}} },
130 { GREEK_CHARSET, 1253, {{0,0,0,0},{FS_GREEK,0}} },
131 { TURKISH_CHARSET, 1254, {{0,0,0,0},{FS_TURKISH,0}} },
132 { HEBREW_CHARSET, 1255, {{0,0,0,0},{FS_HEBREW,0}} },
133 { ARABIC_CHARSET, 1256, {{0,0,0,0},{FS_ARABIC,0}} },
134 { BALTIC_CHARSET, 1257, {{0,0,0,0},{FS_BALTIC,0}} },
135 { VIETNAMESE_CHARSET, 1258, {{0,0,0,0},{FS_VIETNAMESE,0}} },
136 /* reserved by ANSI */
137 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
138 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
139 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
140 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
141 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
142 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
143 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
144 /* ANSI and OEM */
145 { THAI_CHARSET, 874, {{0,0,0,0},{FS_THAI,0}} },
146 { SHIFTJIS_CHARSET, 932, {{0,0,0,0},{FS_JISJAPAN,0}} },
147 { GB2312_CHARSET, 936, {{0,0,0,0},{FS_CHINESESIMP,0}} },
148 { HANGEUL_CHARSET, 949, {{0,0,0,0},{FS_WANSUNG,0}} },
149 { CHINESEBIG5_CHARSET, 950, {{0,0,0,0},{FS_CHINESETRAD,0}} },
150 { JOHAB_CHARSET, 1361, {{0,0,0,0},{FS_JOHAB,0}} },
151 /* reserved for alternate ANSI and OEM */
152 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
153 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
154 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
155 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
156 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
157 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
158 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
159 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
160 /* reserved for system */
161 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
162 { SYMBOL_CHARSET, CP_SYMBOL, {{0,0,0,0},{FS_SYMBOL,0}} }
165 static void FONT_LogFontAToW( const LOGFONTA *fontA, LPLOGFONTW fontW )
167 memcpy(fontW, fontA, sizeof(LOGFONTA) - LF_FACESIZE);
168 MultiByteToWideChar(CP_ACP, 0, fontA->lfFaceName, -1, fontW->lfFaceName,
169 LF_FACESIZE);
170 fontW->lfFaceName[LF_FACESIZE-1] = 0;
173 static void FONT_LogFontWToA( const LOGFONTW *fontW, LPLOGFONTA fontA )
175 memcpy(fontA, fontW, sizeof(LOGFONTA) - LF_FACESIZE);
176 WideCharToMultiByte(CP_ACP, 0, fontW->lfFaceName, -1, fontA->lfFaceName,
177 LF_FACESIZE, NULL, NULL);
178 fontA->lfFaceName[LF_FACESIZE-1] = 0;
181 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEXA fontA )
183 FONT_LogFontWToA( &fontW->elfLogFont, &fontA->elfLogFont );
185 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
186 (LPSTR) fontA->elfFullName, LF_FULLFACESIZE, NULL, NULL );
187 fontA->elfFullName[LF_FULLFACESIZE-1] = '\0';
188 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
189 (LPSTR) fontA->elfStyle, LF_FACESIZE, NULL, NULL );
190 fontA->elfStyle[LF_FACESIZE-1] = '\0';
191 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
192 (LPSTR) fontA->elfScript, LF_FACESIZE, NULL, NULL );
193 fontA->elfScript[LF_FACESIZE-1] = '\0';
196 static void FONT_EnumLogFontExAToW( const ENUMLOGFONTEXA *fontA, LPENUMLOGFONTEXW fontW )
198 FONT_LogFontAToW( &fontA->elfLogFont, &fontW->elfLogFont );
200 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfFullName, -1,
201 fontW->elfFullName, LF_FULLFACESIZE );
202 fontW->elfFullName[LF_FULLFACESIZE-1] = '\0';
203 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfStyle, -1,
204 fontW->elfStyle, LF_FACESIZE );
205 fontW->elfStyle[LF_FACESIZE-1] = '\0';
206 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfScript, -1,
207 fontW->elfScript, LF_FACESIZE );
208 fontW->elfScript[LF_FACESIZE-1] = '\0';
211 /***********************************************************************
212 * TEXTMETRIC conversion functions.
214 static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
216 ptmA->tmHeight = ptmW->tmHeight;
217 ptmA->tmAscent = ptmW->tmAscent;
218 ptmA->tmDescent = ptmW->tmDescent;
219 ptmA->tmInternalLeading = ptmW->tmInternalLeading;
220 ptmA->tmExternalLeading = ptmW->tmExternalLeading;
221 ptmA->tmAveCharWidth = ptmW->tmAveCharWidth;
222 ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth;
223 ptmA->tmWeight = ptmW->tmWeight;
224 ptmA->tmOverhang = ptmW->tmOverhang;
225 ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX;
226 ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
227 ptmA->tmFirstChar = min(ptmW->tmFirstChar, 255);
228 if (ptmW->tmCharSet == SYMBOL_CHARSET)
230 ptmA->tmFirstChar = 0x1e;
231 ptmA->tmLastChar = 0xff; /* win9x behaviour - we need the OS2 table data to calculate correctly */
233 else if (ptmW->tmPitchAndFamily & TMPF_TRUETYPE)
235 ptmA->tmFirstChar = ptmW->tmDefaultChar - 1;
236 ptmA->tmLastChar = min(ptmW->tmLastChar, 0xff);
238 else
240 ptmA->tmFirstChar = min(ptmW->tmFirstChar, 0xff);
241 ptmA->tmLastChar = min(ptmW->tmLastChar, 0xff);
243 ptmA->tmDefaultChar = ptmW->tmDefaultChar;
244 ptmA->tmBreakChar = ptmW->tmBreakChar;
245 ptmA->tmItalic = ptmW->tmItalic;
246 ptmA->tmUnderlined = ptmW->tmUnderlined;
247 ptmA->tmStruckOut = ptmW->tmStruckOut;
248 ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
249 ptmA->tmCharSet = ptmW->tmCharSet;
253 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW *ptmW, NEWTEXTMETRICEXA *ptmA )
255 FONT_TextMetricWToA((const TEXTMETRICW *)ptmW, (LPTEXTMETRICA)ptmA);
256 ptmA->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
257 ptmA->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
258 ptmA->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
259 ptmA->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
260 memcpy(&ptmA->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
264 /***********************************************************************
265 * GdiGetCodePage (GDI32.@)
267 DWORD WINAPI GdiGetCodePage( HDC hdc )
269 UINT cp = CP_ACP;
270 DC *dc = get_dc_ptr( hdc );
272 if (dc)
274 cp = dc->font_code_page;
275 release_dc_ptr( dc );
277 return cp;
280 /***********************************************************************
281 * FONT_mbtowc
283 * Returns a Unicode translation of str using the charset of the
284 * currently selected font in hdc. If count is -1 then str is assumed
285 * to be '\0' terminated, otherwise it contains the number of bytes to
286 * convert. If plenW is non-NULL, on return it will point to the
287 * number of WCHARs that have been written. If pCP is non-NULL, on
288 * return it will point to the codepage used in the conversion. The
289 * caller should free the returned LPWSTR from the process heap
290 * itself.
292 static LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
294 UINT cp;
295 INT lenW;
296 LPWSTR strW;
298 cp = GdiGetCodePage( hdc );
300 if(count == -1) count = strlen(str);
301 lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
302 strW = HeapAlloc(GetProcessHeap(), 0, lenW*sizeof(WCHAR));
303 MultiByteToWideChar(cp, 0, str, count, strW, lenW);
304 TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW));
305 if(plenW) *plenW = lenW;
306 if(pCP) *pCP = cp;
307 return strW;
310 /***********************************************************************
311 * CreateFontIndirectExA (GDI32.@)
313 HFONT WINAPI CreateFontIndirectExA( const ENUMLOGFONTEXDVA *penumexA )
315 ENUMLOGFONTEXDVW enumexW;
317 if (!penumexA) return 0;
319 FONT_EnumLogFontExAToW( &penumexA->elfEnumLogfontEx, &enumexW.elfEnumLogfontEx );
320 enumexW.elfDesignVector = penumexA->elfDesignVector;
321 return CreateFontIndirectExW( &enumexW );
324 /***********************************************************************
325 * CreateFontIndirectExW (GDI32.@)
327 HFONT WINAPI CreateFontIndirectExW( const ENUMLOGFONTEXDVW *penumex )
329 HFONT hFont;
330 FONTOBJ *fontPtr;
331 const LOGFONTW *plf;
333 if (!penumex) return 0;
335 if (penumex->elfEnumLogfontEx.elfFullName[0] ||
336 penumex->elfEnumLogfontEx.elfStyle[0] ||
337 penumex->elfEnumLogfontEx.elfScript[0])
339 FIXME("some fields ignored. fullname=%s, style=%s, script=%s\n",
340 debugstr_w(penumex->elfEnumLogfontEx.elfFullName),
341 debugstr_w(penumex->elfEnumLogfontEx.elfStyle),
342 debugstr_w(penumex->elfEnumLogfontEx.elfScript));
345 plf = &penumex->elfEnumLogfontEx.elfLogFont;
346 if (!(fontPtr = HeapAlloc( GetProcessHeap(), 0, sizeof(*fontPtr) ))) return 0;
348 fontPtr->logfont = *plf;
350 if (plf->lfEscapement != plf->lfOrientation)
352 /* this should really depend on whether GM_ADVANCED is set */
353 fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
354 WARN("orientation angle %f set to "
355 "escapement angle %f for new font %p\n",
356 plf->lfOrientation/10., plf->lfEscapement/10., fontPtr);
359 if (!(hFont = alloc_gdi_handle( &fontPtr->header, OBJ_FONT, &font_funcs )))
361 HeapFree( GetProcessHeap(), 0, fontPtr );
362 return 0;
365 TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
366 plf->lfHeight, plf->lfWidth,
367 plf->lfEscapement, plf->lfOrientation,
368 plf->lfPitchAndFamily,
369 plf->lfOutPrecision, plf->lfClipPrecision,
370 plf->lfQuality, plf->lfCharSet,
371 debugstr_w(plf->lfFaceName),
372 plf->lfWeight > 400 ? "Bold" : "",
373 plf->lfItalic ? "Italic" : "",
374 plf->lfUnderline ? "Underline" : "", hFont);
376 return hFont;
379 /***********************************************************************
380 * CreateFontIndirectA (GDI32.@)
382 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *plfA )
384 LOGFONTW lfW;
386 if (!plfA) return 0;
388 FONT_LogFontAToW( plfA, &lfW );
389 return CreateFontIndirectW( &lfW );
392 /***********************************************************************
393 * CreateFontIndirectW (GDI32.@)
395 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
397 ENUMLOGFONTEXDVW exdv;
399 if (!plf) return 0;
401 exdv.elfEnumLogfontEx.elfLogFont = *plf;
402 exdv.elfEnumLogfontEx.elfFullName[0] = 0;
403 exdv.elfEnumLogfontEx.elfStyle[0] = 0;
404 exdv.elfEnumLogfontEx.elfScript[0] = 0;
405 return CreateFontIndirectExW( &exdv );
408 /*************************************************************************
409 * CreateFontA (GDI32.@)
411 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
412 INT orient, INT weight, DWORD italic,
413 DWORD underline, DWORD strikeout, DWORD charset,
414 DWORD outpres, DWORD clippres, DWORD quality,
415 DWORD pitch, LPCSTR name )
417 LOGFONTA logfont;
419 logfont.lfHeight = height;
420 logfont.lfWidth = width;
421 logfont.lfEscapement = esc;
422 logfont.lfOrientation = orient;
423 logfont.lfWeight = weight;
424 logfont.lfItalic = italic;
425 logfont.lfUnderline = underline;
426 logfont.lfStrikeOut = strikeout;
427 logfont.lfCharSet = charset;
428 logfont.lfOutPrecision = outpres;
429 logfont.lfClipPrecision = clippres;
430 logfont.lfQuality = quality;
431 logfont.lfPitchAndFamily = pitch;
433 if (name)
434 lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
435 else
436 logfont.lfFaceName[0] = '\0';
438 return CreateFontIndirectA( &logfont );
441 /*************************************************************************
442 * CreateFontW (GDI32.@)
444 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
445 INT orient, INT weight, DWORD italic,
446 DWORD underline, DWORD strikeout, DWORD charset,
447 DWORD outpres, DWORD clippres, DWORD quality,
448 DWORD pitch, LPCWSTR name )
450 LOGFONTW logfont;
452 logfont.lfHeight = height;
453 logfont.lfWidth = width;
454 logfont.lfEscapement = esc;
455 logfont.lfOrientation = orient;
456 logfont.lfWeight = weight;
457 logfont.lfItalic = italic;
458 logfont.lfUnderline = underline;
459 logfont.lfStrikeOut = strikeout;
460 logfont.lfCharSet = charset;
461 logfont.lfOutPrecision = outpres;
462 logfont.lfClipPrecision = clippres;
463 logfont.lfQuality = quality;
464 logfont.lfPitchAndFamily = pitch;
466 if (name)
467 lstrcpynW(logfont.lfFaceName, name,
468 sizeof(logfont.lfFaceName) / sizeof(WCHAR));
469 else
470 logfont.lfFaceName[0] = '\0';
472 return CreateFontIndirectW( &logfont );
475 static void update_font_code_page( DC *dc )
477 CHARSETINFO csi;
478 int charset = DEFAULT_CHARSET;
480 if (dc->gdiFont)
481 charset = WineEngGetTextCharsetInfo( dc->gdiFont, NULL, 0 );
483 /* Hmm, nicely designed api this one! */
484 if (TranslateCharsetInfo( ULongToPtr(charset), &csi, TCI_SRCCHARSET) )
485 dc->font_code_page = csi.ciACP;
486 else {
487 switch(charset) {
488 case OEM_CHARSET:
489 dc->font_code_page = GetOEMCP();
490 break;
491 case DEFAULT_CHARSET:
492 dc->font_code_page = GetACP();
493 break;
495 case VISCII_CHARSET:
496 case TCVN_CHARSET:
497 case KOI8_CHARSET:
498 case ISO3_CHARSET:
499 case ISO4_CHARSET:
500 case ISO10_CHARSET:
501 case CELTIC_CHARSET:
502 /* FIXME: These have no place here, but because x11drv
503 enumerates fonts with these (made up) charsets some apps
504 might use them and then the FIXME below would become
505 annoying. Now we could pick the intended codepage for
506 each of these, but since it's broken anyway we'll just
507 use CP_ACP and hope it'll go away...
509 dc->font_code_page = CP_ACP;
510 break;
512 default:
513 FIXME("Can't find codepage for charset %d\n", charset);
514 dc->font_code_page = CP_ACP;
515 break;
519 TRACE("charset %d => cp %d\n", charset, dc->font_code_page);
522 /***********************************************************************
523 * FONT_SelectObject
525 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc )
527 HGDIOBJ ret = 0;
528 DC *dc = get_dc_ptr( hdc );
529 PHYSDEV physdev;
531 if (!dc) return 0;
533 if (!GDI_inc_ref_count( handle ))
535 release_dc_ptr( dc );
536 return 0;
539 physdev = GET_DC_PHYSDEV( dc, pSelectFont );
540 if (physdev->funcs->pSelectFont( physdev, handle ))
542 ret = dc->hFont;
543 dc->hFont = handle;
544 update_font_code_page( dc );
545 GDI_dec_ref_count( ret );
547 else GDI_dec_ref_count( handle );
549 release_dc_ptr( dc );
550 return ret;
554 /***********************************************************************
555 * FONT_GetObjectA
557 static INT FONT_GetObjectA( HGDIOBJ handle, INT count, LPVOID buffer )
559 FONTOBJ *font = GDI_GetObjPtr( handle, OBJ_FONT );
560 LOGFONTA lfA;
562 if (!font) return 0;
563 if (buffer)
565 FONT_LogFontWToA( &font->logfont, &lfA );
566 if (count > sizeof(lfA)) count = sizeof(lfA);
567 memcpy( buffer, &lfA, count );
569 else count = sizeof(lfA);
570 GDI_ReleaseObj( handle );
571 return count;
574 /***********************************************************************
575 * FONT_GetObjectW
577 static INT FONT_GetObjectW( HGDIOBJ handle, INT count, LPVOID buffer )
579 FONTOBJ *font = GDI_GetObjPtr( handle, OBJ_FONT );
581 if (!font) return 0;
582 if (buffer)
584 if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
585 memcpy( buffer, &font->logfont, count );
587 else count = sizeof(LOGFONTW);
588 GDI_ReleaseObj( handle );
589 return count;
593 /***********************************************************************
594 * FONT_DeleteObject
596 static BOOL FONT_DeleteObject( HGDIOBJ handle )
598 FONTOBJ *obj;
600 WineEngDestroyFontInstance( handle );
602 if (!(obj = free_gdi_handle( handle ))) return FALSE;
603 return HeapFree( GetProcessHeap(), 0, obj );
607 /***********************************************************************
608 * FONT_EnumInstance
610 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
611 * We have to use other types because of the FONTENUMPROCW definition.
613 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
614 DWORD fType, LPARAM lp )
616 fontEnum32 *pfe = (fontEnum32*)lp;
617 INT ret = 1;
619 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
620 if ((!pfe->lpLogFontParam ||
621 pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
622 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
623 (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
625 /* convert font metrics */
626 ENUMLOGFONTEXA logfont;
627 NEWTEXTMETRICEXA tmA;
629 pfe->dwFlags |= ENUM_CALLED;
630 if (!(pfe->dwFlags & ENUM_UNICODE))
632 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
633 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
634 plf = (LOGFONTW *)&logfont.elfLogFont;
635 ptm = (TEXTMETRICW *)&tmA;
638 ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
640 return ret;
643 /***********************************************************************
644 * FONT_EnumFontFamiliesEx
646 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf,
647 FONTENUMPROCW efproc,
648 LPARAM lParam, DWORD dwUnicode)
650 INT ret = 1, ret2;
651 DC *dc = get_dc_ptr( hDC );
652 fontEnum32 fe32;
653 BOOL enum_gdi_fonts;
655 if (!dc) return 0;
657 if (plf)
658 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName),
659 plf->lfCharSet);
660 fe32.lpLogFontParam = plf;
661 fe32.lpEnumFunc = efproc;
662 fe32.lpData = lParam;
663 fe32.dwFlags = dwUnicode;
664 fe32.hdc = hDC;
666 enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE;
668 if (enum_gdi_fonts)
669 ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
670 fe32.dwFlags &= ~ENUM_CALLED;
671 if (ret)
673 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pEnumDeviceFonts );
674 ret2 = physdev->funcs->pEnumDeviceFonts( physdev, plf, FONT_EnumInstance, (LPARAM)&fe32 );
675 if(fe32.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
676 ret = ret2;
678 release_dc_ptr( dc );
679 return ret;
682 /***********************************************************************
683 * EnumFontFamiliesExW (GDI32.@)
685 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
686 FONTENUMPROCW efproc,
687 LPARAM lParam, DWORD dwFlags )
689 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, ENUM_UNICODE );
692 /***********************************************************************
693 * EnumFontFamiliesExA (GDI32.@)
695 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
696 FONTENUMPROCA efproc,
697 LPARAM lParam, DWORD dwFlags)
699 LOGFONTW lfW, *plfW;
701 if (plf)
703 FONT_LogFontAToW( plf, &lfW );
704 plfW = &lfW;
706 else plfW = NULL;
708 return FONT_EnumFontFamiliesEx( hDC, plfW, (FONTENUMPROCW)efproc, lParam, 0);
711 /***********************************************************************
712 * EnumFontFamiliesA (GDI32.@)
714 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
715 FONTENUMPROCA efproc, LPARAM lpData )
717 LOGFONTA lf, *plf;
719 if (lpFamily)
721 if (!*lpFamily) return 1;
722 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
723 lf.lfCharSet = DEFAULT_CHARSET;
724 lf.lfPitchAndFamily = 0;
725 plf = &lf;
727 else plf = NULL;
729 return EnumFontFamiliesExA( hDC, plf, efproc, lpData, 0 );
732 /***********************************************************************
733 * EnumFontFamiliesW (GDI32.@)
735 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
736 FONTENUMPROCW efproc, LPARAM lpData )
738 LOGFONTW lf, *plf;
740 if (lpFamily)
742 if (!*lpFamily) return 1;
743 lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
744 lf.lfCharSet = DEFAULT_CHARSET;
745 lf.lfPitchAndFamily = 0;
746 plf = &lf;
748 else plf = NULL;
750 return EnumFontFamiliesExW( hDC, plf, efproc, lpData, 0 );
753 /***********************************************************************
754 * EnumFontsA (GDI32.@)
756 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
757 LPARAM lpData )
759 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
762 /***********************************************************************
763 * EnumFontsW (GDI32.@)
765 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
766 LPARAM lpData )
768 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
772 /***********************************************************************
773 * GetTextCharacterExtra (GDI32.@)
775 INT WINAPI GetTextCharacterExtra( HDC hdc )
777 INT ret;
778 DC *dc = get_dc_ptr( hdc );
779 if (!dc) return 0x80000000;
780 ret = dc->charExtra;
781 release_dc_ptr( dc );
782 return ret;
786 /***********************************************************************
787 * SetTextCharacterExtra (GDI32.@)
789 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
791 INT ret = 0x80000000;
792 DC * dc = get_dc_ptr( hdc );
794 if (dc)
796 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetTextCharacterExtra );
797 extra = physdev->funcs->pSetTextCharacterExtra( physdev, extra );
798 if (extra != 0x80000000)
800 ret = dc->charExtra;
801 dc->charExtra = extra;
803 release_dc_ptr( dc );
805 return ret;
809 /***********************************************************************
810 * SetTextJustification (GDI32.@)
812 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
814 BOOL ret;
815 PHYSDEV physdev;
816 DC * dc = get_dc_ptr( hdc );
818 if (!dc) return FALSE;
820 physdev = GET_DC_PHYSDEV( dc, pSetTextJustification );
821 ret = physdev->funcs->pSetTextJustification( physdev, extra, breaks );
822 if (ret)
824 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
825 if (!extra) breaks = 0;
826 if (breaks)
828 dc->breakExtra = extra / breaks;
829 dc->breakRem = extra - (breaks * dc->breakExtra);
831 else
833 dc->breakExtra = 0;
834 dc->breakRem = 0;
837 release_dc_ptr( dc );
838 return ret;
842 /***********************************************************************
843 * GetTextFaceA (GDI32.@)
845 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
847 INT res = GetTextFaceW(hdc, 0, NULL);
848 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
849 GetTextFaceW( hdc, res, nameW );
851 if (name)
853 if (count)
855 res = WideCharToMultiByte(CP_ACP, 0, nameW, -1, name, count, NULL, NULL);
856 if (res == 0)
857 res = count;
858 name[count-1] = 0;
859 /* GetTextFaceA does NOT include the nul byte in the return count. */
860 res--;
862 else
863 res = 0;
865 else
866 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
867 HeapFree( GetProcessHeap(), 0, nameW );
868 return res;
871 /***********************************************************************
872 * GetTextFaceW (GDI32.@)
874 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
876 FONTOBJ *font;
877 INT ret = 0;
879 DC * dc = get_dc_ptr( hdc );
880 if (!dc) return 0;
882 if(dc->gdiFont)
883 ret = WineEngGetTextFace(dc->gdiFont, count, name);
884 else if ((font = GDI_GetObjPtr( dc->hFont, OBJ_FONT )))
886 INT n = strlenW(font->logfont.lfFaceName) + 1;
887 if (name)
889 lstrcpynW( name, font->logfont.lfFaceName, count );
890 ret = min(count, n);
892 else ret = n;
893 GDI_ReleaseObj( dc->hFont );
895 release_dc_ptr( dc );
896 return ret;
900 /***********************************************************************
901 * GetTextExtentPoint32A (GDI32.@)
903 * See GetTextExtentPoint32W.
905 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
906 LPSIZE size )
908 BOOL ret = FALSE;
909 INT wlen;
910 LPWSTR p;
912 if (count < 0) return FALSE;
914 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
916 if (p)
918 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
919 HeapFree( GetProcessHeap(), 0, p );
922 TRACE("(%p %s %d %p): returning %d x %d\n",
923 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
924 return ret;
928 /***********************************************************************
929 * GetTextExtentPoint32W [GDI32.@]
931 * Computes width/height for a string.
933 * Computes width and height of the specified string.
935 * RETURNS
936 * Success: TRUE
937 * Failure: FALSE
939 BOOL WINAPI GetTextExtentPoint32W(
940 HDC hdc, /* [in] Handle of device context */
941 LPCWSTR str, /* [in] Address of text string */
942 INT count, /* [in] Number of characters in string */
943 LPSIZE size) /* [out] Address of structure for string size */
945 return GetTextExtentExPointW(hdc, str, count, 0, NULL, NULL, size);
948 /***********************************************************************
949 * GetTextExtentExPointI [GDI32.@]
951 * Computes width and height of the array of glyph indices.
953 * PARAMS
954 * hdc [I] Handle of device context.
955 * indices [I] Glyph index array.
956 * count [I] Number of glyphs in array.
957 * max_ext [I] Maximum width in glyphs.
958 * nfit [O] Maximum number of characters.
959 * dxs [O] Partial string widths.
960 * size [O] Returned string size.
962 * RETURNS
963 * Success: TRUE
964 * Failure: FALSE
966 BOOL WINAPI GetTextExtentExPointI( HDC hdc, const WORD *indices, INT count, INT max_ext,
967 LPINT nfit, LPINT dxs, LPSIZE size )
969 BOOL ret = FALSE;
970 DC *dc;
972 if (count < 0) return FALSE;
974 dc = get_dc_ptr( hdc );
975 if (!dc) return FALSE;
977 if(dc->gdiFont)
979 ret = WineEngGetTextExtentExPointI(dc->gdiFont, indices, count, max_ext, nfit, dxs, size);
980 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
981 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
982 size->cx += count * dc->charExtra;
984 else
986 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pGetTextExtentExPoint );
987 FIXME("calling GetTextExtentExPoint\n");
988 ret = physdev->funcs->pGetTextExtentExPoint( physdev, indices, count, max_ext, nfit, dxs, size );
991 release_dc_ptr( dc );
993 TRACE("(%p %p %d %p): returning %d x %d\n",
994 hdc, indices, count, size, size->cx, size->cy );
995 return ret;
998 /***********************************************************************
999 * GetTextExtentPointI [GDI32.@]
1001 * Computes width and height of the array of glyph indices.
1003 * PARAMS
1004 * hdc [I] Handle of device context.
1005 * indices [I] Glyph index array.
1006 * count [I] Number of glyphs in array.
1007 * size [O] Returned string size.
1009 * RETURNS
1010 * Success: TRUE
1011 * Failure: FALSE
1013 BOOL WINAPI GetTextExtentPointI( HDC hdc, const WORD *indices, INT count, LPSIZE size )
1015 return GetTextExtentExPointI( hdc, indices, count, 0, NULL, NULL, size );
1019 /***********************************************************************
1020 * GetTextExtentPointA (GDI32.@)
1022 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
1023 LPSIZE size )
1025 TRACE("not bug compatible.\n");
1026 return GetTextExtentPoint32A( hdc, str, count, size );
1029 /***********************************************************************
1030 * GetTextExtentPointW (GDI32.@)
1032 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1033 LPSIZE size )
1035 TRACE("not bug compatible.\n");
1036 return GetTextExtentPoint32W( hdc, str, count, size );
1040 /***********************************************************************
1041 * GetTextExtentExPointA (GDI32.@)
1043 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1044 INT maxExt, LPINT lpnFit,
1045 LPINT alpDx, LPSIZE size )
1047 BOOL ret;
1048 INT wlen;
1049 INT *walpDx = NULL;
1050 LPWSTR p = NULL;
1052 if (count < 0) return FALSE;
1054 if (alpDx)
1056 walpDx = HeapAlloc( GetProcessHeap(), 0, count * sizeof(INT) );
1057 if (!walpDx) return FALSE;
1060 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1061 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
1062 if (walpDx)
1064 INT n = lpnFit ? *lpnFit : wlen;
1065 INT i, j;
1066 for(i = 0, j = 0; i < n; i++, j++)
1068 alpDx[j] = walpDx[i];
1069 if (IsDBCSLeadByte(str[j])) alpDx[++j] = walpDx[i];
1072 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1073 HeapFree( GetProcessHeap(), 0, p );
1074 HeapFree( GetProcessHeap(), 0, walpDx );
1075 return ret;
1079 /***********************************************************************
1080 * GetTextExtentExPointW (GDI32.@)
1082 * Return the size of the string as it would be if it was output properly by
1083 * e.g. TextOut.
1085 * This should include
1086 * - Intercharacter spacing
1087 * - justification spacing (not yet done)
1088 * - kerning? see below
1090 * Kerning. Since kerning would be carried out by the rendering code it should
1091 * be done by the driver. However they don't support it yet. Also I am not
1092 * yet persuaded that (certainly under Win95) any kerning is actually done.
1094 * str: According to MSDN this should be null-terminated. That is not true; a
1095 * null will not terminate it early.
1096 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1097 * than count. I have seen it be either the size of the full string or
1098 * 1 less than the size of the full string. I have not seen it bear any
1099 * resemblance to the portion that would fit.
1100 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1101 * trailing intercharacter spacing and any trailing justification.
1103 * FIXME
1104 * Currently we do this by measuring each character etc. We should do it by
1105 * passing the request to the driver, perhaps by extending the
1106 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1107 * thinking about kerning issues and rounding issues in the justification.
1110 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1111 INT maxExt, LPINT lpnFit,
1112 LPINT alpDx, LPSIZE size )
1114 INT nFit = 0;
1115 LPINT dxs = NULL;
1116 DC *dc;
1117 BOOL ret = FALSE;
1118 TEXTMETRICW tm;
1119 PHYSDEV dev;
1121 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1123 if (count < 0) return FALSE;
1125 dc = get_dc_ptr(hdc);
1126 if (!dc) return FALSE;
1128 GetTextMetricsW(hdc, &tm);
1130 /* If we need to calculate nFit, then we need the partial extents even if
1131 the user hasn't provided us with an array. */
1132 if (lpnFit)
1134 dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]);
1135 if (! dxs)
1137 release_dc_ptr(dc);
1138 SetLastError(ERROR_OUTOFMEMORY);
1139 return FALSE;
1142 else
1143 dxs = alpDx;
1145 dev = GET_DC_PHYSDEV( dc, pGetTextExtentExPoint );
1146 ret = dev->funcs->pGetTextExtentExPoint(dev, str, count, 0, NULL, dxs, size);
1148 /* Perform device size to world size transformations. */
1149 if (ret)
1151 INT extra = dc->charExtra,
1152 breakExtra = dc->breakExtra,
1153 breakRem = dc->breakRem,
1156 if (dxs)
1158 for (i = 0; i < count; ++i)
1160 dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
1161 dxs[i] += (i+1) * extra;
1162 if (count > 1 && (breakExtra || breakRem) && str[i] == tm.tmBreakChar)
1164 dxs[i] += breakExtra;
1165 if (breakRem > 0)
1167 breakRem--;
1168 dxs[i]++;
1171 if (dxs[i] <= maxExt)
1172 ++nFit;
1174 breakRem = dc->breakRem;
1176 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1177 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1179 if (!dxs && count > 1 && (breakExtra || breakRem))
1181 for (i = 0; i < count; i++)
1183 if (str[i] == tm.tmBreakChar)
1185 size->cx += breakExtra;
1186 if (breakRem > 0)
1188 breakRem--;
1189 (size->cx)++;
1196 if (lpnFit)
1197 *lpnFit = nFit;
1199 if (! alpDx)
1200 HeapFree(GetProcessHeap(), 0, dxs);
1202 release_dc_ptr( dc );
1204 TRACE("returning %d %d x %d\n",nFit,size->cx,size->cy);
1205 return ret;
1208 /***********************************************************************
1209 * GetTextMetricsA (GDI32.@)
1211 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1213 TEXTMETRICW tm32;
1215 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1216 FONT_TextMetricWToA( &tm32, metrics );
1217 return TRUE;
1220 /***********************************************************************
1221 * GetTextMetricsW (GDI32.@)
1223 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1225 BOOL ret = FALSE;
1226 DC * dc = get_dc_ptr( hdc );
1227 if (!dc) return FALSE;
1229 if (dc->gdiFont)
1230 ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1231 else
1233 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pGetTextMetrics );
1234 ret = physdev->funcs->pGetTextMetrics( physdev, metrics );
1237 if (ret)
1239 /* device layer returns values in device units
1240 * therefore we have to convert them to logical */
1242 metrics->tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1243 metrics->tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1245 #define WDPTOLP(x) ((x<0)? \
1246 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1247 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1248 #define HDPTOLP(y) ((y<0)? \
1249 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1250 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1252 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1253 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1254 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1255 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1256 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1257 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1258 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1259 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1260 ret = TRUE;
1261 #undef WDPTOLP
1262 #undef HDPTOLP
1263 TRACE("text metrics:\n"
1264 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1265 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1266 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1267 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1268 " PitchAndFamily = %02x\n"
1269 " --------------------\n"
1270 " InternalLeading = %i\n"
1271 " Ascent = %i\n"
1272 " Descent = %i\n"
1273 " Height = %i\n",
1274 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1275 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1276 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1277 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1278 metrics->tmPitchAndFamily,
1279 metrics->tmInternalLeading,
1280 metrics->tmAscent,
1281 metrics->tmDescent,
1282 metrics->tmHeight );
1284 release_dc_ptr( dc );
1285 return ret;
1289 /***********************************************************************
1290 * GetOutlineTextMetricsA (GDI32.@)
1291 * Gets metrics for TrueType fonts.
1293 * NOTES
1294 * If the supplied buffer isn't big enough Windows partially fills it up to
1295 * its given length and returns that length.
1297 * RETURNS
1298 * Success: Non-zero or size of required buffer
1299 * Failure: 0
1301 UINT WINAPI GetOutlineTextMetricsA(
1302 HDC hdc, /* [in] Handle of device context */
1303 UINT cbData, /* [in] Size of metric data array */
1304 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1306 char buf[512], *ptr;
1307 UINT ret, needed;
1308 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1309 OUTLINETEXTMETRICA *output = lpOTM;
1310 INT left, len;
1312 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1313 return 0;
1314 if(ret > sizeof(buf))
1315 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1316 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1318 needed = sizeof(OUTLINETEXTMETRICA);
1319 if(lpOTMW->otmpFamilyName)
1320 needed += WideCharToMultiByte(CP_ACP, 0,
1321 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1322 NULL, 0, NULL, NULL);
1323 if(lpOTMW->otmpFaceName)
1324 needed += WideCharToMultiByte(CP_ACP, 0,
1325 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1326 NULL, 0, NULL, NULL);
1327 if(lpOTMW->otmpStyleName)
1328 needed += WideCharToMultiByte(CP_ACP, 0,
1329 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1330 NULL, 0, NULL, NULL);
1331 if(lpOTMW->otmpFullName)
1332 needed += WideCharToMultiByte(CP_ACP, 0,
1333 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1334 NULL, 0, NULL, NULL);
1336 if(!lpOTM) {
1337 ret = needed;
1338 goto end;
1341 TRACE("needed = %d\n", needed);
1342 if(needed > cbData)
1343 /* Since the supplied buffer isn't big enough, we'll alloc one
1344 that is and memcpy the first cbData bytes into the lpOTM at
1345 the end. */
1346 output = HeapAlloc(GetProcessHeap(), 0, needed);
1348 ret = output->otmSize = min(needed, cbData);
1349 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1350 output->otmFiller = 0;
1351 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1352 output->otmfsSelection = lpOTMW->otmfsSelection;
1353 output->otmfsType = lpOTMW->otmfsType;
1354 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1355 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1356 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1357 output->otmEMSquare = lpOTMW->otmEMSquare;
1358 output->otmAscent = lpOTMW->otmAscent;
1359 output->otmDescent = lpOTMW->otmDescent;
1360 output->otmLineGap = lpOTMW->otmLineGap;
1361 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1362 output->otmsXHeight = lpOTMW->otmsXHeight;
1363 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1364 output->otmMacAscent = lpOTMW->otmMacAscent;
1365 output->otmMacDescent = lpOTMW->otmMacDescent;
1366 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1367 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1368 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1369 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1370 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1371 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1372 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1373 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1374 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1375 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1378 ptr = (char*)(output + 1);
1379 left = needed - sizeof(*output);
1381 if(lpOTMW->otmpFamilyName) {
1382 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1383 len = WideCharToMultiByte(CP_ACP, 0,
1384 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1385 ptr, left, NULL, NULL);
1386 left -= len;
1387 ptr += len;
1388 } else
1389 output->otmpFamilyName = 0;
1391 if(lpOTMW->otmpFaceName) {
1392 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1393 len = WideCharToMultiByte(CP_ACP, 0,
1394 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1395 ptr, left, NULL, NULL);
1396 left -= len;
1397 ptr += len;
1398 } else
1399 output->otmpFaceName = 0;
1401 if(lpOTMW->otmpStyleName) {
1402 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1403 len = WideCharToMultiByte(CP_ACP, 0,
1404 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1405 ptr, left, NULL, NULL);
1406 left -= len;
1407 ptr += len;
1408 } else
1409 output->otmpStyleName = 0;
1411 if(lpOTMW->otmpFullName) {
1412 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1413 len = WideCharToMultiByte(CP_ACP, 0,
1414 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1415 ptr, left, NULL, NULL);
1416 left -= len;
1417 } else
1418 output->otmpFullName = 0;
1420 assert(left == 0);
1422 if(output != lpOTM) {
1423 memcpy(lpOTM, output, cbData);
1424 HeapFree(GetProcessHeap(), 0, output);
1426 /* check if the string offsets really fit into the provided size */
1427 /* FIXME: should we check string length as well? */
1428 /* make sure that we don't read/write beyond the provided buffer */
1429 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(LPSTR))
1431 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1432 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1435 /* make sure that we don't read/write beyond the provided buffer */
1436 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(LPSTR))
1438 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1439 lpOTM->otmpFaceName = 0; /* doesn't fit */
1442 /* make sure that we don't read/write beyond the provided buffer */
1443 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(LPSTR))
1445 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1446 lpOTM->otmpStyleName = 0; /* doesn't fit */
1449 /* make sure that we don't read/write beyond the provided buffer */
1450 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(LPSTR))
1452 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1453 lpOTM->otmpFullName = 0; /* doesn't fit */
1457 end:
1458 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1459 HeapFree(GetProcessHeap(), 0, lpOTMW);
1461 return ret;
1465 /***********************************************************************
1466 * GetOutlineTextMetricsW [GDI32.@]
1468 UINT WINAPI GetOutlineTextMetricsW(
1469 HDC hdc, /* [in] Handle of device context */
1470 UINT cbData, /* [in] Size of metric data array */
1471 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1473 DC *dc = get_dc_ptr( hdc );
1474 OUTLINETEXTMETRICW *output = lpOTM;
1475 UINT ret;
1477 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1478 if(!dc) return 0;
1480 if(dc->gdiFont) {
1481 ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, output);
1482 if(lpOTM && ret) {
1483 if(ret > cbData) {
1484 output = HeapAlloc(GetProcessHeap(), 0, ret);
1485 WineEngGetOutlineTextMetrics(dc->gdiFont, ret, output);
1488 output->otmTextMetrics.tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1489 output->otmTextMetrics.tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1491 #define WDPTOLP(x) ((x<0)? \
1492 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1493 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1494 #define HDPTOLP(y) ((y<0)? \
1495 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1496 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1498 output->otmTextMetrics.tmHeight = HDPTOLP(output->otmTextMetrics.tmHeight);
1499 output->otmTextMetrics.tmAscent = HDPTOLP(output->otmTextMetrics.tmAscent);
1500 output->otmTextMetrics.tmDescent = HDPTOLP(output->otmTextMetrics.tmDescent);
1501 output->otmTextMetrics.tmInternalLeading = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1502 output->otmTextMetrics.tmExternalLeading = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1503 output->otmTextMetrics.tmAveCharWidth = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1504 output->otmTextMetrics.tmMaxCharWidth = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1505 output->otmTextMetrics.tmOverhang = WDPTOLP(output->otmTextMetrics.tmOverhang);
1506 output->otmAscent = HDPTOLP(output->otmAscent);
1507 output->otmDescent = HDPTOLP(output->otmDescent);
1508 output->otmLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmLineGap));
1509 output->otmsCapEmHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsCapEmHeight));
1510 output->otmsXHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsXHeight));
1511 output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1512 output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1513 output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1514 output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1515 output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1516 output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1517 output->otmMacLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmMacLineGap));
1518 output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1519 output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1520 output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1521 output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1522 output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1523 output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1524 output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1525 output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1526 output->otmsStrikeoutSize = abs(INTERNAL_YDSTOWS(dc,output->otmsStrikeoutSize));
1527 output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1528 output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1529 output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1530 #undef WDPTOLP
1531 #undef HDPTOLP
1532 if(output != lpOTM) {
1533 memcpy(lpOTM, output, cbData);
1534 HeapFree(GetProcessHeap(), 0, output);
1535 ret = cbData;
1540 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1541 but really this should just be a return 0. */
1543 ret = sizeof(*lpOTM);
1544 if (lpOTM) {
1545 if(cbData < ret)
1546 ret = 0;
1547 else {
1548 memset(lpOTM, 0, ret);
1549 lpOTM->otmSize = sizeof(*lpOTM);
1550 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1552 Further fill of the structure not implemented,
1553 Needs real values for the structure members
1558 release_dc_ptr(dc);
1559 return ret;
1562 static LPSTR FONT_GetCharsByRangeA(HDC hdc, UINT firstChar, UINT lastChar, PINT pByteLen)
1564 INT i, count = lastChar - firstChar + 1;
1565 UINT c;
1566 LPSTR str;
1568 if (count <= 0)
1569 return NULL;
1571 switch (GdiGetCodePage(hdc))
1573 case 932:
1574 case 936:
1575 case 949:
1576 case 950:
1577 case 1361:
1578 if (lastChar > 0xffff)
1579 return NULL;
1580 if ((firstChar ^ lastChar) > 0xff)
1581 return NULL;
1582 break;
1583 default:
1584 if (lastChar > 0xff)
1585 return NULL;
1586 break;
1589 str = HeapAlloc(GetProcessHeap(), 0, count * 2 + 1);
1590 if (str == NULL)
1591 return NULL;
1593 for(i = 0, c = firstChar; c <= lastChar; i++, c++)
1595 if (c > 0xff)
1596 str[i++] = (BYTE)(c >> 8);
1597 str[i] = (BYTE)c;
1599 str[i] = '\0';
1601 *pByteLen = i;
1603 return str;
1606 /***********************************************************************
1607 * GetCharWidthW (GDI32.@)
1608 * GetCharWidth32W (GDI32.@)
1610 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1611 LPINT buffer )
1613 UINT i;
1614 BOOL ret;
1615 DC * dc = get_dc_ptr( hdc );
1616 if (!dc) return FALSE;
1618 if (dc->gdiFont)
1619 ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1620 else
1622 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pGetCharWidth );
1623 ret = physdev->funcs->pGetCharWidth( physdev, firstChar, lastChar, buffer);
1626 if (ret)
1628 /* convert device units to logical */
1629 for( i = firstChar; i <= lastChar; i++, buffer++ )
1630 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1631 ret = TRUE;
1633 release_dc_ptr( dc );
1634 return ret;
1638 /***********************************************************************
1639 * GetCharWidthA (GDI32.@)
1640 * GetCharWidth32A (GDI32.@)
1642 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1643 LPINT buffer )
1645 INT i, wlen;
1646 LPSTR str;
1647 LPWSTR wstr;
1648 BOOL ret = TRUE;
1650 str = FONT_GetCharsByRangeA(hdc, firstChar, lastChar, &i);
1651 if(str == NULL)
1652 return FALSE;
1654 wstr = FONT_mbtowc(hdc, str, i, &wlen, NULL);
1656 for(i = 0; i < wlen; i++)
1658 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1660 ret = FALSE;
1661 break;
1663 buffer++;
1666 HeapFree(GetProcessHeap(), 0, str);
1667 HeapFree(GetProcessHeap(), 0, wstr);
1669 return ret;
1673 /***********************************************************************
1674 * ExtTextOutA (GDI32.@)
1676 * See ExtTextOutW.
1678 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1679 const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1681 INT wlen;
1682 UINT codepage;
1683 LPWSTR p;
1684 BOOL ret;
1685 LPINT lpDxW = NULL;
1687 if (flags & ETO_GLYPH_INDEX)
1688 return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
1690 p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
1692 if (lpDx) {
1693 unsigned int i = 0, j = 0;
1695 /* allocate enough for a ETO_PDY */
1696 lpDxW = HeapAlloc( GetProcessHeap(), 0, 2*wlen*sizeof(INT));
1697 while(i < count) {
1698 if(IsDBCSLeadByteEx(codepage, str[i]))
1700 if(flags & ETO_PDY)
1702 lpDxW[j++] = lpDx[i * 2] + lpDx[(i + 1) * 2];
1703 lpDxW[j++] = lpDx[i * 2 + 1] + lpDx[(i + 1) * 2 + 1];
1705 else
1706 lpDxW[j++] = lpDx[i] + lpDx[i + 1];
1707 i = i + 2;
1709 else
1711 if(flags & ETO_PDY)
1713 lpDxW[j++] = lpDx[i * 2];
1714 lpDxW[j++] = lpDx[i * 2 + 1];
1716 else
1717 lpDxW[j++] = lpDx[i];
1718 i = i + 1;
1723 ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1725 HeapFree( GetProcessHeap(), 0, p );
1726 HeapFree( GetProcessHeap(), 0, lpDxW );
1727 return ret;
1731 /***********************************************************************
1732 * ExtTextOutW (GDI32.@)
1734 * Draws text using the currently selected font, background color, and text color.
1737 * PARAMS
1738 * x,y [I] coordinates of string
1739 * flags [I]
1740 * ETO_GRAYED - undocumented on MSDN
1741 * ETO_OPAQUE - use background color for fill the rectangle
1742 * ETO_CLIPPED - clipping text to the rectangle
1743 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1744 * than encoded characters. Implies ETO_IGNORELANGUAGE
1745 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1746 * Affects BiDi ordering
1747 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1748 * ETO_PDY - unimplemented
1749 * ETO_NUMERICSLATIN - unimplemented always assumed -
1750 * do not translate numbers into locale representations
1751 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1752 * lprect [I] dimensions for clipping or/and opaquing
1753 * str [I] text string
1754 * count [I] number of symbols in string
1755 * lpDx [I] optional parameter with distance between drawing characters
1757 * RETURNS
1758 * Success: TRUE
1759 * Failure: FALSE
1761 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1762 const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1764 BOOL ret = FALSE;
1765 LPWSTR reordered_str = (LPWSTR)str;
1766 WORD *glyphs = NULL;
1767 UINT align = GetTextAlign( hdc );
1768 DWORD layout = GetLayout( hdc );
1769 POINT pt;
1770 TEXTMETRICW tm;
1771 LOGFONTW lf;
1772 double cosEsc, sinEsc;
1773 INT char_extra;
1774 SIZE sz;
1775 RECT rc;
1776 BOOL done_extents = FALSE;
1777 POINT *deltas = NULL, width = {0, 0};
1778 DWORD type;
1779 DC * dc = get_dc_ptr( hdc );
1780 PHYSDEV physdev;
1781 INT breakRem;
1782 static int quietfixme = 0;
1784 if (!dc) return FALSE;
1786 breakRem = dc->breakRem;
1788 if (quietfixme == 0 && flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN))
1790 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN unimplemented\n");
1791 quietfixme = 1;
1794 update_dc( dc );
1795 physdev = GET_DC_PHYSDEV( dc, pExtTextOut );
1796 type = GetObjectType(hdc);
1797 if(type == OBJ_METADC || type == OBJ_ENHMETADC)
1799 ret = physdev->funcs->pExtTextOut( physdev, x, y, flags, lprect, str, count, lpDx );
1800 release_dc_ptr( dc );
1801 return ret;
1804 if (!lprect)
1805 flags &= ~ETO_CLIPPED;
1807 if (flags & ETO_RTLREADING) align |= TA_RTLREADING;
1808 if (layout & LAYOUT_RTL)
1810 if ((align & TA_CENTER) != TA_CENTER) align ^= TA_RIGHT;
1811 align ^= TA_RTLREADING;
1814 if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && count > 0 )
1816 INT cGlyphs;
1817 reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1819 BIDI_Reorder( hdc, str, count, GCP_REORDER,
1820 (align & TA_RTLREADING) ? WINE_GCPW_FORCE_RTL : WINE_GCPW_FORCE_LTR,
1821 reordered_str, count, NULL, &glyphs, &cGlyphs);
1823 flags |= ETO_IGNORELANGUAGE;
1824 if (glyphs)
1826 flags |= ETO_GLYPH_INDEX;
1827 if (cGlyphs != count)
1828 count = cGlyphs;
1831 else if(flags & ETO_GLYPH_INDEX)
1832 glyphs = reordered_str;
1834 TRACE("%p, %d, %d, %08x, %s, %s, %d, %p)\n", hdc, x, y, flags,
1835 wine_dbgstr_rect(lprect), debugstr_wn(str, count), count, lpDx);
1836 TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
1838 if(align & TA_UPDATECP)
1840 GetCurrentPositionEx( hdc, &pt );
1841 x = pt.x;
1842 y = pt.y;
1845 GetTextMetricsW(hdc, &tm);
1846 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1848 if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
1849 lf.lfEscapement = 0;
1851 if(lf.lfEscapement != 0)
1853 cosEsc = cos(lf.lfEscapement * M_PI / 1800);
1854 sinEsc = sin(lf.lfEscapement * M_PI / 1800);
1856 else
1858 cosEsc = 1;
1859 sinEsc = 0;
1862 if(flags & (ETO_CLIPPED | ETO_OPAQUE))
1864 if(!lprect)
1866 if(flags & ETO_GLYPH_INDEX)
1867 GetTextExtentPointI(hdc, glyphs, count, &sz);
1868 else
1869 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1871 done_extents = TRUE;
1872 rc.left = x;
1873 rc.top = y;
1874 rc.right = x + sz.cx;
1875 rc.bottom = y + sz.cy;
1877 else
1879 rc = *lprect;
1882 LPtoDP(hdc, (POINT*)&rc, 2);
1884 if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
1885 if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
1888 if ((flags & ETO_OPAQUE) && !PATH_IsPathOpen(dc->path))
1889 physdev->funcs->pExtTextOut( physdev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL );
1891 if(count == 0)
1893 ret = TRUE;
1894 goto done;
1897 pt.x = x;
1898 pt.y = y;
1899 LPtoDP(hdc, &pt, 1);
1900 x = pt.x;
1901 y = pt.y;
1903 char_extra = GetTextCharacterExtra(hdc);
1904 if(char_extra || dc->breakExtra || breakRem || lpDx || lf.lfEscapement != 0)
1906 UINT i;
1907 SIZE tmpsz;
1908 POINT total = {0, 0}, desired[2];
1910 deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
1911 for(i = 0; i < count; i++)
1913 if(lpDx)
1915 if(flags & ETO_PDY)
1917 deltas[i].x = lpDx[i * 2] + char_extra;
1918 deltas[i].y = -lpDx[i * 2 + 1];
1920 else
1922 deltas[i].x = lpDx[i] + char_extra;
1923 deltas[i].y = 0;
1927 else
1929 if(flags & ETO_GLYPH_INDEX)
1930 GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
1931 else
1932 GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
1934 deltas[i].x = tmpsz.cx;
1935 deltas[i].y = 0;
1938 if (!(flags & ETO_GLYPH_INDEX) && (dc->breakExtra || breakRem) && reordered_str[i] == tm.tmBreakChar)
1940 deltas[i].x = deltas[i].x + dc->breakExtra;
1941 if (breakRem > 0)
1943 breakRem--;
1944 deltas[i].x++;
1947 total.x += deltas[i].x;
1948 total.y += deltas[i].y;
1950 desired[0].x = desired[0].y = 0;
1952 desired[1].x = cosEsc * total.x + sinEsc * total.y;
1953 desired[1].y = -sinEsc * total.x + cosEsc * total.y;
1955 LPtoDP(hdc, desired, 2);
1956 desired[1].x -= desired[0].x;
1957 desired[1].y -= desired[0].y;
1958 if (layout & LAYOUT_RTL) desired[1].x = -desired[1].x;
1960 deltas[i].x = desired[1].x - width.x;
1961 deltas[i].y = desired[1].y - width.y;
1963 width = desired[1];
1965 flags |= ETO_PDY;
1967 else
1969 if(!done_extents)
1971 if(flags & ETO_GLYPH_INDEX)
1972 GetTextExtentPointI(hdc, glyphs, count, &sz);
1973 else
1974 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1975 done_extents = TRUE;
1977 width.x = abs(INTERNAL_XWSTODS(dc, sz.cx));
1978 width.y = 0;
1981 tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
1982 tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
1983 switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
1985 case TA_LEFT:
1986 if (align & TA_UPDATECP)
1988 pt.x = x + width.x;
1989 pt.y = y + width.y;
1990 DPtoLP(hdc, &pt, 1);
1991 MoveToEx(hdc, pt.x, pt.y, NULL);
1993 break;
1995 case TA_CENTER:
1996 x -= width.x / 2;
1997 y -= width.y / 2;
1998 break;
2000 case TA_RIGHT:
2001 x -= width.x;
2002 y -= width.y;
2003 if (align & TA_UPDATECP)
2005 pt.x = x;
2006 pt.y = y;
2007 DPtoLP(hdc, &pt, 1);
2008 MoveToEx(hdc, pt.x, pt.y, NULL);
2010 break;
2013 switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
2015 case TA_TOP:
2016 y += tm.tmAscent * cosEsc;
2017 x += tm.tmAscent * sinEsc;
2018 break;
2020 case TA_BOTTOM:
2021 y -= tm.tmDescent * cosEsc;
2022 x -= tm.tmDescent * sinEsc;
2023 break;
2025 case TA_BASELINE:
2026 break;
2029 if (GetBkMode(hdc) != TRANSPARENT && !PATH_IsPathOpen(dc->path))
2031 if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
2033 if(!(flags & ETO_OPAQUE) || x < rc.left || x + width.x >= rc.right ||
2034 y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
2036 RECT rc;
2037 rc.left = x;
2038 rc.right = x + width.x;
2039 rc.top = y - tm.tmAscent;
2040 rc.bottom = y + tm.tmDescent;
2042 if(flags & ETO_CLIPPED)
2044 rc.left = max(lprect->left, rc.left);
2045 rc.right = min(lprect->right, rc.right);
2046 rc.top = max(lprect->top, rc.top);
2047 rc.bottom = min(lprect->bottom, rc.bottom);
2049 if(rc.left < rc.right && rc.top < rc.bottom)
2050 physdev->funcs->pExtTextOut( physdev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL );
2055 if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
2057 HFONT orig_font = dc->hFont, cur_font;
2058 UINT glyph;
2059 INT span = 0;
2060 POINT *offsets = NULL;
2061 unsigned int i;
2063 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2064 for(i = 0; i < count; i++)
2066 WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
2067 if(cur_font != dc->hFont)
2069 if(!offsets)
2071 unsigned int j;
2072 offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
2073 offsets[0].x = offsets[0].y = 0;
2075 if(!deltas)
2077 SIZE tmpsz;
2078 for(j = 1; j < count; j++)
2080 GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
2081 offsets[j].x = offsets[j - 1].x + abs(INTERNAL_XWSTODS(dc, tmpsz.cx));
2082 offsets[j].y = 0;
2085 else
2087 for(j = 1; j < count; j++)
2089 offsets[j].x = offsets[j - 1].x + deltas[j].x;
2090 offsets[j].y = offsets[j - 1].y + deltas[j].y;
2094 if(span)
2096 if (PATH_IsPathOpen(dc->path))
2097 ret = PATH_ExtTextOut(dc, x + offsets[i - span].x, y + offsets[i - span].y,
2098 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2099 glyphs, span, deltas ? (INT*)(deltas + (i - span)) : NULL);
2100 else
2101 physdev->funcs->pExtTextOut( physdev, x + offsets[i - span].x,
2102 y + offsets[i - span].y,
2103 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc, glyphs,
2104 span, deltas ? (INT*)(deltas + (i - span)) : NULL);
2105 span = 0;
2107 SelectObject(hdc, cur_font);
2109 glyphs[span++] = glyph;
2111 if(i == count - 1)
2113 if (PATH_IsPathOpen(dc->path))
2114 ret = PATH_ExtTextOut(dc, x + (offsets ? offsets[count - span].x : 0),
2115 y + (offsets ? offsets[count - span].y : 0),
2116 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2117 glyphs, span, deltas ? (INT*)(deltas + (count - span)) : NULL);
2118 else
2119 ret = physdev->funcs->pExtTextOut(physdev, x + (offsets ? offsets[count - span].x : 0),
2120 y + (offsets ? offsets[count - span].y : 0),
2121 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc, glyphs,
2122 span, deltas ? (INT*)(deltas + (count - span)) : NULL);
2123 SelectObject(hdc, orig_font);
2124 HeapFree(GetProcessHeap(), 0, offsets);
2128 else
2130 if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
2132 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2133 GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
2134 flags |= ETO_GLYPH_INDEX;
2137 if (PATH_IsPathOpen(dc->path))
2138 ret = PATH_ExtTextOut(dc, x, y, (flags & ~ETO_OPAQUE), &rc,
2139 glyphs ? glyphs : reordered_str, count, (INT*)deltas);
2140 else
2141 ret = physdev->funcs->pExtTextOut( physdev, x, y, (flags & ~ETO_OPAQUE), &rc,
2142 glyphs ? glyphs : reordered_str, count, (INT*)deltas );
2145 done:
2146 HeapFree(GetProcessHeap(), 0, deltas);
2147 if(glyphs != reordered_str)
2148 HeapFree(GetProcessHeap(), 0, glyphs);
2149 if(reordered_str != str)
2150 HeapFree(GetProcessHeap(), 0, reordered_str);
2152 release_dc_ptr( dc );
2154 if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2156 int underlinePos, strikeoutPos;
2157 int underlineWidth, strikeoutWidth;
2158 UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2159 OUTLINETEXTMETRICW* otm = NULL;
2161 if(!size)
2163 underlinePos = 0;
2164 underlineWidth = tm.tmAscent / 20 + 1;
2165 strikeoutPos = tm.tmAscent / 2;
2166 strikeoutWidth = underlineWidth;
2168 else
2170 otm = HeapAlloc(GetProcessHeap(), 0, size);
2171 GetOutlineTextMetricsW(hdc, size, otm);
2172 underlinePos = otm->otmsUnderscorePosition;
2173 underlineWidth = otm->otmsUnderscoreSize;
2174 strikeoutPos = otm->otmsStrikeoutPosition;
2175 strikeoutWidth = otm->otmsStrikeoutSize;
2176 HeapFree(GetProcessHeap(), 0, otm);
2179 if (PATH_IsPathOpen(dc->path))
2181 POINT pts[5];
2182 HPEN hpen;
2183 HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2185 hbrush = SelectObject(hdc, hbrush);
2186 hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2188 if (lf.lfUnderline)
2190 pts[0].x = x - underlinePos * sinEsc;
2191 pts[0].y = y - underlinePos * cosEsc;
2192 pts[1].x = x + width.x - underlinePos * sinEsc;
2193 pts[1].y = y + width.y - underlinePos * cosEsc;
2194 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2195 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2196 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2197 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2198 pts[4].x = pts[0].x;
2199 pts[4].y = pts[0].y;
2200 DPtoLP(hdc, pts, 5);
2201 Polygon(hdc, pts, 5);
2204 if (lf.lfStrikeOut)
2206 pts[0].x = x - strikeoutPos * sinEsc;
2207 pts[0].y = y - strikeoutPos * cosEsc;
2208 pts[1].x = x + width.x - strikeoutPos * sinEsc;
2209 pts[1].y = y + width.y - strikeoutPos * cosEsc;
2210 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2211 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2212 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2213 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2214 pts[4].x = pts[0].x;
2215 pts[4].y = pts[0].y;
2216 DPtoLP(hdc, pts, 5);
2217 Polygon(hdc, pts, 5);
2220 SelectObject(hdc, hpen);
2221 hbrush = SelectObject(hdc, hbrush);
2222 DeleteObject(hbrush);
2224 else
2226 POINT pts[2], oldpt;
2227 HPEN hpen;
2229 if (lf.lfUnderline)
2231 hpen = CreatePen(PS_SOLID, underlineWidth, GetTextColor(hdc));
2232 hpen = SelectObject(hdc, hpen);
2233 pts[0].x = x;
2234 pts[0].y = y;
2235 pts[1].x = x + width.x;
2236 pts[1].y = y + width.y;
2237 DPtoLP(hdc, pts, 2);
2238 MoveToEx(hdc, pts[0].x - underlinePos * sinEsc, pts[0].y - underlinePos * cosEsc, &oldpt);
2239 LineTo(hdc, pts[1].x - underlinePos * sinEsc, pts[1].y - underlinePos * cosEsc);
2240 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2241 DeleteObject(SelectObject(hdc, hpen));
2244 if (lf.lfStrikeOut)
2246 hpen = CreatePen(PS_SOLID, strikeoutWidth, GetTextColor(hdc));
2247 hpen = SelectObject(hdc, hpen);
2248 pts[0].x = x;
2249 pts[0].y = y;
2250 pts[1].x = x + width.x;
2251 pts[1].y = y + width.y;
2252 DPtoLP(hdc, pts, 2);
2253 MoveToEx(hdc, pts[0].x - strikeoutPos * sinEsc, pts[0].y - strikeoutPos * cosEsc, &oldpt);
2254 LineTo(hdc, pts[1].x - strikeoutPos * sinEsc, pts[1].y - strikeoutPos * cosEsc);
2255 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2256 DeleteObject(SelectObject(hdc, hpen));
2261 return ret;
2265 /***********************************************************************
2266 * TextOutA (GDI32.@)
2268 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2270 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2274 /***********************************************************************
2275 * TextOutW (GDI32.@)
2277 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2279 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2283 /***********************************************************************
2284 * PolyTextOutA (GDI32.@)
2286 * See PolyTextOutW.
2288 BOOL WINAPI PolyTextOutA( HDC hdc, const POLYTEXTA *pptxt, INT cStrings )
2290 for (; cStrings>0; cStrings--, pptxt++)
2291 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2292 return FALSE;
2293 return TRUE;
2298 /***********************************************************************
2299 * PolyTextOutW (GDI32.@)
2301 * Draw several Strings
2303 * RETURNS
2304 * TRUE: Success.
2305 * FALSE: Failure.
2307 BOOL WINAPI PolyTextOutW( HDC hdc, const POLYTEXTW *pptxt, INT cStrings )
2309 for (; cStrings>0; cStrings--, pptxt++)
2310 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2311 return FALSE;
2312 return TRUE;
2316 /***********************************************************************
2317 * SetMapperFlags (GDI32.@)
2319 DWORD WINAPI SetMapperFlags( HDC hdc, DWORD flags )
2321 DC *dc = get_dc_ptr( hdc );
2322 DWORD ret = GDI_ERROR;
2324 if (dc)
2326 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetMapperFlags );
2327 flags = physdev->funcs->pSetMapperFlags( physdev, flags );
2328 if (flags != GDI_ERROR)
2330 ret = dc->mapperFlags;
2331 dc->mapperFlags = flags;
2333 release_dc_ptr( dc );
2335 return ret;
2338 /***********************************************************************
2339 * GetAspectRatioFilterEx (GDI32.@)
2341 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2343 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2344 return FALSE;
2348 /***********************************************************************
2349 * GetCharABCWidthsA (GDI32.@)
2351 * See GetCharABCWidthsW.
2353 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2354 LPABC abc )
2356 INT i, wlen;
2357 LPSTR str;
2358 LPWSTR wstr;
2359 BOOL ret = TRUE;
2361 str = FONT_GetCharsByRangeA(hdc, firstChar, lastChar, &i);
2362 if (str == NULL)
2363 return FALSE;
2365 wstr = FONT_mbtowc(hdc, str, i, &wlen, NULL);
2366 if (wstr == NULL)
2368 HeapFree(GetProcessHeap(), 0, str);
2369 return FALSE;
2372 for(i = 0; i < wlen; i++)
2374 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2376 ret = FALSE;
2377 break;
2379 abc++;
2382 HeapFree(GetProcessHeap(), 0, str);
2383 HeapFree(GetProcessHeap(), 0, wstr);
2385 return ret;
2389 /******************************************************************************
2390 * GetCharABCWidthsW [GDI32.@]
2392 * Retrieves widths of characters in range.
2394 * PARAMS
2395 * hdc [I] Handle of device context
2396 * firstChar [I] First character in range to query
2397 * lastChar [I] Last character in range to query
2398 * abc [O] Address of character-width structure
2400 * NOTES
2401 * Only works with TrueType fonts
2403 * RETURNS
2404 * Success: TRUE
2405 * Failure: FALSE
2407 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2408 LPABC abc )
2410 DC *dc = get_dc_ptr(hdc);
2411 unsigned int i;
2412 BOOL ret = FALSE;
2414 if (!dc) return FALSE;
2416 if (!abc)
2418 release_dc_ptr( dc );
2419 return FALSE;
2422 if(dc->gdiFont)
2423 ret = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
2424 else
2425 FIXME(": stub\n");
2427 if (ret)
2429 /* convert device units to logical */
2430 for( i = firstChar; i <= lastChar; i++, abc++ ) {
2431 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2432 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2433 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2435 ret = TRUE;
2438 release_dc_ptr( dc );
2439 return ret;
2443 /******************************************************************************
2444 * GetCharABCWidthsI [GDI32.@]
2446 * Retrieves widths of characters in range.
2448 * PARAMS
2449 * hdc [I] Handle of device context
2450 * firstChar [I] First glyphs in range to query
2451 * count [I] Last glyphs in range to query
2452 * pgi [i] Array of glyphs to query
2453 * abc [O] Address of character-width structure
2455 * NOTES
2456 * Only works with TrueType fonts
2458 * RETURNS
2459 * Success: TRUE
2460 * Failure: FALSE
2462 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2463 LPWORD pgi, LPABC abc)
2465 DC *dc = get_dc_ptr(hdc);
2466 unsigned int i;
2467 BOOL ret = FALSE;
2469 if (!dc) return FALSE;
2471 if (!abc)
2473 release_dc_ptr( dc );
2474 return FALSE;
2477 if(dc->gdiFont)
2478 ret = WineEngGetCharABCWidthsI( dc->gdiFont, firstChar, count, pgi, abc );
2479 else
2480 FIXME(": stub\n");
2482 if (ret)
2484 /* convert device units to logical */
2485 for( i = 0; i < count; i++, abc++ ) {
2486 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2487 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2488 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2490 ret = TRUE;
2493 release_dc_ptr( dc );
2494 return ret;
2498 /***********************************************************************
2499 * GetGlyphOutlineA (GDI32.@)
2501 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2502 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2503 LPVOID lpBuffer, const MAT2 *lpmat2 )
2505 if (!lpmat2) return GDI_ERROR;
2507 if(!(fuFormat & GGO_GLYPH_INDEX)) {
2508 UINT cp;
2509 int len;
2510 char mbchs[2];
2512 cp = GdiGetCodePage(hdc);
2513 if (IsDBCSLeadByteEx(cp, uChar >> 8)) {
2514 len = 2;
2515 mbchs[0] = (uChar & 0xff00) >> 8;
2516 mbchs[1] = (uChar & 0xff);
2517 } else {
2518 len = 1;
2519 mbchs[0] = (uChar & 0xff);
2521 uChar = 0;
2522 MultiByteToWideChar(cp, 0, mbchs, len, (LPWSTR)&uChar, 1);
2525 return GetGlyphOutlineW(hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer,
2526 lpmat2);
2529 /***********************************************************************
2530 * GetGlyphOutlineW (GDI32.@)
2532 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2533 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2534 LPVOID lpBuffer, const MAT2 *lpmat2 )
2536 DC *dc;
2537 DWORD ret;
2539 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2540 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2542 if (!lpmat2) return GDI_ERROR;
2544 dc = get_dc_ptr(hdc);
2545 if(!dc) return GDI_ERROR;
2547 if(dc->gdiFont)
2548 ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
2549 cbBuffer, lpBuffer, lpmat2);
2550 else
2551 ret = GDI_ERROR;
2553 release_dc_ptr( dc );
2554 return ret;
2558 /***********************************************************************
2559 * CreateScalableFontResourceA (GDI32.@)
2561 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2562 LPCSTR lpszResourceFile,
2563 LPCSTR lpszFontFile,
2564 LPCSTR lpszCurrentPath )
2566 LPWSTR lpszResourceFileW = NULL;
2567 LPWSTR lpszFontFileW = NULL;
2568 LPWSTR lpszCurrentPathW = NULL;
2569 int len;
2570 BOOL ret;
2572 if (lpszResourceFile)
2574 len = MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, NULL, 0);
2575 lpszResourceFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2576 MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, lpszResourceFileW, len);
2579 if (lpszFontFile)
2581 len = MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, NULL, 0);
2582 lpszFontFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2583 MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, lpszFontFileW, len);
2586 if (lpszCurrentPath)
2588 len = MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, NULL, 0);
2589 lpszCurrentPathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2590 MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, lpszCurrentPathW, len);
2593 ret = CreateScalableFontResourceW(fHidden, lpszResourceFileW,
2594 lpszFontFileW, lpszCurrentPathW);
2596 HeapFree(GetProcessHeap(), 0, lpszResourceFileW);
2597 HeapFree(GetProcessHeap(), 0, lpszFontFileW);
2598 HeapFree(GetProcessHeap(), 0, lpszCurrentPathW);
2600 return ret;
2603 /***********************************************************************
2604 * CreateScalableFontResourceW (GDI32.@)
2606 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2607 LPCWSTR lpszResourceFile,
2608 LPCWSTR lpszFontFile,
2609 LPCWSTR lpszCurrentPath )
2611 HANDLE f;
2612 FIXME("(%d,%s,%s,%s): stub\n",
2613 fHidden, debugstr_w(lpszResourceFile), debugstr_w(lpszFontFile),
2614 debugstr_w(lpszCurrentPath) );
2616 /* fHidden=1 - only visible for the calling app, read-only, not
2617 * enumerated with EnumFonts/EnumFontFamilies
2618 * lpszCurrentPath can be NULL
2621 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2622 if ((f = CreateFileW(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2623 CloseHandle(f);
2624 SetLastError(ERROR_FILE_EXISTS);
2625 return FALSE;
2627 return FALSE; /* create failed */
2630 /*************************************************************************
2631 * GetKerningPairsA (GDI32.@)
2633 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2634 LPKERNINGPAIR kern_pairA )
2636 UINT cp;
2637 CPINFO cpi;
2638 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2639 KERNINGPAIR *kern_pairW;
2641 if (!cPairs && kern_pairA)
2643 SetLastError(ERROR_INVALID_PARAMETER);
2644 return 0;
2647 cp = GdiGetCodePage(hDC);
2649 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2650 * to fail on an invalid character for CP_SYMBOL.
2652 cpi.DefaultChar[0] = 0;
2653 if (cp != CP_SYMBOL && !GetCPInfo(cp, &cpi))
2655 FIXME("Can't find codepage %u info\n", cp);
2656 return 0;
2659 total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2660 if (!total_kern_pairs) return 0;
2662 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2663 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2665 for (i = 0; i < total_kern_pairs; i++)
2667 char first, second;
2669 if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2670 continue;
2672 if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2673 continue;
2675 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2676 continue;
2678 if (kern_pairA)
2680 if (kern_pairs_copied >= cPairs) break;
2682 kern_pairA->wFirst = (BYTE)first;
2683 kern_pairA->wSecond = (BYTE)second;
2684 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2685 kern_pairA++;
2687 kern_pairs_copied++;
2690 HeapFree(GetProcessHeap(), 0, kern_pairW);
2692 return kern_pairs_copied;
2695 /*************************************************************************
2696 * GetKerningPairsW (GDI32.@)
2698 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2699 LPKERNINGPAIR lpKerningPairs )
2701 DC *dc;
2702 DWORD ret = 0;
2704 TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2706 if (!cPairs && lpKerningPairs)
2708 SetLastError(ERROR_INVALID_PARAMETER);
2709 return 0;
2712 dc = get_dc_ptr(hDC);
2713 if (!dc) return 0;
2715 if (dc->gdiFont)
2716 ret = WineEngGetKerningPairs(dc->gdiFont, cPairs, lpKerningPairs);
2718 release_dc_ptr( dc );
2719 return ret;
2722 /*************************************************************************
2723 * TranslateCharsetInfo [GDI32.@]
2725 * Fills a CHARSETINFO structure for a character set, code page, or
2726 * font. This allows making the correspondence between different labels
2727 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2728 * of the same encoding.
2730 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2731 * only one codepage should be set in *lpSrc.
2733 * RETURNS
2734 * TRUE on success, FALSE on failure.
2737 BOOL WINAPI TranslateCharsetInfo(
2738 LPDWORD lpSrc, /* [in]
2739 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2740 if flags == TCI_SRCCHARSET: a character set value
2741 if flags == TCI_SRCCODEPAGE: a code page value
2743 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2744 DWORD flags /* [in] determines interpretation of lpSrc */)
2746 int index = 0;
2747 switch (flags) {
2748 case TCI_SRCFONTSIG:
2749 while (index < MAXTCIINDEX && !(*lpSrc>>index & 0x0001)) index++;
2750 break;
2751 case TCI_SRCCODEPAGE:
2752 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciACP) index++;
2753 break;
2754 case TCI_SRCCHARSET:
2755 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciCharset) index++;
2756 break;
2757 default:
2758 return FALSE;
2760 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2761 *lpCs = FONT_tci[index];
2762 return TRUE;
2765 /*************************************************************************
2766 * GetFontLanguageInfo (GDI32.@)
2768 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2770 FONTSIGNATURE fontsig;
2771 static const DWORD GCP_DBCS_MASK=0x003F0000,
2772 GCP_DIACRITIC_MASK=0x00000000,
2773 FLI_GLYPHS_MASK=0x00000000,
2774 GCP_GLYPHSHAPE_MASK=0x00000040,
2775 GCP_KASHIDA_MASK=0x00000000,
2776 GCP_LIGATE_MASK=0x00000000,
2777 GCP_USEKERNING_MASK=0x00000000,
2778 GCP_REORDER_MASK=0x00000060;
2780 DWORD result=0;
2782 GetTextCharsetInfo( hdc, &fontsig, 0 );
2783 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2785 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2786 result|=GCP_DBCS;
2788 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2789 result|=GCP_DIACRITIC;
2791 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2792 result|=FLI_GLYPHS;
2794 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2795 result|=GCP_GLYPHSHAPE;
2797 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2798 result|=GCP_KASHIDA;
2800 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2801 result|=GCP_LIGATE;
2803 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2804 result|=GCP_USEKERNING;
2806 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2807 if( GetTextAlign( hdc) & TA_RTLREADING )
2808 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2809 result|=GCP_REORDER;
2811 return result;
2815 /*************************************************************************
2816 * GetFontData [GDI32.@]
2818 * Retrieve data for TrueType font.
2820 * RETURNS
2822 * success: Number of bytes returned
2823 * failure: GDI_ERROR
2825 * NOTES
2827 * Calls SetLastError()
2830 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2831 LPVOID buffer, DWORD length)
2833 DC *dc = get_dc_ptr(hdc);
2834 DWORD ret = GDI_ERROR;
2836 if(!dc) return GDI_ERROR;
2838 if(dc->gdiFont)
2839 ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2841 release_dc_ptr( dc );
2842 return ret;
2845 /*************************************************************************
2846 * GetGlyphIndicesA [GDI32.@]
2848 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2849 LPWORD pgi, DWORD flags)
2851 DWORD ret;
2852 WCHAR *lpstrW;
2853 INT countW;
2855 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2856 hdc, debugstr_an(lpstr, count), count, pgi, flags);
2858 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2859 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2860 HeapFree(GetProcessHeap(), 0, lpstrW);
2862 return ret;
2865 /*************************************************************************
2866 * GetGlyphIndicesW [GDI32.@]
2868 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2869 LPWORD pgi, DWORD flags)
2871 DC *dc = get_dc_ptr(hdc);
2872 DWORD ret = GDI_ERROR;
2874 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2875 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2877 if(!dc) return GDI_ERROR;
2879 if(dc->gdiFont)
2880 ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2882 release_dc_ptr( dc );
2883 return ret;
2886 /*************************************************************************
2887 * GetCharacterPlacementA [GDI32.@]
2889 * See GetCharacterPlacementW.
2891 * NOTES:
2892 * the web browser control of ie4 calls this with dwFlags=0
2894 DWORD WINAPI
2895 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2896 INT nMaxExtent, GCP_RESULTSA *lpResults,
2897 DWORD dwFlags)
2899 WCHAR *lpStringW;
2900 INT uCountW;
2901 GCP_RESULTSW resultsW;
2902 DWORD ret;
2903 UINT font_cp;
2905 TRACE("%s, %d, %d, 0x%08x\n",
2906 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2908 /* both structs are equal in size */
2909 memcpy(&resultsW, lpResults, sizeof(resultsW));
2911 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2912 if(lpResults->lpOutString)
2913 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2915 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2917 lpResults->nGlyphs = resultsW.nGlyphs;
2918 lpResults->nMaxFit = resultsW.nMaxFit;
2920 if(lpResults->lpOutString) {
2921 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2922 lpResults->lpOutString, uCount, NULL, NULL );
2925 HeapFree(GetProcessHeap(), 0, lpStringW);
2926 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2928 return ret;
2931 /*************************************************************************
2932 * GetCharacterPlacementW [GDI32.@]
2934 * Retrieve information about a string. This includes the width, reordering,
2935 * Glyphing and so on.
2937 * RETURNS
2939 * The width and height of the string if successful, 0 if failed.
2941 * BUGS
2943 * All flags except GCP_REORDER are not yet implemented.
2944 * Reordering is not 100% compliant to the Windows BiDi method.
2945 * Caret positioning is not yet implemented for BiDi.
2946 * Classes are not yet implemented.
2949 DWORD WINAPI
2950 GetCharacterPlacementW(
2951 HDC hdc, /* [in] Device context for which the rendering is to be done */
2952 LPCWSTR lpString, /* [in] The string for which information is to be returned */
2953 INT uCount, /* [in] Number of WORDS in string. */
2954 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
2955 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2956 DWORD dwFlags /* [in] Flags specifying how to process the string */
2959 DWORD ret=0;
2960 SIZE size;
2961 UINT i, nSet;
2963 TRACE("%s, %d, %d, 0x%08x\n",
2964 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2966 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2967 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2968 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2969 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2970 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2972 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08x ignored\n", dwFlags);
2973 if(lpResults->lpClass) FIXME("classes not implemented\n");
2974 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2975 FIXME("Caret positions for complex scripts not implemented\n");
2977 nSet = (UINT)uCount;
2978 if(nSet > lpResults->nGlyphs)
2979 nSet = lpResults->nGlyphs;
2981 /* return number of initialized fields */
2982 lpResults->nGlyphs = nSet;
2984 if((dwFlags&GCP_REORDER)==0 )
2986 /* Treat the case where no special handling was requested in a fastpath way */
2987 /* copy will do if the GCP_REORDER flag is not set */
2988 if(lpResults->lpOutString)
2989 memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
2991 if(lpResults->lpOrder)
2993 for(i = 0; i < nSet; i++)
2994 lpResults->lpOrder[i] = i;
2996 } else
2998 BIDI_Reorder(NULL, lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
2999 nSet, lpResults->lpOrder, NULL, NULL );
3002 /* FIXME: Will use the placement chars */
3003 if (lpResults->lpDx)
3005 int c;
3006 for (i = 0; i < nSet; i++)
3008 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
3009 lpResults->lpDx[i]= c;
3013 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
3015 int pos = 0;
3017 lpResults->lpCaretPos[0] = 0;
3018 for (i = 1; i < nSet; i++)
3019 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
3020 lpResults->lpCaretPos[i] = (pos += size.cx);
3023 if(lpResults->lpGlyphs)
3024 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
3026 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
3027 ret = MAKELONG(size.cx, size.cy);
3029 return ret;
3032 /*************************************************************************
3033 * GetCharABCWidthsFloatA [GDI32.@]
3035 * See GetCharABCWidthsFloatW.
3037 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3039 INT i, wlen;
3040 LPSTR str;
3041 LPWSTR wstr;
3042 BOOL ret = TRUE;
3044 str = FONT_GetCharsByRangeA(hdc, first, last, &i);
3045 if (str == NULL)
3046 return FALSE;
3048 wstr = FONT_mbtowc( hdc, str, i, &wlen, NULL );
3050 for (i = 0; i < wlen; i++)
3052 if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
3054 ret = FALSE;
3055 break;
3057 abcf++;
3060 HeapFree( GetProcessHeap(), 0, str );
3061 HeapFree( GetProcessHeap(), 0, wstr );
3063 return ret;
3066 /*************************************************************************
3067 * GetCharABCWidthsFloatW [GDI32.@]
3069 * Retrieves widths of a range of characters.
3071 * PARAMS
3072 * hdc [I] Handle to device context.
3073 * first [I] First character in range to query.
3074 * last [I] Last character in range to query.
3075 * abcf [O] Array of LPABCFLOAT structures.
3077 * RETURNS
3078 * Success: TRUE
3079 * Failure: FALSE
3081 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3083 UINT i;
3084 BOOL ret = FALSE;
3085 DC *dc = get_dc_ptr( hdc );
3087 TRACE("%p, %d, %d, %p\n", hdc, first, last, abcf);
3089 if (!dc) return FALSE;
3091 if (!abcf)
3093 release_dc_ptr( dc );
3094 return FALSE;
3097 if (dc->gdiFont)
3098 ret = WineEngGetCharABCWidthsFloat( dc->gdiFont, first, last, abcf );
3099 else
3100 FIXME("stub\n");
3102 if (ret)
3104 /* convert device units to logical */
3105 for (i = first; i <= last; i++, abcf++)
3107 abcf->abcfA = abcf->abcfA * dc->xformVport2World.eM11;
3108 abcf->abcfB = abcf->abcfB * dc->xformVport2World.eM11;
3109 abcf->abcfC = abcf->abcfC * dc->xformVport2World.eM11;
3113 release_dc_ptr( dc );
3114 return ret;
3117 /*************************************************************************
3118 * GetCharWidthFloatA [GDI32.@]
3120 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
3121 UINT iLastChar, PFLOAT pxBuffer)
3123 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3124 return 0;
3127 /*************************************************************************
3128 * GetCharWidthFloatW [GDI32.@]
3130 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
3131 UINT iLastChar, PFLOAT pxBuffer)
3133 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3134 return 0;
3138 /***********************************************************************
3140 * Font Resource API *
3142 ***********************************************************************/
3144 /***********************************************************************
3145 * AddFontResourceA (GDI32.@)
3147 INT WINAPI AddFontResourceA( LPCSTR str )
3149 return AddFontResourceExA( str, 0, NULL);
3152 /***********************************************************************
3153 * AddFontResourceW (GDI32.@)
3155 INT WINAPI AddFontResourceW( LPCWSTR str )
3157 return AddFontResourceExW(str, 0, NULL);
3161 /***********************************************************************
3162 * AddFontResourceExA (GDI32.@)
3164 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3166 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3167 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3168 INT ret;
3170 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3171 ret = AddFontResourceExW(strW, fl, pdv);
3172 HeapFree(GetProcessHeap(), 0, strW);
3173 return ret;
3176 static BOOL CALLBACK load_enumed_resource(HMODULE hModule, LPCWSTR type, LPWSTR name, LONG_PTR lParam)
3178 HRSRC rsrc = FindResourceW(hModule, name, type);
3179 HGLOBAL hMem = LoadResource(hModule, rsrc);
3180 LPVOID *pMem = LockResource(hMem);
3181 int *num_total = (int *)lParam;
3182 DWORD num_in_res;
3184 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type));
3185 if (!AddFontMemResourceEx(pMem, SizeofResource(hModule, rsrc), NULL, &num_in_res))
3187 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule, hMem);
3188 return FALSE;
3191 *num_total += num_in_res;
3192 return TRUE;
3195 /***********************************************************************
3196 * AddFontResourceExW (GDI32.@)
3198 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3200 int ret = WineEngAddFontResourceEx(str, fl, pdv);
3201 if (ret == 0)
3203 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3204 HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
3205 if (hModule != NULL)
3207 int num_resources = 0;
3208 LPWSTR rt_font = (LPWSTR)((ULONG_PTR)8); /* we don't want to include winuser.h */
3210 TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3211 wine_dbgstr_w(str));
3212 if (EnumResourceNamesW(hModule, rt_font, load_enumed_resource, (LONG_PTR)&num_resources))
3213 ret = num_resources;
3214 FreeLibrary(hModule);
3217 return ret;
3220 /***********************************************************************
3221 * RemoveFontResourceA (GDI32.@)
3223 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3225 return RemoveFontResourceExA(str, 0, 0);
3228 /***********************************************************************
3229 * RemoveFontResourceW (GDI32.@)
3231 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3233 return RemoveFontResourceExW(str, 0, 0);
3236 /***********************************************************************
3237 * AddFontMemResourceEx (GDI32.@)
3239 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3241 HANDLE ret;
3242 DWORD num_fonts;
3244 if (!pbFont || !cbFont || !pcFonts)
3246 SetLastError(ERROR_INVALID_PARAMETER);
3247 return NULL;
3250 ret = WineEngAddFontMemResourceEx(pbFont, cbFont, pdv, &num_fonts);
3251 if (ret)
3253 __TRY
3255 *pcFonts = num_fonts;
3257 __EXCEPT_PAGE_FAULT
3259 WARN("page fault while writing to *pcFonts (%p)\n", pcFonts);
3260 RemoveFontMemResourceEx(ret);
3261 ret = 0;
3263 __ENDTRY
3265 return ret;
3268 /***********************************************************************
3269 * RemoveFontMemResourceEx (GDI32.@)
3271 BOOL WINAPI RemoveFontMemResourceEx( HANDLE fh )
3273 FIXME("(%p) stub\n", fh);
3274 return TRUE;
3277 /***********************************************************************
3278 * RemoveFontResourceExA (GDI32.@)
3280 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3282 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3283 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3284 INT ret;
3286 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3287 ret = RemoveFontResourceExW(strW, fl, pdv);
3288 HeapFree(GetProcessHeap(), 0, strW);
3289 return ret;
3292 /***********************************************************************
3293 * RemoveFontResourceExW (GDI32.@)
3295 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3297 return WineEngRemoveFontResourceEx(str, fl, pdv);
3300 /***********************************************************************
3301 * GetTextCharset (GDI32.@)
3303 UINT WINAPI GetTextCharset(HDC hdc)
3305 /* MSDN docs say this is equivalent */
3306 return GetTextCharsetInfo(hdc, NULL, 0);
3309 /***********************************************************************
3310 * GetTextCharsetInfo (GDI32.@)
3312 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3314 UINT ret = DEFAULT_CHARSET;
3315 DC *dc = get_dc_ptr(hdc);
3317 if (dc)
3319 if (dc->gdiFont)
3320 ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
3322 release_dc_ptr( dc );
3325 if (ret == DEFAULT_CHARSET && fs)
3326 memset(fs, 0, sizeof(FONTSIGNATURE));
3327 return ret;
3330 /***********************************************************************
3331 * GdiGetCharDimensions (GDI32.@)
3333 * Gets the average width of the characters in the English alphabet.
3335 * PARAMS
3336 * hdc [I] Handle to the device context to measure on.
3337 * lptm [O] Pointer to memory to store the text metrics into.
3338 * height [O] On exit, the maximum height of characters in the English alphabet.
3340 * RETURNS
3341 * The average width of characters in the English alphabet.
3343 * NOTES
3344 * This function is used by the dialog manager to get the size of a dialog
3345 * unit. It should also be used by other pieces of code that need to know
3346 * the size of a dialog unit in logical units without having access to the
3347 * window handle of the dialog.
3348 * Windows caches the font metrics from this function, but we don't and
3349 * there doesn't appear to be an immediate advantage to do so.
3351 * SEE ALSO
3352 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3354 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3356 SIZE sz;
3357 static const WCHAR alphabet[] = {
3358 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3359 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3360 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3362 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3364 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3366 if (height) *height = sz.cy;
3367 return (sz.cx / 26 + 1) / 2;
3370 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3372 FIXME("(%d): stub\n", fEnableEUDC);
3373 return FALSE;
3376 /***********************************************************************
3377 * GetCharWidthI (GDI32.@)
3379 * Retrieve widths of characters.
3381 * PARAMS
3382 * hdc [I] Handle to a device context.
3383 * first [I] First glyph in range to query.
3384 * count [I] Number of glyph indices to query.
3385 * glyphs [I] Array of glyphs to query.
3386 * buffer [O] Buffer to receive character widths.
3388 * NOTES
3389 * Only works with TrueType fonts.
3391 * RETURNS
3392 * Success: TRUE
3393 * Failure: FALSE
3395 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3397 ABC *abc;
3398 unsigned int i;
3400 TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3402 if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3403 return FALSE;
3405 if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3407 HeapFree(GetProcessHeap(), 0, abc);
3408 return FALSE;
3411 for (i = 0; i < count; i++)
3412 buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3414 HeapFree(GetProcessHeap(), 0, abc);
3415 return TRUE;
3418 /***********************************************************************
3419 * GetFontUnicodeRanges (GDI32.@)
3421 * Retrieve a list of supported Unicode characters in a font.
3423 * PARAMS
3424 * hdc [I] Handle to a device context.
3425 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3427 * RETURNS
3428 * Success: Number of bytes written to the buffer pointed to by lpgs.
3429 * Failure: 0
3432 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3434 DWORD ret = 0;
3435 DC *dc = get_dc_ptr(hdc);
3437 TRACE("(%p, %p)\n", hdc, lpgs);
3439 if (!dc) return 0;
3441 if (dc->gdiFont) ret = WineEngGetFontUnicodeRanges(dc->gdiFont, lpgs);
3442 release_dc_ptr(dc);
3443 return ret;
3447 /*************************************************************
3448 * FontIsLinked (GDI32.@)
3450 BOOL WINAPI FontIsLinked(HDC hdc)
3452 DC *dc = get_dc_ptr(hdc);
3453 BOOL ret = FALSE;
3455 if (!dc) return FALSE;
3456 if (dc->gdiFont) ret = WineEngFontIsLinked(dc->gdiFont);
3457 release_dc_ptr(dc);
3458 TRACE("returning %d\n", ret);
3459 return ret;
3462 /*************************************************************
3463 * GdiRealizationInfo (GDI32.@)
3465 * Returns a structure that contains some font information.
3467 BOOL WINAPI GdiRealizationInfo(HDC hdc, realization_info_t *info)
3469 DC *dc = get_dc_ptr(hdc);
3470 BOOL ret = FALSE;
3472 if (!dc) return FALSE;
3473 if (dc->gdiFont) ret = WineEngRealizationInfo(dc->gdiFont, info);
3474 release_dc_ptr(dc);
3476 return ret;