gdi32: Implement GetOutlineTextMetrics as a standard driver entry point.
[wine/multimedia.git] / dlls / gdi32 / font.c
blob5e55e31b3a96ce6f01fb15a2f47bc1cd34357cf1
1 /*
2 * GDI font objects
4 * Copyright 1993 Alexandre Julliard
5 * 1997 Alex Korobka
6 * Copyright 2002,2003 Shachar Shemesh
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "config.h"
24 #include "wine/port.h"
26 #include <stdarg.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <assert.h>
30 #include "winerror.h"
31 #include "windef.h"
32 #include "winbase.h"
33 #include "winnls.h"
34 #include "gdi_private.h"
35 #include "wine/exception.h"
36 #include "wine/unicode.h"
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(font);
41 /* Device -> World size conversion */
43 /* Performs a device to world transformation on the specified width (which
44 * is in integer format).
46 static inline INT INTERNAL_XDSTOWS(DC *dc, INT width)
48 double floatWidth;
50 /* Perform operation with floating point */
51 floatWidth = (double)width * dc->xformVport2World.eM11;
52 /* Round to integers */
53 return GDI_ROUND(floatWidth);
56 /* Performs a device to world transformation on the specified size (which
57 * is in integer format).
59 static inline INT INTERNAL_YDSTOWS(DC *dc, INT height)
61 double floatHeight;
63 /* Perform operation with floating point */
64 floatHeight = (double)height * dc->xformVport2World.eM22;
65 /* Round to integers */
66 return GDI_ROUND(floatHeight);
69 static inline INT INTERNAL_XWSTODS(DC *dc, INT width)
71 POINT pt[2];
72 pt[0].x = pt[0].y = 0;
73 pt[1].x = width;
74 pt[1].y = 0;
75 LPtoDP(dc->hSelf, pt, 2);
76 return pt[1].x - pt[0].x;
79 static inline INT INTERNAL_YWSTODS(DC *dc, INT height)
81 POINT pt[2];
82 pt[0].x = pt[0].y = 0;
83 pt[1].x = 0;
84 pt[1].y = height;
85 LPtoDP(dc->hSelf, pt, 2);
86 return pt[1].y - pt[0].y;
89 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc );
90 static INT FONT_GetObjectA( HGDIOBJ handle, INT count, LPVOID buffer );
91 static INT FONT_GetObjectW( HGDIOBJ handle, INT count, LPVOID buffer );
92 static BOOL FONT_DeleteObject( HGDIOBJ handle );
94 static const struct gdi_obj_funcs font_funcs =
96 FONT_SelectObject, /* pSelectObject */
97 FONT_GetObjectA, /* pGetObjectA */
98 FONT_GetObjectW, /* pGetObjectW */
99 NULL, /* pUnrealizeObject */
100 FONT_DeleteObject /* pDeleteObject */
103 typedef struct
105 GDIOBJHDR header;
106 LOGFONTW logfont;
107 } FONTOBJ;
109 struct font_enum
111 LPLOGFONTW lpLogFontParam;
112 FONTENUMPROCW lpEnumFunc;
113 LPARAM lpData;
114 BOOL unicode;
115 HDC hdc;
119 * For TranslateCharsetInfo
121 #define MAXTCIINDEX 32
122 static const CHARSETINFO FONT_tci[MAXTCIINDEX] = {
123 /* ANSI */
124 { ANSI_CHARSET, 1252, {{0,0,0,0},{FS_LATIN1,0}} },
125 { EASTEUROPE_CHARSET, 1250, {{0,0,0,0},{FS_LATIN2,0}} },
126 { RUSSIAN_CHARSET, 1251, {{0,0,0,0},{FS_CYRILLIC,0}} },
127 { GREEK_CHARSET, 1253, {{0,0,0,0},{FS_GREEK,0}} },
128 { TURKISH_CHARSET, 1254, {{0,0,0,0},{FS_TURKISH,0}} },
129 { HEBREW_CHARSET, 1255, {{0,0,0,0},{FS_HEBREW,0}} },
130 { ARABIC_CHARSET, 1256, {{0,0,0,0},{FS_ARABIC,0}} },
131 { BALTIC_CHARSET, 1257, {{0,0,0,0},{FS_BALTIC,0}} },
132 { VIETNAMESE_CHARSET, 1258, {{0,0,0,0},{FS_VIETNAMESE,0}} },
133 /* reserved by ANSI */
134 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
135 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
136 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
137 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
138 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
139 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
140 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
141 /* ANSI and OEM */
142 { THAI_CHARSET, 874, {{0,0,0,0},{FS_THAI,0}} },
143 { SHIFTJIS_CHARSET, 932, {{0,0,0,0},{FS_JISJAPAN,0}} },
144 { GB2312_CHARSET, 936, {{0,0,0,0},{FS_CHINESESIMP,0}} },
145 { HANGEUL_CHARSET, 949, {{0,0,0,0},{FS_WANSUNG,0}} },
146 { CHINESEBIG5_CHARSET, 950, {{0,0,0,0},{FS_CHINESETRAD,0}} },
147 { JOHAB_CHARSET, 1361, {{0,0,0,0},{FS_JOHAB,0}} },
148 /* reserved for alternate ANSI and OEM */
149 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
150 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
151 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
152 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
153 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
154 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
155 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
156 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
157 /* reserved for system */
158 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
159 { SYMBOL_CHARSET, CP_SYMBOL, {{0,0,0,0},{FS_SYMBOL,0}} }
162 static void FONT_LogFontAToW( const LOGFONTA *fontA, LPLOGFONTW fontW )
164 memcpy(fontW, fontA, sizeof(LOGFONTA) - LF_FACESIZE);
165 MultiByteToWideChar(CP_ACP, 0, fontA->lfFaceName, -1, fontW->lfFaceName,
166 LF_FACESIZE);
167 fontW->lfFaceName[LF_FACESIZE-1] = 0;
170 static void FONT_LogFontWToA( const LOGFONTW *fontW, LPLOGFONTA fontA )
172 memcpy(fontA, fontW, sizeof(LOGFONTA) - LF_FACESIZE);
173 WideCharToMultiByte(CP_ACP, 0, fontW->lfFaceName, -1, fontA->lfFaceName,
174 LF_FACESIZE, NULL, NULL);
175 fontA->lfFaceName[LF_FACESIZE-1] = 0;
178 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEXA fontA )
180 FONT_LogFontWToA( &fontW->elfLogFont, &fontA->elfLogFont );
182 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
183 (LPSTR) fontA->elfFullName, LF_FULLFACESIZE, NULL, NULL );
184 fontA->elfFullName[LF_FULLFACESIZE-1] = '\0';
185 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
186 (LPSTR) fontA->elfStyle, LF_FACESIZE, NULL, NULL );
187 fontA->elfStyle[LF_FACESIZE-1] = '\0';
188 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
189 (LPSTR) fontA->elfScript, LF_FACESIZE, NULL, NULL );
190 fontA->elfScript[LF_FACESIZE-1] = '\0';
193 static void FONT_EnumLogFontExAToW( const ENUMLOGFONTEXA *fontA, LPENUMLOGFONTEXW fontW )
195 FONT_LogFontAToW( &fontA->elfLogFont, &fontW->elfLogFont );
197 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfFullName, -1,
198 fontW->elfFullName, LF_FULLFACESIZE );
199 fontW->elfFullName[LF_FULLFACESIZE-1] = '\0';
200 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfStyle, -1,
201 fontW->elfStyle, LF_FACESIZE );
202 fontW->elfStyle[LF_FACESIZE-1] = '\0';
203 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfScript, -1,
204 fontW->elfScript, LF_FACESIZE );
205 fontW->elfScript[LF_FACESIZE-1] = '\0';
208 /***********************************************************************
209 * TEXTMETRIC conversion functions.
211 static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
213 ptmA->tmHeight = ptmW->tmHeight;
214 ptmA->tmAscent = ptmW->tmAscent;
215 ptmA->tmDescent = ptmW->tmDescent;
216 ptmA->tmInternalLeading = ptmW->tmInternalLeading;
217 ptmA->tmExternalLeading = ptmW->tmExternalLeading;
218 ptmA->tmAveCharWidth = ptmW->tmAveCharWidth;
219 ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth;
220 ptmA->tmWeight = ptmW->tmWeight;
221 ptmA->tmOverhang = ptmW->tmOverhang;
222 ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX;
223 ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
224 ptmA->tmFirstChar = min(ptmW->tmFirstChar, 255);
225 if (ptmW->tmCharSet == SYMBOL_CHARSET)
227 ptmA->tmFirstChar = 0x1e;
228 ptmA->tmLastChar = 0xff; /* win9x behaviour - we need the OS2 table data to calculate correctly */
230 else if (ptmW->tmPitchAndFamily & TMPF_TRUETYPE)
232 ptmA->tmFirstChar = ptmW->tmDefaultChar - 1;
233 ptmA->tmLastChar = min(ptmW->tmLastChar, 0xff);
235 else
237 ptmA->tmFirstChar = min(ptmW->tmFirstChar, 0xff);
238 ptmA->tmLastChar = min(ptmW->tmLastChar, 0xff);
240 ptmA->tmDefaultChar = ptmW->tmDefaultChar;
241 ptmA->tmBreakChar = ptmW->tmBreakChar;
242 ptmA->tmItalic = ptmW->tmItalic;
243 ptmA->tmUnderlined = ptmW->tmUnderlined;
244 ptmA->tmStruckOut = ptmW->tmStruckOut;
245 ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
246 ptmA->tmCharSet = ptmW->tmCharSet;
250 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW *ptmW, NEWTEXTMETRICEXA *ptmA )
252 FONT_TextMetricWToA((const TEXTMETRICW *)ptmW, (LPTEXTMETRICA)ptmA);
253 ptmA->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
254 ptmA->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
255 ptmA->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
256 ptmA->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
257 memcpy(&ptmA->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
261 /***********************************************************************
262 * GdiGetCodePage (GDI32.@)
264 DWORD WINAPI GdiGetCodePage( HDC hdc )
266 UINT cp = CP_ACP;
267 DC *dc = get_dc_ptr( hdc );
269 if (dc)
271 cp = dc->font_code_page;
272 release_dc_ptr( dc );
274 return cp;
277 /***********************************************************************
278 * FONT_mbtowc
280 * Returns a Unicode translation of str using the charset of the
281 * currently selected font in hdc. If count is -1 then str is assumed
282 * to be '\0' terminated, otherwise it contains the number of bytes to
283 * convert. If plenW is non-NULL, on return it will point to the
284 * number of WCHARs that have been written. If pCP is non-NULL, on
285 * return it will point to the codepage used in the conversion. The
286 * caller should free the returned LPWSTR from the process heap
287 * itself.
289 static LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
291 UINT cp;
292 INT lenW;
293 LPWSTR strW;
295 cp = GdiGetCodePage( hdc );
297 if(count == -1) count = strlen(str);
298 lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
299 strW = HeapAlloc(GetProcessHeap(), 0, lenW*sizeof(WCHAR));
300 MultiByteToWideChar(cp, 0, str, count, strW, lenW);
301 TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW));
302 if(plenW) *plenW = lenW;
303 if(pCP) *pCP = cp;
304 return strW;
307 /***********************************************************************
308 * CreateFontIndirectExA (GDI32.@)
310 HFONT WINAPI CreateFontIndirectExA( const ENUMLOGFONTEXDVA *penumexA )
312 ENUMLOGFONTEXDVW enumexW;
314 if (!penumexA) return 0;
316 FONT_EnumLogFontExAToW( &penumexA->elfEnumLogfontEx, &enumexW.elfEnumLogfontEx );
317 enumexW.elfDesignVector = penumexA->elfDesignVector;
318 return CreateFontIndirectExW( &enumexW );
321 /***********************************************************************
322 * CreateFontIndirectExW (GDI32.@)
324 HFONT WINAPI CreateFontIndirectExW( const ENUMLOGFONTEXDVW *penumex )
326 HFONT hFont;
327 FONTOBJ *fontPtr;
328 const LOGFONTW *plf;
330 if (!penumex) return 0;
332 if (penumex->elfEnumLogfontEx.elfFullName[0] ||
333 penumex->elfEnumLogfontEx.elfStyle[0] ||
334 penumex->elfEnumLogfontEx.elfScript[0])
336 FIXME("some fields ignored. fullname=%s, style=%s, script=%s\n",
337 debugstr_w(penumex->elfEnumLogfontEx.elfFullName),
338 debugstr_w(penumex->elfEnumLogfontEx.elfStyle),
339 debugstr_w(penumex->elfEnumLogfontEx.elfScript));
342 plf = &penumex->elfEnumLogfontEx.elfLogFont;
343 if (!(fontPtr = HeapAlloc( GetProcessHeap(), 0, sizeof(*fontPtr) ))) return 0;
345 fontPtr->logfont = *plf;
347 if (plf->lfEscapement != plf->lfOrientation)
349 /* this should really depend on whether GM_ADVANCED is set */
350 fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
351 WARN("orientation angle %f set to "
352 "escapement angle %f for new font %p\n",
353 plf->lfOrientation/10., plf->lfEscapement/10., fontPtr);
356 if (!(hFont = alloc_gdi_handle( &fontPtr->header, OBJ_FONT, &font_funcs )))
358 HeapFree( GetProcessHeap(), 0, fontPtr );
359 return 0;
362 TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
363 plf->lfHeight, plf->lfWidth,
364 plf->lfEscapement, plf->lfOrientation,
365 plf->lfPitchAndFamily,
366 plf->lfOutPrecision, plf->lfClipPrecision,
367 plf->lfQuality, plf->lfCharSet,
368 debugstr_w(plf->lfFaceName),
369 plf->lfWeight > 400 ? "Bold" : "",
370 plf->lfItalic ? "Italic" : "",
371 plf->lfUnderline ? "Underline" : "", hFont);
373 return hFont;
376 /***********************************************************************
377 * CreateFontIndirectA (GDI32.@)
379 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *plfA )
381 LOGFONTW lfW;
383 if (!plfA) return 0;
385 FONT_LogFontAToW( plfA, &lfW );
386 return CreateFontIndirectW( &lfW );
389 /***********************************************************************
390 * CreateFontIndirectW (GDI32.@)
392 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
394 ENUMLOGFONTEXDVW exdv;
396 if (!plf) return 0;
398 exdv.elfEnumLogfontEx.elfLogFont = *plf;
399 exdv.elfEnumLogfontEx.elfFullName[0] = 0;
400 exdv.elfEnumLogfontEx.elfStyle[0] = 0;
401 exdv.elfEnumLogfontEx.elfScript[0] = 0;
402 return CreateFontIndirectExW( &exdv );
405 /*************************************************************************
406 * CreateFontA (GDI32.@)
408 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
409 INT orient, INT weight, DWORD italic,
410 DWORD underline, DWORD strikeout, DWORD charset,
411 DWORD outpres, DWORD clippres, DWORD quality,
412 DWORD pitch, LPCSTR name )
414 LOGFONTA logfont;
416 logfont.lfHeight = height;
417 logfont.lfWidth = width;
418 logfont.lfEscapement = esc;
419 logfont.lfOrientation = orient;
420 logfont.lfWeight = weight;
421 logfont.lfItalic = italic;
422 logfont.lfUnderline = underline;
423 logfont.lfStrikeOut = strikeout;
424 logfont.lfCharSet = charset;
425 logfont.lfOutPrecision = outpres;
426 logfont.lfClipPrecision = clippres;
427 logfont.lfQuality = quality;
428 logfont.lfPitchAndFamily = pitch;
430 if (name)
431 lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
432 else
433 logfont.lfFaceName[0] = '\0';
435 return CreateFontIndirectA( &logfont );
438 /*************************************************************************
439 * CreateFontW (GDI32.@)
441 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
442 INT orient, INT weight, DWORD italic,
443 DWORD underline, DWORD strikeout, DWORD charset,
444 DWORD outpres, DWORD clippres, DWORD quality,
445 DWORD pitch, LPCWSTR name )
447 LOGFONTW logfont;
449 logfont.lfHeight = height;
450 logfont.lfWidth = width;
451 logfont.lfEscapement = esc;
452 logfont.lfOrientation = orient;
453 logfont.lfWeight = weight;
454 logfont.lfItalic = italic;
455 logfont.lfUnderline = underline;
456 logfont.lfStrikeOut = strikeout;
457 logfont.lfCharSet = charset;
458 logfont.lfOutPrecision = outpres;
459 logfont.lfClipPrecision = clippres;
460 logfont.lfQuality = quality;
461 logfont.lfPitchAndFamily = pitch;
463 if (name)
464 lstrcpynW(logfont.lfFaceName, name,
465 sizeof(logfont.lfFaceName) / sizeof(WCHAR));
466 else
467 logfont.lfFaceName[0] = '\0';
469 return CreateFontIndirectW( &logfont );
472 static void update_font_code_page( DC *dc )
474 CHARSETINFO csi;
475 int charset = DEFAULT_CHARSET;
477 if (dc->gdiFont)
478 charset = WineEngGetTextCharsetInfo( dc->gdiFont, NULL, 0 );
480 /* Hmm, nicely designed api this one! */
481 if (TranslateCharsetInfo( ULongToPtr(charset), &csi, TCI_SRCCHARSET) )
482 dc->font_code_page = csi.ciACP;
483 else {
484 switch(charset) {
485 case OEM_CHARSET:
486 dc->font_code_page = GetOEMCP();
487 break;
488 case DEFAULT_CHARSET:
489 dc->font_code_page = GetACP();
490 break;
492 case VISCII_CHARSET:
493 case TCVN_CHARSET:
494 case KOI8_CHARSET:
495 case ISO3_CHARSET:
496 case ISO4_CHARSET:
497 case ISO10_CHARSET:
498 case CELTIC_CHARSET:
499 /* FIXME: These have no place here, but because x11drv
500 enumerates fonts with these (made up) charsets some apps
501 might use them and then the FIXME below would become
502 annoying. Now we could pick the intended codepage for
503 each of these, but since it's broken anyway we'll just
504 use CP_ACP and hope it'll go away...
506 dc->font_code_page = CP_ACP;
507 break;
509 default:
510 FIXME("Can't find codepage for charset %d\n", charset);
511 dc->font_code_page = CP_ACP;
512 break;
516 TRACE("charset %d => cp %d\n", charset, dc->font_code_page);
519 /***********************************************************************
520 * FONT_SelectObject
522 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc )
524 HGDIOBJ ret = 0;
525 DC *dc = get_dc_ptr( hdc );
526 PHYSDEV physdev;
528 if (!dc) return 0;
530 if (!GDI_inc_ref_count( handle ))
532 release_dc_ptr( dc );
533 return 0;
536 physdev = GET_DC_PHYSDEV( dc, pSelectFont );
537 if (physdev->funcs->pSelectFont( physdev, handle ))
539 ret = dc->hFont;
540 dc->hFont = handle;
541 update_font_code_page( dc );
542 GDI_dec_ref_count( ret );
544 else GDI_dec_ref_count( handle );
546 release_dc_ptr( dc );
547 return ret;
551 /***********************************************************************
552 * FONT_GetObjectA
554 static INT FONT_GetObjectA( HGDIOBJ handle, INT count, LPVOID buffer )
556 FONTOBJ *font = GDI_GetObjPtr( handle, OBJ_FONT );
557 LOGFONTA lfA;
559 if (!font) return 0;
560 if (buffer)
562 FONT_LogFontWToA( &font->logfont, &lfA );
563 if (count > sizeof(lfA)) count = sizeof(lfA);
564 memcpy( buffer, &lfA, count );
566 else count = sizeof(lfA);
567 GDI_ReleaseObj( handle );
568 return count;
571 /***********************************************************************
572 * FONT_GetObjectW
574 static INT FONT_GetObjectW( HGDIOBJ handle, INT count, LPVOID buffer )
576 FONTOBJ *font = GDI_GetObjPtr( handle, OBJ_FONT );
578 if (!font) return 0;
579 if (buffer)
581 if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
582 memcpy( buffer, &font->logfont, count );
584 else count = sizeof(LOGFONTW);
585 GDI_ReleaseObj( handle );
586 return count;
590 /***********************************************************************
591 * FONT_DeleteObject
593 static BOOL FONT_DeleteObject( HGDIOBJ handle )
595 FONTOBJ *obj;
597 WineEngDestroyFontInstance( handle );
599 if (!(obj = free_gdi_handle( handle ))) return FALSE;
600 return HeapFree( GetProcessHeap(), 0, obj );
604 /***********************************************************************
605 * FONT_EnumInstance
607 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
608 * We have to use other types because of the FONTENUMPROCW definition.
610 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
611 DWORD fType, LPARAM lp )
613 struct font_enum *pfe = (struct font_enum *)lp;
614 INT ret = 1;
616 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
617 if ((!pfe->lpLogFontParam ||
618 pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
619 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
620 (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
622 /* convert font metrics */
623 ENUMLOGFONTEXA logfont;
624 NEWTEXTMETRICEXA tmA;
626 if (!pfe->unicode)
628 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
629 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
630 plf = (LOGFONTW *)&logfont.elfLogFont;
631 ptm = (TEXTMETRICW *)&tmA;
633 ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
635 return ret;
638 /***********************************************************************
639 * FONT_EnumFontFamiliesEx
641 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf, FONTENUMPROCW efproc,
642 LPARAM lParam, BOOL unicode )
644 INT ret = 0;
645 DC *dc = get_dc_ptr( hDC );
646 struct font_enum fe;
648 if (dc)
650 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pEnumFonts );
652 if (plf) TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName), plf->lfCharSet);
653 fe.lpLogFontParam = plf;
654 fe.lpEnumFunc = efproc;
655 fe.lpData = lParam;
656 fe.unicode = unicode;
657 fe.hdc = hDC;
658 ret = physdev->funcs->pEnumFonts( physdev, plf, FONT_EnumInstance, (LPARAM)&fe );
660 release_dc_ptr( dc );
661 return ret;
664 /***********************************************************************
665 * EnumFontFamiliesExW (GDI32.@)
667 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
668 FONTENUMPROCW efproc,
669 LPARAM lParam, DWORD dwFlags )
671 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, TRUE );
674 /***********************************************************************
675 * EnumFontFamiliesExA (GDI32.@)
677 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
678 FONTENUMPROCA efproc,
679 LPARAM lParam, DWORD dwFlags)
681 LOGFONTW lfW, *plfW;
683 if (plf)
685 FONT_LogFontAToW( plf, &lfW );
686 plfW = &lfW;
688 else plfW = NULL;
690 return FONT_EnumFontFamiliesEx( hDC, plfW, (FONTENUMPROCW)efproc, lParam, FALSE );
693 /***********************************************************************
694 * EnumFontFamiliesA (GDI32.@)
696 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
697 FONTENUMPROCA efproc, LPARAM lpData )
699 LOGFONTA lf, *plf;
701 if (lpFamily)
703 if (!*lpFamily) return 1;
704 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
705 lf.lfCharSet = DEFAULT_CHARSET;
706 lf.lfPitchAndFamily = 0;
707 plf = &lf;
709 else plf = NULL;
711 return EnumFontFamiliesExA( hDC, plf, efproc, lpData, 0 );
714 /***********************************************************************
715 * EnumFontFamiliesW (GDI32.@)
717 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
718 FONTENUMPROCW efproc, LPARAM lpData )
720 LOGFONTW lf, *plf;
722 if (lpFamily)
724 if (!*lpFamily) return 1;
725 lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
726 lf.lfCharSet = DEFAULT_CHARSET;
727 lf.lfPitchAndFamily = 0;
728 plf = &lf;
730 else plf = NULL;
732 return EnumFontFamiliesExW( hDC, plf, efproc, lpData, 0 );
735 /***********************************************************************
736 * EnumFontsA (GDI32.@)
738 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
739 LPARAM lpData )
741 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
744 /***********************************************************************
745 * EnumFontsW (GDI32.@)
747 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
748 LPARAM lpData )
750 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
754 /***********************************************************************
755 * GetTextCharacterExtra (GDI32.@)
757 INT WINAPI GetTextCharacterExtra( HDC hdc )
759 INT ret;
760 DC *dc = get_dc_ptr( hdc );
761 if (!dc) return 0x80000000;
762 ret = dc->charExtra;
763 release_dc_ptr( dc );
764 return ret;
768 /***********************************************************************
769 * SetTextCharacterExtra (GDI32.@)
771 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
773 INT ret = 0x80000000;
774 DC * dc = get_dc_ptr( hdc );
776 if (dc)
778 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetTextCharacterExtra );
779 extra = physdev->funcs->pSetTextCharacterExtra( physdev, extra );
780 if (extra != 0x80000000)
782 ret = dc->charExtra;
783 dc->charExtra = extra;
785 release_dc_ptr( dc );
787 return ret;
791 /***********************************************************************
792 * SetTextJustification (GDI32.@)
794 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
796 BOOL ret;
797 PHYSDEV physdev;
798 DC * dc = get_dc_ptr( hdc );
800 if (!dc) return FALSE;
802 physdev = GET_DC_PHYSDEV( dc, pSetTextJustification );
803 ret = physdev->funcs->pSetTextJustification( physdev, extra, breaks );
804 if (ret)
806 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
807 if (!extra) breaks = 0;
808 if (breaks)
810 dc->breakExtra = extra / breaks;
811 dc->breakRem = extra - (breaks * dc->breakExtra);
813 else
815 dc->breakExtra = 0;
816 dc->breakRem = 0;
819 release_dc_ptr( dc );
820 return ret;
824 /***********************************************************************
825 * GetTextFaceA (GDI32.@)
827 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
829 INT res = GetTextFaceW(hdc, 0, NULL);
830 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
831 GetTextFaceW( hdc, res, nameW );
833 if (name)
835 if (count)
837 res = WideCharToMultiByte(CP_ACP, 0, nameW, -1, name, count, NULL, NULL);
838 if (res == 0)
839 res = count;
840 name[count-1] = 0;
841 /* GetTextFaceA does NOT include the nul byte in the return count. */
842 res--;
844 else
845 res = 0;
847 else
848 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
849 HeapFree( GetProcessHeap(), 0, nameW );
850 return res;
853 /***********************************************************************
854 * GetTextFaceW (GDI32.@)
856 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
858 FONTOBJ *font;
859 INT ret = 0;
861 DC * dc = get_dc_ptr( hdc );
862 if (!dc) return 0;
864 if(dc->gdiFont)
865 ret = WineEngGetTextFace(dc->gdiFont, count, name);
866 else if ((font = GDI_GetObjPtr( dc->hFont, OBJ_FONT )))
868 INT n = strlenW(font->logfont.lfFaceName) + 1;
869 if (name)
871 lstrcpynW( name, font->logfont.lfFaceName, count );
872 ret = min(count, n);
874 else ret = n;
875 GDI_ReleaseObj( dc->hFont );
877 release_dc_ptr( dc );
878 return ret;
882 /***********************************************************************
883 * GetTextExtentPoint32A (GDI32.@)
885 * See GetTextExtentPoint32W.
887 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
888 LPSIZE size )
890 BOOL ret = FALSE;
891 INT wlen;
892 LPWSTR p;
894 if (count < 0) return FALSE;
896 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
898 if (p)
900 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
901 HeapFree( GetProcessHeap(), 0, p );
904 TRACE("(%p %s %d %p): returning %d x %d\n",
905 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
906 return ret;
910 /***********************************************************************
911 * GetTextExtentPoint32W [GDI32.@]
913 * Computes width/height for a string.
915 * Computes width and height of the specified string.
917 * RETURNS
918 * Success: TRUE
919 * Failure: FALSE
921 BOOL WINAPI GetTextExtentPoint32W(
922 HDC hdc, /* [in] Handle of device context */
923 LPCWSTR str, /* [in] Address of text string */
924 INT count, /* [in] Number of characters in string */
925 LPSIZE size) /* [out] Address of structure for string size */
927 return GetTextExtentExPointW(hdc, str, count, 0, NULL, NULL, size);
930 /***********************************************************************
931 * GetTextExtentExPointI [GDI32.@]
933 * Computes width and height of the array of glyph indices.
935 * PARAMS
936 * hdc [I] Handle of device context.
937 * indices [I] Glyph index array.
938 * count [I] Number of glyphs in array.
939 * max_ext [I] Maximum width in glyphs.
940 * nfit [O] Maximum number of characters.
941 * dxs [O] Partial string widths.
942 * size [O] Returned string size.
944 * RETURNS
945 * Success: TRUE
946 * Failure: FALSE
948 BOOL WINAPI GetTextExtentExPointI( HDC hdc, const WORD *indices, INT count, INT max_ext,
949 LPINT nfit, LPINT dxs, LPSIZE size )
951 BOOL ret = FALSE;
952 DC *dc;
954 if (count < 0) return FALSE;
956 dc = get_dc_ptr( hdc );
957 if (!dc) return FALSE;
959 if(dc->gdiFont)
961 ret = WineEngGetTextExtentExPointI(dc->gdiFont, indices, count, max_ext, nfit, dxs, size);
962 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
963 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
964 size->cx += count * dc->charExtra;
966 else
968 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pGetTextExtentExPoint );
969 FIXME("calling GetTextExtentExPoint\n");
970 ret = physdev->funcs->pGetTextExtentExPoint( physdev, indices, count, max_ext, nfit, dxs, size );
973 release_dc_ptr( dc );
975 TRACE("(%p %p %d %p): returning %d x %d\n",
976 hdc, indices, count, size, size->cx, size->cy );
977 return ret;
980 /***********************************************************************
981 * GetTextExtentPointI [GDI32.@]
983 * Computes width and height of the array of glyph indices.
985 * PARAMS
986 * hdc [I] Handle of device context.
987 * indices [I] Glyph index array.
988 * count [I] Number of glyphs in array.
989 * size [O] Returned string size.
991 * RETURNS
992 * Success: TRUE
993 * Failure: FALSE
995 BOOL WINAPI GetTextExtentPointI( HDC hdc, const WORD *indices, INT count, LPSIZE size )
997 return GetTextExtentExPointI( hdc, indices, count, 0, NULL, NULL, size );
1001 /***********************************************************************
1002 * GetTextExtentPointA (GDI32.@)
1004 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
1005 LPSIZE size )
1007 TRACE("not bug compatible.\n");
1008 return GetTextExtentPoint32A( hdc, str, count, size );
1011 /***********************************************************************
1012 * GetTextExtentPointW (GDI32.@)
1014 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1015 LPSIZE size )
1017 TRACE("not bug compatible.\n");
1018 return GetTextExtentPoint32W( hdc, str, count, size );
1022 /***********************************************************************
1023 * GetTextExtentExPointA (GDI32.@)
1025 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1026 INT maxExt, LPINT lpnFit,
1027 LPINT alpDx, LPSIZE size )
1029 BOOL ret;
1030 INT wlen;
1031 INT *walpDx = NULL;
1032 LPWSTR p = NULL;
1034 if (count < 0) return FALSE;
1036 if (alpDx)
1038 walpDx = HeapAlloc( GetProcessHeap(), 0, count * sizeof(INT) );
1039 if (!walpDx) return FALSE;
1042 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1043 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
1044 if (walpDx)
1046 INT n = lpnFit ? *lpnFit : wlen;
1047 INT i, j;
1048 for(i = 0, j = 0; i < n; i++, j++)
1050 alpDx[j] = walpDx[i];
1051 if (IsDBCSLeadByte(str[j])) alpDx[++j] = walpDx[i];
1054 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1055 HeapFree( GetProcessHeap(), 0, p );
1056 HeapFree( GetProcessHeap(), 0, walpDx );
1057 return ret;
1061 /***********************************************************************
1062 * GetTextExtentExPointW (GDI32.@)
1064 * Return the size of the string as it would be if it was output properly by
1065 * e.g. TextOut.
1067 * This should include
1068 * - Intercharacter spacing
1069 * - justification spacing (not yet done)
1070 * - kerning? see below
1072 * Kerning. Since kerning would be carried out by the rendering code it should
1073 * be done by the driver. However they don't support it yet. Also I am not
1074 * yet persuaded that (certainly under Win95) any kerning is actually done.
1076 * str: According to MSDN this should be null-terminated. That is not true; a
1077 * null will not terminate it early.
1078 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1079 * than count. I have seen it be either the size of the full string or
1080 * 1 less than the size of the full string. I have not seen it bear any
1081 * resemblance to the portion that would fit.
1082 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1083 * trailing intercharacter spacing and any trailing justification.
1085 * FIXME
1086 * Currently we do this by measuring each character etc. We should do it by
1087 * passing the request to the driver, perhaps by extending the
1088 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1089 * thinking about kerning issues and rounding issues in the justification.
1092 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1093 INT maxExt, LPINT lpnFit,
1094 LPINT alpDx, LPSIZE size )
1096 INT nFit = 0;
1097 LPINT dxs = NULL;
1098 DC *dc;
1099 BOOL ret = FALSE;
1100 TEXTMETRICW tm;
1101 PHYSDEV dev;
1103 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1105 if (count < 0) return FALSE;
1107 dc = get_dc_ptr(hdc);
1108 if (!dc) return FALSE;
1110 GetTextMetricsW(hdc, &tm);
1112 /* If we need to calculate nFit, then we need the partial extents even if
1113 the user hasn't provided us with an array. */
1114 if (lpnFit)
1116 dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]);
1117 if (! dxs)
1119 release_dc_ptr(dc);
1120 SetLastError(ERROR_OUTOFMEMORY);
1121 return FALSE;
1124 else
1125 dxs = alpDx;
1127 dev = GET_DC_PHYSDEV( dc, pGetTextExtentExPoint );
1128 ret = dev->funcs->pGetTextExtentExPoint(dev, str, count, 0, NULL, dxs, size);
1130 /* Perform device size to world size transformations. */
1131 if (ret)
1133 INT extra = dc->charExtra,
1134 breakExtra = dc->breakExtra,
1135 breakRem = dc->breakRem,
1138 if (dxs)
1140 for (i = 0; i < count; ++i)
1142 dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
1143 dxs[i] += (i+1) * extra;
1144 if (count > 1 && (breakExtra || breakRem) && str[i] == tm.tmBreakChar)
1146 dxs[i] += breakExtra;
1147 if (breakRem > 0)
1149 breakRem--;
1150 dxs[i]++;
1153 if (dxs[i] <= maxExt)
1154 ++nFit;
1156 breakRem = dc->breakRem;
1158 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1159 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1161 if (!dxs && count > 1 && (breakExtra || breakRem))
1163 for (i = 0; i < count; i++)
1165 if (str[i] == tm.tmBreakChar)
1167 size->cx += breakExtra;
1168 if (breakRem > 0)
1170 breakRem--;
1171 (size->cx)++;
1178 if (lpnFit)
1179 *lpnFit = nFit;
1181 if (! alpDx)
1182 HeapFree(GetProcessHeap(), 0, dxs);
1184 release_dc_ptr( dc );
1186 TRACE("returning %d %d x %d\n",nFit,size->cx,size->cy);
1187 return ret;
1190 /***********************************************************************
1191 * GetTextMetricsA (GDI32.@)
1193 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1195 TEXTMETRICW tm32;
1197 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1198 FONT_TextMetricWToA( &tm32, metrics );
1199 return TRUE;
1202 /***********************************************************************
1203 * GetTextMetricsW (GDI32.@)
1205 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1207 PHYSDEV physdev;
1208 BOOL ret = FALSE;
1209 DC * dc = get_dc_ptr( hdc );
1210 if (!dc) return FALSE;
1212 physdev = GET_DC_PHYSDEV( dc, pGetTextMetrics );
1213 ret = physdev->funcs->pGetTextMetrics( physdev, metrics );
1215 if (ret)
1217 /* device layer returns values in device units
1218 * therefore we have to convert them to logical */
1220 metrics->tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1221 metrics->tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1223 #define WDPTOLP(x) ((x<0)? \
1224 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1225 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1226 #define HDPTOLP(y) ((y<0)? \
1227 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1228 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1230 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1231 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1232 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1233 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1234 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1235 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1236 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1237 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1238 ret = TRUE;
1239 #undef WDPTOLP
1240 #undef HDPTOLP
1241 TRACE("text metrics:\n"
1242 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1243 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1244 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1245 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1246 " PitchAndFamily = %02x\n"
1247 " --------------------\n"
1248 " InternalLeading = %i\n"
1249 " Ascent = %i\n"
1250 " Descent = %i\n"
1251 " Height = %i\n",
1252 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1253 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1254 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1255 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1256 metrics->tmPitchAndFamily,
1257 metrics->tmInternalLeading,
1258 metrics->tmAscent,
1259 metrics->tmDescent,
1260 metrics->tmHeight );
1262 release_dc_ptr( dc );
1263 return ret;
1267 /***********************************************************************
1268 * GetOutlineTextMetricsA (GDI32.@)
1269 * Gets metrics for TrueType fonts.
1271 * NOTES
1272 * If the supplied buffer isn't big enough Windows partially fills it up to
1273 * its given length and returns that length.
1275 * RETURNS
1276 * Success: Non-zero or size of required buffer
1277 * Failure: 0
1279 UINT WINAPI GetOutlineTextMetricsA(
1280 HDC hdc, /* [in] Handle of device context */
1281 UINT cbData, /* [in] Size of metric data array */
1282 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1284 char buf[512], *ptr;
1285 UINT ret, needed;
1286 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1287 OUTLINETEXTMETRICA *output = lpOTM;
1288 INT left, len;
1290 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1291 return 0;
1292 if(ret > sizeof(buf))
1293 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1294 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1296 needed = sizeof(OUTLINETEXTMETRICA);
1297 if(lpOTMW->otmpFamilyName)
1298 needed += WideCharToMultiByte(CP_ACP, 0,
1299 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1300 NULL, 0, NULL, NULL);
1301 if(lpOTMW->otmpFaceName)
1302 needed += WideCharToMultiByte(CP_ACP, 0,
1303 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1304 NULL, 0, NULL, NULL);
1305 if(lpOTMW->otmpStyleName)
1306 needed += WideCharToMultiByte(CP_ACP, 0,
1307 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1308 NULL, 0, NULL, NULL);
1309 if(lpOTMW->otmpFullName)
1310 needed += WideCharToMultiByte(CP_ACP, 0,
1311 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1312 NULL, 0, NULL, NULL);
1314 if(!lpOTM) {
1315 ret = needed;
1316 goto end;
1319 TRACE("needed = %d\n", needed);
1320 if(needed > cbData)
1321 /* Since the supplied buffer isn't big enough, we'll alloc one
1322 that is and memcpy the first cbData bytes into the lpOTM at
1323 the end. */
1324 output = HeapAlloc(GetProcessHeap(), 0, needed);
1326 ret = output->otmSize = min(needed, cbData);
1327 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1328 output->otmFiller = 0;
1329 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1330 output->otmfsSelection = lpOTMW->otmfsSelection;
1331 output->otmfsType = lpOTMW->otmfsType;
1332 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1333 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1334 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1335 output->otmEMSquare = lpOTMW->otmEMSquare;
1336 output->otmAscent = lpOTMW->otmAscent;
1337 output->otmDescent = lpOTMW->otmDescent;
1338 output->otmLineGap = lpOTMW->otmLineGap;
1339 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1340 output->otmsXHeight = lpOTMW->otmsXHeight;
1341 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1342 output->otmMacAscent = lpOTMW->otmMacAscent;
1343 output->otmMacDescent = lpOTMW->otmMacDescent;
1344 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1345 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1346 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1347 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1348 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1349 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1350 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1351 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1352 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1353 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1356 ptr = (char*)(output + 1);
1357 left = needed - sizeof(*output);
1359 if(lpOTMW->otmpFamilyName) {
1360 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1361 len = WideCharToMultiByte(CP_ACP, 0,
1362 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1363 ptr, left, NULL, NULL);
1364 left -= len;
1365 ptr += len;
1366 } else
1367 output->otmpFamilyName = 0;
1369 if(lpOTMW->otmpFaceName) {
1370 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1371 len = WideCharToMultiByte(CP_ACP, 0,
1372 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1373 ptr, left, NULL, NULL);
1374 left -= len;
1375 ptr += len;
1376 } else
1377 output->otmpFaceName = 0;
1379 if(lpOTMW->otmpStyleName) {
1380 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1381 len = WideCharToMultiByte(CP_ACP, 0,
1382 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1383 ptr, left, NULL, NULL);
1384 left -= len;
1385 ptr += len;
1386 } else
1387 output->otmpStyleName = 0;
1389 if(lpOTMW->otmpFullName) {
1390 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1391 len = WideCharToMultiByte(CP_ACP, 0,
1392 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1393 ptr, left, NULL, NULL);
1394 left -= len;
1395 } else
1396 output->otmpFullName = 0;
1398 assert(left == 0);
1400 if(output != lpOTM) {
1401 memcpy(lpOTM, output, cbData);
1402 HeapFree(GetProcessHeap(), 0, output);
1404 /* check if the string offsets really fit into the provided size */
1405 /* FIXME: should we check string length as well? */
1406 /* make sure that we don't read/write beyond the provided buffer */
1407 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(LPSTR))
1409 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1410 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1413 /* make sure that we don't read/write beyond the provided buffer */
1414 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(LPSTR))
1416 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1417 lpOTM->otmpFaceName = 0; /* doesn't fit */
1420 /* make sure that we don't read/write beyond the provided buffer */
1421 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(LPSTR))
1423 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1424 lpOTM->otmpStyleName = 0; /* doesn't fit */
1427 /* make sure that we don't read/write beyond the provided buffer */
1428 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(LPSTR))
1430 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1431 lpOTM->otmpFullName = 0; /* doesn't fit */
1435 end:
1436 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1437 HeapFree(GetProcessHeap(), 0, lpOTMW);
1439 return ret;
1443 /***********************************************************************
1444 * GetOutlineTextMetricsW [GDI32.@]
1446 UINT WINAPI GetOutlineTextMetricsW(
1447 HDC hdc, /* [in] Handle of device context */
1448 UINT cbData, /* [in] Size of metric data array */
1449 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1451 DC *dc = get_dc_ptr( hdc );
1452 OUTLINETEXTMETRICW *output = lpOTM;
1453 PHYSDEV dev;
1454 UINT ret;
1456 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1457 if(!dc) return 0;
1459 dev = GET_DC_PHYSDEV( dc, pGetOutlineTextMetrics );
1460 ret = dev->funcs->pGetOutlineTextMetrics( dev, cbData, output );
1462 if (lpOTM && ret > cbData)
1464 output = HeapAlloc(GetProcessHeap(), 0, ret);
1465 ret = dev->funcs->pGetOutlineTextMetrics( dev, ret, output );
1468 if (lpOTM && ret)
1470 output->otmTextMetrics.tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1471 output->otmTextMetrics.tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1473 #define WDPTOLP(x) ((x<0)? \
1474 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1475 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1476 #define HDPTOLP(y) ((y<0)? \
1477 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1478 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1480 output->otmTextMetrics.tmHeight = HDPTOLP(output->otmTextMetrics.tmHeight);
1481 output->otmTextMetrics.tmAscent = HDPTOLP(output->otmTextMetrics.tmAscent);
1482 output->otmTextMetrics.tmDescent = HDPTOLP(output->otmTextMetrics.tmDescent);
1483 output->otmTextMetrics.tmInternalLeading = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1484 output->otmTextMetrics.tmExternalLeading = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1485 output->otmTextMetrics.tmAveCharWidth = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1486 output->otmTextMetrics.tmMaxCharWidth = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1487 output->otmTextMetrics.tmOverhang = WDPTOLP(output->otmTextMetrics.tmOverhang);
1488 output->otmAscent = HDPTOLP(output->otmAscent);
1489 output->otmDescent = HDPTOLP(output->otmDescent);
1490 output->otmLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmLineGap));
1491 output->otmsCapEmHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsCapEmHeight));
1492 output->otmsXHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsXHeight));
1493 output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1494 output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1495 output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1496 output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1497 output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1498 output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1499 output->otmMacLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmMacLineGap));
1500 output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1501 output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1502 output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1503 output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1504 output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1505 output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1506 output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1507 output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1508 output->otmsStrikeoutSize = abs(INTERNAL_YDSTOWS(dc,output->otmsStrikeoutSize));
1509 output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1510 output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1511 output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1512 #undef WDPTOLP
1513 #undef HDPTOLP
1514 if(output != lpOTM)
1516 memcpy(lpOTM, output, cbData);
1517 HeapFree(GetProcessHeap(), 0, output);
1518 ret = cbData;
1521 release_dc_ptr(dc);
1522 return ret;
1525 static LPSTR FONT_GetCharsByRangeA(HDC hdc, UINT firstChar, UINT lastChar, PINT pByteLen)
1527 INT i, count = lastChar - firstChar + 1;
1528 UINT c;
1529 LPSTR str;
1531 if (count <= 0)
1532 return NULL;
1534 switch (GdiGetCodePage(hdc))
1536 case 932:
1537 case 936:
1538 case 949:
1539 case 950:
1540 case 1361:
1541 if (lastChar > 0xffff)
1542 return NULL;
1543 if ((firstChar ^ lastChar) > 0xff)
1544 return NULL;
1545 break;
1546 default:
1547 if (lastChar > 0xff)
1548 return NULL;
1549 break;
1552 str = HeapAlloc(GetProcessHeap(), 0, count * 2 + 1);
1553 if (str == NULL)
1554 return NULL;
1556 for(i = 0, c = firstChar; c <= lastChar; i++, c++)
1558 if (c > 0xff)
1559 str[i++] = (BYTE)(c >> 8);
1560 str[i] = (BYTE)c;
1562 str[i] = '\0';
1564 *pByteLen = i;
1566 return str;
1569 /***********************************************************************
1570 * GetCharWidthW (GDI32.@)
1571 * GetCharWidth32W (GDI32.@)
1573 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1574 LPINT buffer )
1576 UINT i;
1577 BOOL ret;
1578 PHYSDEV dev;
1579 DC * dc = get_dc_ptr( hdc );
1581 if (!dc) return FALSE;
1583 dev = GET_DC_PHYSDEV( dc, pGetCharWidth );
1584 ret = dev->funcs->pGetCharWidth( dev, firstChar, lastChar, buffer );
1586 if (ret)
1588 /* convert device units to logical */
1589 for( i = firstChar; i <= lastChar; i++, buffer++ )
1590 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1592 release_dc_ptr( dc );
1593 return ret;
1597 /***********************************************************************
1598 * GetCharWidthA (GDI32.@)
1599 * GetCharWidth32A (GDI32.@)
1601 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1602 LPINT buffer )
1604 INT i, wlen;
1605 LPSTR str;
1606 LPWSTR wstr;
1607 BOOL ret = TRUE;
1609 str = FONT_GetCharsByRangeA(hdc, firstChar, lastChar, &i);
1610 if(str == NULL)
1611 return FALSE;
1613 wstr = FONT_mbtowc(hdc, str, i, &wlen, NULL);
1615 for(i = 0; i < wlen; i++)
1617 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1619 ret = FALSE;
1620 break;
1622 buffer++;
1625 HeapFree(GetProcessHeap(), 0, str);
1626 HeapFree(GetProcessHeap(), 0, wstr);
1628 return ret;
1632 /***********************************************************************
1633 * ExtTextOutA (GDI32.@)
1635 * See ExtTextOutW.
1637 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1638 const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1640 INT wlen;
1641 UINT codepage;
1642 LPWSTR p;
1643 BOOL ret;
1644 LPINT lpDxW = NULL;
1646 if (flags & ETO_GLYPH_INDEX)
1647 return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
1649 p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
1651 if (lpDx) {
1652 unsigned int i = 0, j = 0;
1654 /* allocate enough for a ETO_PDY */
1655 lpDxW = HeapAlloc( GetProcessHeap(), 0, 2*wlen*sizeof(INT));
1656 while(i < count) {
1657 if(IsDBCSLeadByteEx(codepage, str[i]))
1659 if(flags & ETO_PDY)
1661 lpDxW[j++] = lpDx[i * 2] + lpDx[(i + 1) * 2];
1662 lpDxW[j++] = lpDx[i * 2 + 1] + lpDx[(i + 1) * 2 + 1];
1664 else
1665 lpDxW[j++] = lpDx[i] + lpDx[i + 1];
1666 i = i + 2;
1668 else
1670 if(flags & ETO_PDY)
1672 lpDxW[j++] = lpDx[i * 2];
1673 lpDxW[j++] = lpDx[i * 2 + 1];
1675 else
1676 lpDxW[j++] = lpDx[i];
1677 i = i + 1;
1682 ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1684 HeapFree( GetProcessHeap(), 0, p );
1685 HeapFree( GetProcessHeap(), 0, lpDxW );
1686 return ret;
1690 /***********************************************************************
1691 * ExtTextOutW (GDI32.@)
1693 * Draws text using the currently selected font, background color, and text color.
1696 * PARAMS
1697 * x,y [I] coordinates of string
1698 * flags [I]
1699 * ETO_GRAYED - undocumented on MSDN
1700 * ETO_OPAQUE - use background color for fill the rectangle
1701 * ETO_CLIPPED - clipping text to the rectangle
1702 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1703 * than encoded characters. Implies ETO_IGNORELANGUAGE
1704 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1705 * Affects BiDi ordering
1706 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1707 * ETO_PDY - unimplemented
1708 * ETO_NUMERICSLATIN - unimplemented always assumed -
1709 * do not translate numbers into locale representations
1710 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1711 * lprect [I] dimensions for clipping or/and opaquing
1712 * str [I] text string
1713 * count [I] number of symbols in string
1714 * lpDx [I] optional parameter with distance between drawing characters
1716 * RETURNS
1717 * Success: TRUE
1718 * Failure: FALSE
1720 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1721 const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1723 BOOL ret = FALSE;
1724 LPWSTR reordered_str = (LPWSTR)str;
1725 WORD *glyphs = NULL;
1726 UINT align = GetTextAlign( hdc );
1727 DWORD layout = GetLayout( hdc );
1728 POINT pt;
1729 TEXTMETRICW tm;
1730 LOGFONTW lf;
1731 double cosEsc, sinEsc;
1732 INT char_extra;
1733 SIZE sz;
1734 RECT rc;
1735 BOOL done_extents = FALSE;
1736 POINT *deltas = NULL, width = {0, 0};
1737 DWORD type;
1738 DC * dc = get_dc_ptr( hdc );
1739 PHYSDEV physdev;
1740 INT breakRem;
1741 static int quietfixme = 0;
1743 if (!dc) return FALSE;
1745 breakRem = dc->breakRem;
1747 if (quietfixme == 0 && flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN))
1749 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN unimplemented\n");
1750 quietfixme = 1;
1753 update_dc( dc );
1754 physdev = GET_DC_PHYSDEV( dc, pExtTextOut );
1755 type = GetObjectType(hdc);
1756 if(type == OBJ_METADC || type == OBJ_ENHMETADC)
1758 ret = physdev->funcs->pExtTextOut( physdev, x, y, flags, lprect, str, count, lpDx );
1759 release_dc_ptr( dc );
1760 return ret;
1763 if (!lprect)
1764 flags &= ~ETO_CLIPPED;
1766 if (flags & ETO_RTLREADING) align |= TA_RTLREADING;
1767 if (layout & LAYOUT_RTL)
1769 if ((align & TA_CENTER) != TA_CENTER) align ^= TA_RIGHT;
1770 align ^= TA_RTLREADING;
1773 if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && count > 0 )
1775 INT cGlyphs;
1776 reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1778 BIDI_Reorder( hdc, str, count, GCP_REORDER,
1779 (align & TA_RTLREADING) ? WINE_GCPW_FORCE_RTL : WINE_GCPW_FORCE_LTR,
1780 reordered_str, count, NULL, &glyphs, &cGlyphs);
1782 flags |= ETO_IGNORELANGUAGE;
1783 if (glyphs)
1785 flags |= ETO_GLYPH_INDEX;
1786 if (cGlyphs != count)
1787 count = cGlyphs;
1790 else if(flags & ETO_GLYPH_INDEX)
1791 glyphs = reordered_str;
1793 TRACE("%p, %d, %d, %08x, %s, %s, %d, %p)\n", hdc, x, y, flags,
1794 wine_dbgstr_rect(lprect), debugstr_wn(str, count), count, lpDx);
1795 TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
1797 if(align & TA_UPDATECP)
1799 GetCurrentPositionEx( hdc, &pt );
1800 x = pt.x;
1801 y = pt.y;
1804 GetTextMetricsW(hdc, &tm);
1805 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1807 if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
1808 lf.lfEscapement = 0;
1810 if(lf.lfEscapement != 0)
1812 cosEsc = cos(lf.lfEscapement * M_PI / 1800);
1813 sinEsc = sin(lf.lfEscapement * M_PI / 1800);
1815 else
1817 cosEsc = 1;
1818 sinEsc = 0;
1821 if(flags & (ETO_CLIPPED | ETO_OPAQUE))
1823 if(!lprect)
1825 if(flags & ETO_GLYPH_INDEX)
1826 GetTextExtentPointI(hdc, glyphs, count, &sz);
1827 else
1828 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1830 done_extents = TRUE;
1831 rc.left = x;
1832 rc.top = y;
1833 rc.right = x + sz.cx;
1834 rc.bottom = y + sz.cy;
1836 else
1838 rc = *lprect;
1841 LPtoDP(hdc, (POINT*)&rc, 2);
1843 if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
1844 if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
1847 if ((flags & ETO_OPAQUE) && !PATH_IsPathOpen(dc->path))
1848 physdev->funcs->pExtTextOut( physdev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL );
1850 if(count == 0)
1852 ret = TRUE;
1853 goto done;
1856 pt.x = x;
1857 pt.y = y;
1858 LPtoDP(hdc, &pt, 1);
1859 x = pt.x;
1860 y = pt.y;
1862 char_extra = GetTextCharacterExtra(hdc);
1863 if(char_extra || dc->breakExtra || breakRem || lpDx || lf.lfEscapement != 0)
1865 UINT i;
1866 SIZE tmpsz;
1867 POINT total = {0, 0}, desired[2];
1869 deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
1870 for(i = 0; i < count; i++)
1872 if(lpDx)
1874 if(flags & ETO_PDY)
1876 deltas[i].x = lpDx[i * 2] + char_extra;
1877 deltas[i].y = -lpDx[i * 2 + 1];
1879 else
1881 deltas[i].x = lpDx[i] + char_extra;
1882 deltas[i].y = 0;
1886 else
1888 if(flags & ETO_GLYPH_INDEX)
1889 GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
1890 else
1891 GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
1893 deltas[i].x = tmpsz.cx;
1894 deltas[i].y = 0;
1897 if (!(flags & ETO_GLYPH_INDEX) && (dc->breakExtra || breakRem) && reordered_str[i] == tm.tmBreakChar)
1899 deltas[i].x = deltas[i].x + dc->breakExtra;
1900 if (breakRem > 0)
1902 breakRem--;
1903 deltas[i].x++;
1906 total.x += deltas[i].x;
1907 total.y += deltas[i].y;
1909 desired[0].x = desired[0].y = 0;
1911 desired[1].x = cosEsc * total.x + sinEsc * total.y;
1912 desired[1].y = -sinEsc * total.x + cosEsc * total.y;
1914 LPtoDP(hdc, desired, 2);
1915 desired[1].x -= desired[0].x;
1916 desired[1].y -= desired[0].y;
1917 if (layout & LAYOUT_RTL) desired[1].x = -desired[1].x;
1919 deltas[i].x = desired[1].x - width.x;
1920 deltas[i].y = desired[1].y - width.y;
1922 width = desired[1];
1924 flags |= ETO_PDY;
1926 else
1928 if(!done_extents)
1930 if(flags & ETO_GLYPH_INDEX)
1931 GetTextExtentPointI(hdc, glyphs, count, &sz);
1932 else
1933 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1934 done_extents = TRUE;
1936 width.x = abs(INTERNAL_XWSTODS(dc, sz.cx));
1937 width.y = 0;
1940 tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
1941 tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
1942 switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
1944 case TA_LEFT:
1945 if (align & TA_UPDATECP)
1947 pt.x = x + width.x;
1948 pt.y = y + width.y;
1949 DPtoLP(hdc, &pt, 1);
1950 MoveToEx(hdc, pt.x, pt.y, NULL);
1952 break;
1954 case TA_CENTER:
1955 x -= width.x / 2;
1956 y -= width.y / 2;
1957 break;
1959 case TA_RIGHT:
1960 x -= width.x;
1961 y -= width.y;
1962 if (align & TA_UPDATECP)
1964 pt.x = x;
1965 pt.y = y;
1966 DPtoLP(hdc, &pt, 1);
1967 MoveToEx(hdc, pt.x, pt.y, NULL);
1969 break;
1972 switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
1974 case TA_TOP:
1975 y += tm.tmAscent * cosEsc;
1976 x += tm.tmAscent * sinEsc;
1977 break;
1979 case TA_BOTTOM:
1980 y -= tm.tmDescent * cosEsc;
1981 x -= tm.tmDescent * sinEsc;
1982 break;
1984 case TA_BASELINE:
1985 break;
1988 if (GetBkMode(hdc) != TRANSPARENT && !PATH_IsPathOpen(dc->path))
1990 if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
1992 if(!(flags & ETO_OPAQUE) || x < rc.left || x + width.x >= rc.right ||
1993 y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
1995 RECT rc;
1996 rc.left = x;
1997 rc.right = x + width.x;
1998 rc.top = y - tm.tmAscent;
1999 rc.bottom = y + tm.tmDescent;
2001 if(flags & ETO_CLIPPED)
2003 rc.left = max(lprect->left, rc.left);
2004 rc.right = min(lprect->right, rc.right);
2005 rc.top = max(lprect->top, rc.top);
2006 rc.bottom = min(lprect->bottom, rc.bottom);
2008 if(rc.left < rc.right && rc.top < rc.bottom)
2009 physdev->funcs->pExtTextOut( physdev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL );
2014 if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
2016 HFONT orig_font = dc->hFont, cur_font;
2017 UINT glyph;
2018 INT span = 0;
2019 POINT *offsets = NULL;
2020 unsigned int i;
2022 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2023 for(i = 0; i < count; i++)
2025 WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
2026 if(cur_font != dc->hFont)
2028 if(!offsets)
2030 unsigned int j;
2031 offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
2032 offsets[0].x = offsets[0].y = 0;
2034 if(!deltas)
2036 SIZE tmpsz;
2037 for(j = 1; j < count; j++)
2039 GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
2040 offsets[j].x = offsets[j - 1].x + abs(INTERNAL_XWSTODS(dc, tmpsz.cx));
2041 offsets[j].y = 0;
2044 else
2046 for(j = 1; j < count; j++)
2048 offsets[j].x = offsets[j - 1].x + deltas[j].x;
2049 offsets[j].y = offsets[j - 1].y + deltas[j].y;
2053 if(span)
2055 if (PATH_IsPathOpen(dc->path))
2056 ret = PATH_ExtTextOut(dc, x + offsets[i - span].x, y + offsets[i - span].y,
2057 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2058 glyphs, span, deltas ? (INT*)(deltas + (i - span)) : NULL);
2059 else
2060 physdev->funcs->pExtTextOut( physdev, x + offsets[i - span].x,
2061 y + offsets[i - span].y,
2062 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc, glyphs,
2063 span, deltas ? (INT*)(deltas + (i - span)) : NULL);
2064 span = 0;
2066 SelectObject(hdc, cur_font);
2068 glyphs[span++] = glyph;
2070 if(i == count - 1)
2072 if (PATH_IsPathOpen(dc->path))
2073 ret = PATH_ExtTextOut(dc, x + (offsets ? offsets[count - span].x : 0),
2074 y + (offsets ? offsets[count - span].y : 0),
2075 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2076 glyphs, span, deltas ? (INT*)(deltas + (count - span)) : NULL);
2077 else
2078 ret = physdev->funcs->pExtTextOut(physdev, x + (offsets ? offsets[count - span].x : 0),
2079 y + (offsets ? offsets[count - span].y : 0),
2080 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc, glyphs,
2081 span, deltas ? (INT*)(deltas + (count - span)) : NULL);
2082 SelectObject(hdc, orig_font);
2083 HeapFree(GetProcessHeap(), 0, offsets);
2087 else
2089 if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
2091 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2092 GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
2093 flags |= ETO_GLYPH_INDEX;
2096 if (PATH_IsPathOpen(dc->path))
2097 ret = PATH_ExtTextOut(dc, x, y, (flags & ~ETO_OPAQUE), &rc,
2098 glyphs ? glyphs : reordered_str, count, (INT*)deltas);
2099 else
2100 ret = physdev->funcs->pExtTextOut( physdev, x, y, (flags & ~ETO_OPAQUE), &rc,
2101 glyphs ? glyphs : reordered_str, count, (INT*)deltas );
2104 done:
2105 HeapFree(GetProcessHeap(), 0, deltas);
2106 if(glyphs != reordered_str)
2107 HeapFree(GetProcessHeap(), 0, glyphs);
2108 if(reordered_str != str)
2109 HeapFree(GetProcessHeap(), 0, reordered_str);
2111 release_dc_ptr( dc );
2113 if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2115 int underlinePos, strikeoutPos;
2116 int underlineWidth, strikeoutWidth;
2117 UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2118 OUTLINETEXTMETRICW* otm = NULL;
2120 if(!size)
2122 underlinePos = 0;
2123 underlineWidth = tm.tmAscent / 20 + 1;
2124 strikeoutPos = tm.tmAscent / 2;
2125 strikeoutWidth = underlineWidth;
2127 else
2129 otm = HeapAlloc(GetProcessHeap(), 0, size);
2130 GetOutlineTextMetricsW(hdc, size, otm);
2131 underlinePos = otm->otmsUnderscorePosition;
2132 underlineWidth = otm->otmsUnderscoreSize;
2133 strikeoutPos = otm->otmsStrikeoutPosition;
2134 strikeoutWidth = otm->otmsStrikeoutSize;
2135 HeapFree(GetProcessHeap(), 0, otm);
2138 if (PATH_IsPathOpen(dc->path))
2140 POINT pts[5];
2141 HPEN hpen;
2142 HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2144 hbrush = SelectObject(hdc, hbrush);
2145 hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2147 if (lf.lfUnderline)
2149 pts[0].x = x - underlinePos * sinEsc;
2150 pts[0].y = y - underlinePos * cosEsc;
2151 pts[1].x = x + width.x - underlinePos * sinEsc;
2152 pts[1].y = y + width.y - underlinePos * cosEsc;
2153 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2154 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2155 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2156 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2157 pts[4].x = pts[0].x;
2158 pts[4].y = pts[0].y;
2159 DPtoLP(hdc, pts, 5);
2160 Polygon(hdc, pts, 5);
2163 if (lf.lfStrikeOut)
2165 pts[0].x = x - strikeoutPos * sinEsc;
2166 pts[0].y = y - strikeoutPos * cosEsc;
2167 pts[1].x = x + width.x - strikeoutPos * sinEsc;
2168 pts[1].y = y + width.y - strikeoutPos * cosEsc;
2169 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2170 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2171 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2172 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2173 pts[4].x = pts[0].x;
2174 pts[4].y = pts[0].y;
2175 DPtoLP(hdc, pts, 5);
2176 Polygon(hdc, pts, 5);
2179 SelectObject(hdc, hpen);
2180 hbrush = SelectObject(hdc, hbrush);
2181 DeleteObject(hbrush);
2183 else
2185 POINT pts[2], oldpt;
2186 HPEN hpen;
2188 if (lf.lfUnderline)
2190 hpen = CreatePen(PS_SOLID, underlineWidth, GetTextColor(hdc));
2191 hpen = SelectObject(hdc, hpen);
2192 pts[0].x = x;
2193 pts[0].y = y;
2194 pts[1].x = x + width.x;
2195 pts[1].y = y + width.y;
2196 DPtoLP(hdc, pts, 2);
2197 MoveToEx(hdc, pts[0].x - underlinePos * sinEsc, pts[0].y - underlinePos * cosEsc, &oldpt);
2198 LineTo(hdc, pts[1].x - underlinePos * sinEsc, pts[1].y - underlinePos * cosEsc);
2199 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2200 DeleteObject(SelectObject(hdc, hpen));
2203 if (lf.lfStrikeOut)
2205 hpen = CreatePen(PS_SOLID, strikeoutWidth, GetTextColor(hdc));
2206 hpen = SelectObject(hdc, hpen);
2207 pts[0].x = x;
2208 pts[0].y = y;
2209 pts[1].x = x + width.x;
2210 pts[1].y = y + width.y;
2211 DPtoLP(hdc, pts, 2);
2212 MoveToEx(hdc, pts[0].x - strikeoutPos * sinEsc, pts[0].y - strikeoutPos * cosEsc, &oldpt);
2213 LineTo(hdc, pts[1].x - strikeoutPos * sinEsc, pts[1].y - strikeoutPos * cosEsc);
2214 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2215 DeleteObject(SelectObject(hdc, hpen));
2220 return ret;
2224 /***********************************************************************
2225 * TextOutA (GDI32.@)
2227 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2229 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2233 /***********************************************************************
2234 * TextOutW (GDI32.@)
2236 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2238 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2242 /***********************************************************************
2243 * PolyTextOutA (GDI32.@)
2245 * See PolyTextOutW.
2247 BOOL WINAPI PolyTextOutA( HDC hdc, const POLYTEXTA *pptxt, INT cStrings )
2249 for (; cStrings>0; cStrings--, pptxt++)
2250 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2251 return FALSE;
2252 return TRUE;
2257 /***********************************************************************
2258 * PolyTextOutW (GDI32.@)
2260 * Draw several Strings
2262 * RETURNS
2263 * TRUE: Success.
2264 * FALSE: Failure.
2266 BOOL WINAPI PolyTextOutW( HDC hdc, const POLYTEXTW *pptxt, INT cStrings )
2268 for (; cStrings>0; cStrings--, pptxt++)
2269 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2270 return FALSE;
2271 return TRUE;
2275 /***********************************************************************
2276 * SetMapperFlags (GDI32.@)
2278 DWORD WINAPI SetMapperFlags( HDC hdc, DWORD flags )
2280 DC *dc = get_dc_ptr( hdc );
2281 DWORD ret = GDI_ERROR;
2283 if (dc)
2285 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetMapperFlags );
2286 flags = physdev->funcs->pSetMapperFlags( physdev, flags );
2287 if (flags != GDI_ERROR)
2289 ret = dc->mapperFlags;
2290 dc->mapperFlags = flags;
2292 release_dc_ptr( dc );
2294 return ret;
2297 /***********************************************************************
2298 * GetAspectRatioFilterEx (GDI32.@)
2300 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2302 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2303 return FALSE;
2307 /***********************************************************************
2308 * GetCharABCWidthsA (GDI32.@)
2310 * See GetCharABCWidthsW.
2312 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2313 LPABC abc )
2315 INT i, wlen;
2316 LPSTR str;
2317 LPWSTR wstr;
2318 BOOL ret = TRUE;
2320 str = FONT_GetCharsByRangeA(hdc, firstChar, lastChar, &i);
2321 if (str == NULL)
2322 return FALSE;
2324 wstr = FONT_mbtowc(hdc, str, i, &wlen, NULL);
2325 if (wstr == NULL)
2327 HeapFree(GetProcessHeap(), 0, str);
2328 return FALSE;
2331 for(i = 0; i < wlen; i++)
2333 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2335 ret = FALSE;
2336 break;
2338 abc++;
2341 HeapFree(GetProcessHeap(), 0, str);
2342 HeapFree(GetProcessHeap(), 0, wstr);
2344 return ret;
2348 /******************************************************************************
2349 * GetCharABCWidthsW [GDI32.@]
2351 * Retrieves widths of characters in range.
2353 * PARAMS
2354 * hdc [I] Handle of device context
2355 * firstChar [I] First character in range to query
2356 * lastChar [I] Last character in range to query
2357 * abc [O] Address of character-width structure
2359 * NOTES
2360 * Only works with TrueType fonts
2362 * RETURNS
2363 * Success: TRUE
2364 * Failure: FALSE
2366 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2367 LPABC abc )
2369 DC *dc = get_dc_ptr(hdc);
2370 PHYSDEV dev;
2371 unsigned int i;
2372 BOOL ret;
2374 if (!dc) return FALSE;
2376 if (!abc)
2378 release_dc_ptr( dc );
2379 return FALSE;
2382 dev = GET_DC_PHYSDEV( dc, pGetCharABCWidths );
2383 ret = dev->funcs->pGetCharABCWidths( dev, firstChar, lastChar, abc );
2384 if (ret)
2386 /* convert device units to logical */
2387 for( i = firstChar; i <= lastChar; i++, abc++ ) {
2388 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2389 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2390 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2394 release_dc_ptr( dc );
2395 return ret;
2399 /******************************************************************************
2400 * GetCharABCWidthsI [GDI32.@]
2402 * Retrieves widths of characters in range.
2404 * PARAMS
2405 * hdc [I] Handle of device context
2406 * firstChar [I] First glyphs in range to query
2407 * count [I] Last glyphs in range to query
2408 * pgi [i] Array of glyphs to query
2409 * abc [O] Address of character-width structure
2411 * NOTES
2412 * Only works with TrueType fonts
2414 * RETURNS
2415 * Success: TRUE
2416 * Failure: FALSE
2418 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2419 LPWORD pgi, LPABC abc)
2421 DC *dc = get_dc_ptr(hdc);
2422 PHYSDEV dev;
2423 unsigned int i;
2424 BOOL ret;
2426 if (!dc) return FALSE;
2428 if (!abc)
2430 release_dc_ptr( dc );
2431 return FALSE;
2434 dev = GET_DC_PHYSDEV( dc, pGetCharABCWidthsI );
2435 ret = dev->funcs->pGetCharABCWidthsI( dev, firstChar, count, pgi, abc );
2436 if (ret)
2438 /* convert device units to logical */
2439 for( i = 0; i < count; i++, abc++ ) {
2440 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2441 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2442 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2446 release_dc_ptr( dc );
2447 return ret;
2451 /***********************************************************************
2452 * GetGlyphOutlineA (GDI32.@)
2454 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2455 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2456 LPVOID lpBuffer, const MAT2 *lpmat2 )
2458 if (!lpmat2) return GDI_ERROR;
2460 if(!(fuFormat & GGO_GLYPH_INDEX)) {
2461 UINT cp;
2462 int len;
2463 char mbchs[2];
2465 cp = GdiGetCodePage(hdc);
2466 if (IsDBCSLeadByteEx(cp, uChar >> 8)) {
2467 len = 2;
2468 mbchs[0] = (uChar & 0xff00) >> 8;
2469 mbchs[1] = (uChar & 0xff);
2470 } else {
2471 len = 1;
2472 mbchs[0] = (uChar & 0xff);
2474 uChar = 0;
2475 MultiByteToWideChar(cp, 0, mbchs, len, (LPWSTR)&uChar, 1);
2478 return GetGlyphOutlineW(hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer,
2479 lpmat2);
2482 /***********************************************************************
2483 * GetGlyphOutlineW (GDI32.@)
2485 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2486 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2487 LPVOID lpBuffer, const MAT2 *lpmat2 )
2489 DC *dc;
2490 DWORD ret;
2491 PHYSDEV dev;
2493 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2494 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2496 if (!lpmat2) return GDI_ERROR;
2498 dc = get_dc_ptr(hdc);
2499 if(!dc) return GDI_ERROR;
2501 dev = GET_DC_PHYSDEV( dc, pGetGlyphOutline );
2502 ret = dev->funcs->pGetGlyphOutline( dev, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2503 release_dc_ptr( dc );
2504 return ret;
2508 /***********************************************************************
2509 * CreateScalableFontResourceA (GDI32.@)
2511 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2512 LPCSTR lpszResourceFile,
2513 LPCSTR lpszFontFile,
2514 LPCSTR lpszCurrentPath )
2516 LPWSTR lpszResourceFileW = NULL;
2517 LPWSTR lpszFontFileW = NULL;
2518 LPWSTR lpszCurrentPathW = NULL;
2519 int len;
2520 BOOL ret;
2522 if (lpszResourceFile)
2524 len = MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, NULL, 0);
2525 lpszResourceFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2526 MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, lpszResourceFileW, len);
2529 if (lpszFontFile)
2531 len = MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, NULL, 0);
2532 lpszFontFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2533 MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, lpszFontFileW, len);
2536 if (lpszCurrentPath)
2538 len = MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, NULL, 0);
2539 lpszCurrentPathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2540 MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, lpszCurrentPathW, len);
2543 ret = CreateScalableFontResourceW(fHidden, lpszResourceFileW,
2544 lpszFontFileW, lpszCurrentPathW);
2546 HeapFree(GetProcessHeap(), 0, lpszResourceFileW);
2547 HeapFree(GetProcessHeap(), 0, lpszFontFileW);
2548 HeapFree(GetProcessHeap(), 0, lpszCurrentPathW);
2550 return ret;
2553 /***********************************************************************
2554 * CreateScalableFontResourceW (GDI32.@)
2556 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2557 LPCWSTR lpszResourceFile,
2558 LPCWSTR lpszFontFile,
2559 LPCWSTR lpszCurrentPath )
2561 HANDLE f;
2562 FIXME("(%d,%s,%s,%s): stub\n",
2563 fHidden, debugstr_w(lpszResourceFile), debugstr_w(lpszFontFile),
2564 debugstr_w(lpszCurrentPath) );
2566 /* fHidden=1 - only visible for the calling app, read-only, not
2567 * enumerated with EnumFonts/EnumFontFamilies
2568 * lpszCurrentPath can be NULL
2571 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2572 if ((f = CreateFileW(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2573 CloseHandle(f);
2574 SetLastError(ERROR_FILE_EXISTS);
2575 return FALSE;
2577 return FALSE; /* create failed */
2580 /*************************************************************************
2581 * GetKerningPairsA (GDI32.@)
2583 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2584 LPKERNINGPAIR kern_pairA )
2586 UINT cp;
2587 CPINFO cpi;
2588 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2589 KERNINGPAIR *kern_pairW;
2591 if (!cPairs && kern_pairA)
2593 SetLastError(ERROR_INVALID_PARAMETER);
2594 return 0;
2597 cp = GdiGetCodePage(hDC);
2599 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2600 * to fail on an invalid character for CP_SYMBOL.
2602 cpi.DefaultChar[0] = 0;
2603 if (cp != CP_SYMBOL && !GetCPInfo(cp, &cpi))
2605 FIXME("Can't find codepage %u info\n", cp);
2606 return 0;
2609 total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2610 if (!total_kern_pairs) return 0;
2612 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2613 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2615 for (i = 0; i < total_kern_pairs; i++)
2617 char first, second;
2619 if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2620 continue;
2622 if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2623 continue;
2625 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2626 continue;
2628 if (kern_pairA)
2630 if (kern_pairs_copied >= cPairs) break;
2632 kern_pairA->wFirst = (BYTE)first;
2633 kern_pairA->wSecond = (BYTE)second;
2634 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2635 kern_pairA++;
2637 kern_pairs_copied++;
2640 HeapFree(GetProcessHeap(), 0, kern_pairW);
2642 return kern_pairs_copied;
2645 /*************************************************************************
2646 * GetKerningPairsW (GDI32.@)
2648 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2649 LPKERNINGPAIR lpKerningPairs )
2651 DC *dc;
2652 DWORD ret;
2653 PHYSDEV dev;
2655 TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2657 if (!cPairs && lpKerningPairs)
2659 SetLastError(ERROR_INVALID_PARAMETER);
2660 return 0;
2663 dc = get_dc_ptr(hDC);
2664 if (!dc) return 0;
2666 dev = GET_DC_PHYSDEV( dc, pGetKerningPairs );
2667 ret = dev->funcs->pGetKerningPairs( dev, cPairs, lpKerningPairs );
2668 release_dc_ptr( dc );
2669 return ret;
2672 /*************************************************************************
2673 * TranslateCharsetInfo [GDI32.@]
2675 * Fills a CHARSETINFO structure for a character set, code page, or
2676 * font. This allows making the correspondence between different labels
2677 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2678 * of the same encoding.
2680 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2681 * only one codepage should be set in *lpSrc.
2683 * RETURNS
2684 * TRUE on success, FALSE on failure.
2687 BOOL WINAPI TranslateCharsetInfo(
2688 LPDWORD lpSrc, /* [in]
2689 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2690 if flags == TCI_SRCCHARSET: a character set value
2691 if flags == TCI_SRCCODEPAGE: a code page value
2693 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2694 DWORD flags /* [in] determines interpretation of lpSrc */)
2696 int index = 0;
2697 switch (flags) {
2698 case TCI_SRCFONTSIG:
2699 while (index < MAXTCIINDEX && !(*lpSrc>>index & 0x0001)) index++;
2700 break;
2701 case TCI_SRCCODEPAGE:
2702 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciACP) index++;
2703 break;
2704 case TCI_SRCCHARSET:
2705 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciCharset) index++;
2706 break;
2707 default:
2708 return FALSE;
2710 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2711 *lpCs = FONT_tci[index];
2712 return TRUE;
2715 /*************************************************************************
2716 * GetFontLanguageInfo (GDI32.@)
2718 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2720 FONTSIGNATURE fontsig;
2721 static const DWORD GCP_DBCS_MASK=0x003F0000,
2722 GCP_DIACRITIC_MASK=0x00000000,
2723 FLI_GLYPHS_MASK=0x00000000,
2724 GCP_GLYPHSHAPE_MASK=0x00000040,
2725 GCP_KASHIDA_MASK=0x00000000,
2726 GCP_LIGATE_MASK=0x00000000,
2727 GCP_USEKERNING_MASK=0x00000000,
2728 GCP_REORDER_MASK=0x00000060;
2730 DWORD result=0;
2732 GetTextCharsetInfo( hdc, &fontsig, 0 );
2733 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2735 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2736 result|=GCP_DBCS;
2738 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2739 result|=GCP_DIACRITIC;
2741 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2742 result|=FLI_GLYPHS;
2744 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2745 result|=GCP_GLYPHSHAPE;
2747 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2748 result|=GCP_KASHIDA;
2750 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2751 result|=GCP_LIGATE;
2753 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2754 result|=GCP_USEKERNING;
2756 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2757 if( GetTextAlign( hdc) & TA_RTLREADING )
2758 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2759 result|=GCP_REORDER;
2761 return result;
2765 /*************************************************************************
2766 * GetFontData [GDI32.@]
2768 * Retrieve data for TrueType font.
2770 * RETURNS
2772 * success: Number of bytes returned
2773 * failure: GDI_ERROR
2775 * NOTES
2777 * Calls SetLastError()
2780 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2781 LPVOID buffer, DWORD length)
2783 DC *dc = get_dc_ptr(hdc);
2784 DWORD ret = GDI_ERROR;
2786 if(!dc) return GDI_ERROR;
2788 if(dc->gdiFont)
2789 ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2791 release_dc_ptr( dc );
2792 return ret;
2795 /*************************************************************************
2796 * GetGlyphIndicesA [GDI32.@]
2798 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2799 LPWORD pgi, DWORD flags)
2801 DWORD ret;
2802 WCHAR *lpstrW;
2803 INT countW;
2805 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2806 hdc, debugstr_an(lpstr, count), count, pgi, flags);
2808 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2809 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2810 HeapFree(GetProcessHeap(), 0, lpstrW);
2812 return ret;
2815 /*************************************************************************
2816 * GetGlyphIndicesW [GDI32.@]
2818 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2819 LPWORD pgi, DWORD flags)
2821 DC *dc = get_dc_ptr(hdc);
2822 PHYSDEV dev;
2823 DWORD ret;
2825 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2826 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2828 if(!dc) return GDI_ERROR;
2830 dev = GET_DC_PHYSDEV( dc, pGetGlyphIndices );
2831 ret = dev->funcs->pGetGlyphIndices( dev, lpstr, count, pgi, flags );
2832 release_dc_ptr( dc );
2833 return ret;
2836 /*************************************************************************
2837 * GetCharacterPlacementA [GDI32.@]
2839 * See GetCharacterPlacementW.
2841 * NOTES:
2842 * the web browser control of ie4 calls this with dwFlags=0
2844 DWORD WINAPI
2845 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2846 INT nMaxExtent, GCP_RESULTSA *lpResults,
2847 DWORD dwFlags)
2849 WCHAR *lpStringW;
2850 INT uCountW;
2851 GCP_RESULTSW resultsW;
2852 DWORD ret;
2853 UINT font_cp;
2855 TRACE("%s, %d, %d, 0x%08x\n",
2856 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2858 /* both structs are equal in size */
2859 memcpy(&resultsW, lpResults, sizeof(resultsW));
2861 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2862 if(lpResults->lpOutString)
2863 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2865 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2867 lpResults->nGlyphs = resultsW.nGlyphs;
2868 lpResults->nMaxFit = resultsW.nMaxFit;
2870 if(lpResults->lpOutString) {
2871 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2872 lpResults->lpOutString, uCount, NULL, NULL );
2875 HeapFree(GetProcessHeap(), 0, lpStringW);
2876 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2878 return ret;
2881 /*************************************************************************
2882 * GetCharacterPlacementW [GDI32.@]
2884 * Retrieve information about a string. This includes the width, reordering,
2885 * Glyphing and so on.
2887 * RETURNS
2889 * The width and height of the string if successful, 0 if failed.
2891 * BUGS
2893 * All flags except GCP_REORDER are not yet implemented.
2894 * Reordering is not 100% compliant to the Windows BiDi method.
2895 * Caret positioning is not yet implemented for BiDi.
2896 * Classes are not yet implemented.
2899 DWORD WINAPI
2900 GetCharacterPlacementW(
2901 HDC hdc, /* [in] Device context for which the rendering is to be done */
2902 LPCWSTR lpString, /* [in] The string for which information is to be returned */
2903 INT uCount, /* [in] Number of WORDS in string. */
2904 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
2905 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2906 DWORD dwFlags /* [in] Flags specifying how to process the string */
2909 DWORD ret=0;
2910 SIZE size;
2911 UINT i, nSet;
2913 TRACE("%s, %d, %d, 0x%08x\n",
2914 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2916 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2917 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2918 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2919 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2920 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2922 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08x ignored\n", dwFlags);
2923 if(lpResults->lpClass) FIXME("classes not implemented\n");
2924 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2925 FIXME("Caret positions for complex scripts not implemented\n");
2927 nSet = (UINT)uCount;
2928 if(nSet > lpResults->nGlyphs)
2929 nSet = lpResults->nGlyphs;
2931 /* return number of initialized fields */
2932 lpResults->nGlyphs = nSet;
2934 if((dwFlags&GCP_REORDER)==0 )
2936 /* Treat the case where no special handling was requested in a fastpath way */
2937 /* copy will do if the GCP_REORDER flag is not set */
2938 if(lpResults->lpOutString)
2939 memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
2941 if(lpResults->lpOrder)
2943 for(i = 0; i < nSet; i++)
2944 lpResults->lpOrder[i] = i;
2946 } else
2948 BIDI_Reorder(NULL, lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
2949 nSet, lpResults->lpOrder, NULL, NULL );
2952 /* FIXME: Will use the placement chars */
2953 if (lpResults->lpDx)
2955 int c;
2956 for (i = 0; i < nSet; i++)
2958 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
2959 lpResults->lpDx[i]= c;
2963 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
2965 int pos = 0;
2967 lpResults->lpCaretPos[0] = 0;
2968 for (i = 1; i < nSet; i++)
2969 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
2970 lpResults->lpCaretPos[i] = (pos += size.cx);
2973 if(lpResults->lpGlyphs)
2974 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
2976 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
2977 ret = MAKELONG(size.cx, size.cy);
2979 return ret;
2982 /*************************************************************************
2983 * GetCharABCWidthsFloatA [GDI32.@]
2985 * See GetCharABCWidthsFloatW.
2987 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
2989 INT i, wlen;
2990 LPSTR str;
2991 LPWSTR wstr;
2992 BOOL ret = TRUE;
2994 str = FONT_GetCharsByRangeA(hdc, first, last, &i);
2995 if (str == NULL)
2996 return FALSE;
2998 wstr = FONT_mbtowc( hdc, str, i, &wlen, NULL );
3000 for (i = 0; i < wlen; i++)
3002 if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
3004 ret = FALSE;
3005 break;
3007 abcf++;
3010 HeapFree( GetProcessHeap(), 0, str );
3011 HeapFree( GetProcessHeap(), 0, wstr );
3013 return ret;
3016 /*************************************************************************
3017 * GetCharABCWidthsFloatW [GDI32.@]
3019 * Retrieves widths of a range of characters.
3021 * PARAMS
3022 * hdc [I] Handle to device context.
3023 * first [I] First character in range to query.
3024 * last [I] Last character in range to query.
3025 * abcf [O] Array of LPABCFLOAT structures.
3027 * RETURNS
3028 * Success: TRUE
3029 * Failure: FALSE
3031 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3033 UINT i;
3034 ABC *abc;
3035 PHYSDEV dev;
3036 BOOL ret = FALSE;
3037 DC *dc = get_dc_ptr( hdc );
3039 TRACE("%p, %d, %d, %p\n", hdc, first, last, abcf);
3041 if (!dc) return FALSE;
3043 if (!abcf) goto done;
3044 if (!(abc = HeapAlloc( GetProcessHeap(), 0, (last - first + 1) * sizeof(*abc) ))) goto done;
3046 dev = GET_DC_PHYSDEV( dc, pGetCharABCWidths );
3047 ret = dev->funcs->pGetCharABCWidths( dev, first, last, abc );
3048 if (ret)
3050 /* convert device units to logical */
3051 for (i = first; i <= last; i++, abcf++)
3053 abcf->abcfA = abc->abcA * dc->xformVport2World.eM11;
3054 abcf->abcfB = abc->abcB * dc->xformVport2World.eM11;
3055 abcf->abcfC = abc->abcC * dc->xformVport2World.eM11;
3058 HeapFree( GetProcessHeap(), 0, abc );
3060 done:
3061 release_dc_ptr( dc );
3062 return ret;
3065 /*************************************************************************
3066 * GetCharWidthFloatA [GDI32.@]
3068 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
3069 UINT iLastChar, PFLOAT pxBuffer)
3071 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3072 return 0;
3075 /*************************************************************************
3076 * GetCharWidthFloatW [GDI32.@]
3078 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
3079 UINT iLastChar, PFLOAT pxBuffer)
3081 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3082 return 0;
3086 /***********************************************************************
3088 * Font Resource API *
3090 ***********************************************************************/
3092 /***********************************************************************
3093 * AddFontResourceA (GDI32.@)
3095 INT WINAPI AddFontResourceA( LPCSTR str )
3097 return AddFontResourceExA( str, 0, NULL);
3100 /***********************************************************************
3101 * AddFontResourceW (GDI32.@)
3103 INT WINAPI AddFontResourceW( LPCWSTR str )
3105 return AddFontResourceExW(str, 0, NULL);
3109 /***********************************************************************
3110 * AddFontResourceExA (GDI32.@)
3112 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3114 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3115 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3116 INT ret;
3118 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3119 ret = AddFontResourceExW(strW, fl, pdv);
3120 HeapFree(GetProcessHeap(), 0, strW);
3121 return ret;
3124 static BOOL CALLBACK load_enumed_resource(HMODULE hModule, LPCWSTR type, LPWSTR name, LONG_PTR lParam)
3126 HRSRC rsrc = FindResourceW(hModule, name, type);
3127 HGLOBAL hMem = LoadResource(hModule, rsrc);
3128 LPVOID *pMem = LockResource(hMem);
3129 int *num_total = (int *)lParam;
3130 DWORD num_in_res;
3132 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type));
3133 if (!AddFontMemResourceEx(pMem, SizeofResource(hModule, rsrc), NULL, &num_in_res))
3135 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule, hMem);
3136 return FALSE;
3139 *num_total += num_in_res;
3140 return TRUE;
3143 /***********************************************************************
3144 * AddFontResourceExW (GDI32.@)
3146 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3148 int ret = WineEngAddFontResourceEx(str, fl, pdv);
3149 if (ret == 0)
3151 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3152 HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
3153 if (hModule != NULL)
3155 int num_resources = 0;
3156 LPWSTR rt_font = (LPWSTR)((ULONG_PTR)8); /* we don't want to include winuser.h */
3158 TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3159 wine_dbgstr_w(str));
3160 if (EnumResourceNamesW(hModule, rt_font, load_enumed_resource, (LONG_PTR)&num_resources))
3161 ret = num_resources;
3162 FreeLibrary(hModule);
3165 return ret;
3168 /***********************************************************************
3169 * RemoveFontResourceA (GDI32.@)
3171 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3173 return RemoveFontResourceExA(str, 0, 0);
3176 /***********************************************************************
3177 * RemoveFontResourceW (GDI32.@)
3179 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3181 return RemoveFontResourceExW(str, 0, 0);
3184 /***********************************************************************
3185 * AddFontMemResourceEx (GDI32.@)
3187 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3189 HANDLE ret;
3190 DWORD num_fonts;
3192 if (!pbFont || !cbFont || !pcFonts)
3194 SetLastError(ERROR_INVALID_PARAMETER);
3195 return NULL;
3198 ret = WineEngAddFontMemResourceEx(pbFont, cbFont, pdv, &num_fonts);
3199 if (ret)
3201 __TRY
3203 *pcFonts = num_fonts;
3205 __EXCEPT_PAGE_FAULT
3207 WARN("page fault while writing to *pcFonts (%p)\n", pcFonts);
3208 RemoveFontMemResourceEx(ret);
3209 ret = 0;
3211 __ENDTRY
3213 return ret;
3216 /***********************************************************************
3217 * RemoveFontMemResourceEx (GDI32.@)
3219 BOOL WINAPI RemoveFontMemResourceEx( HANDLE fh )
3221 FIXME("(%p) stub\n", fh);
3222 return TRUE;
3225 /***********************************************************************
3226 * RemoveFontResourceExA (GDI32.@)
3228 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3230 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3231 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3232 INT ret;
3234 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3235 ret = RemoveFontResourceExW(strW, fl, pdv);
3236 HeapFree(GetProcessHeap(), 0, strW);
3237 return ret;
3240 /***********************************************************************
3241 * RemoveFontResourceExW (GDI32.@)
3243 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3245 return WineEngRemoveFontResourceEx(str, fl, pdv);
3248 /***********************************************************************
3249 * GetTextCharset (GDI32.@)
3251 UINT WINAPI GetTextCharset(HDC hdc)
3253 /* MSDN docs say this is equivalent */
3254 return GetTextCharsetInfo(hdc, NULL, 0);
3257 /***********************************************************************
3258 * GetTextCharsetInfo (GDI32.@)
3260 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3262 UINT ret = DEFAULT_CHARSET;
3263 DC *dc = get_dc_ptr(hdc);
3265 if (dc)
3267 if (dc->gdiFont)
3268 ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
3270 release_dc_ptr( dc );
3273 if (ret == DEFAULT_CHARSET && fs)
3274 memset(fs, 0, sizeof(FONTSIGNATURE));
3275 return ret;
3278 /***********************************************************************
3279 * GdiGetCharDimensions (GDI32.@)
3281 * Gets the average width of the characters in the English alphabet.
3283 * PARAMS
3284 * hdc [I] Handle to the device context to measure on.
3285 * lptm [O] Pointer to memory to store the text metrics into.
3286 * height [O] On exit, the maximum height of characters in the English alphabet.
3288 * RETURNS
3289 * The average width of characters in the English alphabet.
3291 * NOTES
3292 * This function is used by the dialog manager to get the size of a dialog
3293 * unit. It should also be used by other pieces of code that need to know
3294 * the size of a dialog unit in logical units without having access to the
3295 * window handle of the dialog.
3296 * Windows caches the font metrics from this function, but we don't and
3297 * there doesn't appear to be an immediate advantage to do so.
3299 * SEE ALSO
3300 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3302 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3304 SIZE sz;
3305 static const WCHAR alphabet[] = {
3306 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3307 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3308 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3310 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3312 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3314 if (height) *height = sz.cy;
3315 return (sz.cx / 26 + 1) / 2;
3318 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3320 FIXME("(%d): stub\n", fEnableEUDC);
3321 return FALSE;
3324 /***********************************************************************
3325 * GetCharWidthI (GDI32.@)
3327 * Retrieve widths of characters.
3329 * PARAMS
3330 * hdc [I] Handle to a device context.
3331 * first [I] First glyph in range to query.
3332 * count [I] Number of glyph indices to query.
3333 * glyphs [I] Array of glyphs to query.
3334 * buffer [O] Buffer to receive character widths.
3336 * NOTES
3337 * Only works with TrueType fonts.
3339 * RETURNS
3340 * Success: TRUE
3341 * Failure: FALSE
3343 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3345 ABC *abc;
3346 unsigned int i;
3348 TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3350 if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3351 return FALSE;
3353 if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3355 HeapFree(GetProcessHeap(), 0, abc);
3356 return FALSE;
3359 for (i = 0; i < count; i++)
3360 buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3362 HeapFree(GetProcessHeap(), 0, abc);
3363 return TRUE;
3366 /***********************************************************************
3367 * GetFontUnicodeRanges (GDI32.@)
3369 * Retrieve a list of supported Unicode characters in a font.
3371 * PARAMS
3372 * hdc [I] Handle to a device context.
3373 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3375 * RETURNS
3376 * Success: Number of bytes written to the buffer pointed to by lpgs.
3377 * Failure: 0
3380 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3382 DWORD ret;
3383 PHYSDEV dev;
3384 DC *dc = get_dc_ptr(hdc);
3386 TRACE("(%p, %p)\n", hdc, lpgs);
3388 if (!dc) return 0;
3390 dev = GET_DC_PHYSDEV( dc, pGetFontUnicodeRanges );
3391 ret = dev->funcs->pGetFontUnicodeRanges( dev, lpgs );
3392 release_dc_ptr(dc);
3393 return ret;
3397 /*************************************************************
3398 * FontIsLinked (GDI32.@)
3400 BOOL WINAPI FontIsLinked(HDC hdc)
3402 DC *dc = get_dc_ptr(hdc);
3403 BOOL ret = FALSE;
3405 if (!dc) return FALSE;
3406 if (dc->gdiFont) ret = WineEngFontIsLinked(dc->gdiFont);
3407 release_dc_ptr(dc);
3408 TRACE("returning %d\n", ret);
3409 return ret;
3412 /*************************************************************
3413 * GdiRealizationInfo (GDI32.@)
3415 * Returns a structure that contains some font information.
3417 BOOL WINAPI GdiRealizationInfo(HDC hdc, realization_info_t *info)
3419 DC *dc = get_dc_ptr(hdc);
3420 BOOL ret = FALSE;
3422 if (!dc) return FALSE;
3423 if (dc->gdiFont) ret = WineEngRealizationInfo(dc->gdiFont, info);
3424 release_dc_ptr(dc);
3426 return ret;