d3dx9: Allow setting texture to NULL.
[wine.git] / dlls / gdi32 / font.c
blob97cc2b623373d62a4a82d89eb9fad20e2512abc0
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 = GetTextCharsetInfo( dc->hSelf, NULL, 0 );
477 /* Hmm, nicely designed api this one! */
478 if (TranslateCharsetInfo( ULongToPtr(charset), &csi, TCI_SRCCHARSET) )
479 dc->font_code_page = csi.ciACP;
480 else {
481 switch(charset) {
482 case OEM_CHARSET:
483 dc->font_code_page = GetOEMCP();
484 break;
485 case DEFAULT_CHARSET:
486 dc->font_code_page = GetACP();
487 break;
489 case VISCII_CHARSET:
490 case TCVN_CHARSET:
491 case KOI8_CHARSET:
492 case ISO3_CHARSET:
493 case ISO4_CHARSET:
494 case ISO10_CHARSET:
495 case CELTIC_CHARSET:
496 /* FIXME: These have no place here, but because x11drv
497 enumerates fonts with these (made up) charsets some apps
498 might use them and then the FIXME below would become
499 annoying. Now we could pick the intended codepage for
500 each of these, but since it's broken anyway we'll just
501 use CP_ACP and hope it'll go away...
503 dc->font_code_page = CP_ACP;
504 break;
506 default:
507 FIXME("Can't find codepage for charset %d\n", charset);
508 dc->font_code_page = CP_ACP;
509 break;
513 TRACE("charset %d => cp %d\n", charset, dc->font_code_page);
516 /***********************************************************************
517 * FONT_SelectObject
519 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc )
521 HGDIOBJ ret = 0;
522 DC *dc = get_dc_ptr( hdc );
523 PHYSDEV physdev;
525 if (!dc) return 0;
527 if (!GDI_inc_ref_count( handle ))
529 release_dc_ptr( dc );
530 return 0;
533 physdev = GET_DC_PHYSDEV( dc, pSelectFont );
534 if (physdev->funcs->pSelectFont( physdev, handle ))
536 ret = dc->hFont;
537 dc->hFont = handle;
538 update_font_code_page( dc );
539 GDI_dec_ref_count( ret );
541 else GDI_dec_ref_count( handle );
543 release_dc_ptr( dc );
544 return ret;
548 /***********************************************************************
549 * FONT_GetObjectA
551 static INT FONT_GetObjectA( HGDIOBJ handle, INT count, LPVOID buffer )
553 FONTOBJ *font = GDI_GetObjPtr( handle, OBJ_FONT );
554 LOGFONTA lfA;
556 if (!font) return 0;
557 if (buffer)
559 FONT_LogFontWToA( &font->logfont, &lfA );
560 if (count > sizeof(lfA)) count = sizeof(lfA);
561 memcpy( buffer, &lfA, count );
563 else count = sizeof(lfA);
564 GDI_ReleaseObj( handle );
565 return count;
568 /***********************************************************************
569 * FONT_GetObjectW
571 static INT FONT_GetObjectW( HGDIOBJ handle, INT count, LPVOID buffer )
573 FONTOBJ *font = GDI_GetObjPtr( handle, OBJ_FONT );
575 if (!font) return 0;
576 if (buffer)
578 if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
579 memcpy( buffer, &font->logfont, count );
581 else count = sizeof(LOGFONTW);
582 GDI_ReleaseObj( handle );
583 return count;
587 /***********************************************************************
588 * FONT_DeleteObject
590 static BOOL FONT_DeleteObject( HGDIOBJ handle )
592 FONTOBJ *obj;
594 WineEngDestroyFontInstance( handle );
596 if (!(obj = free_gdi_handle( handle ))) return FALSE;
597 return HeapFree( GetProcessHeap(), 0, obj );
601 /***********************************************************************
602 * FONT_EnumInstance
604 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
605 * We have to use other types because of the FONTENUMPROCW definition.
607 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
608 DWORD fType, LPARAM lp )
610 struct font_enum *pfe = (struct font_enum *)lp;
611 INT ret = 1;
613 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
614 if ((!pfe->lpLogFontParam ||
615 pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
616 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
617 (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
619 /* convert font metrics */
620 ENUMLOGFONTEXA logfont;
621 NEWTEXTMETRICEXA tmA;
623 if (!pfe->unicode)
625 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
626 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
627 plf = (LOGFONTW *)&logfont.elfLogFont;
628 ptm = (TEXTMETRICW *)&tmA;
630 ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
632 return ret;
635 /***********************************************************************
636 * FONT_EnumFontFamiliesEx
638 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf, FONTENUMPROCW efproc,
639 LPARAM lParam, BOOL unicode )
641 INT ret = 0;
642 DC *dc = get_dc_ptr( hDC );
643 struct font_enum fe;
645 if (dc)
647 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pEnumFonts );
649 if (plf) TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName), plf->lfCharSet);
650 fe.lpLogFontParam = plf;
651 fe.lpEnumFunc = efproc;
652 fe.lpData = lParam;
653 fe.unicode = unicode;
654 fe.hdc = hDC;
655 ret = physdev->funcs->pEnumFonts( physdev, plf, FONT_EnumInstance, (LPARAM)&fe );
656 release_dc_ptr( dc );
658 return ret;
661 /***********************************************************************
662 * EnumFontFamiliesExW (GDI32.@)
664 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
665 FONTENUMPROCW efproc,
666 LPARAM lParam, DWORD dwFlags )
668 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, TRUE );
671 /***********************************************************************
672 * EnumFontFamiliesExA (GDI32.@)
674 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
675 FONTENUMPROCA efproc,
676 LPARAM lParam, DWORD dwFlags)
678 LOGFONTW lfW, *plfW;
680 if (plf)
682 FONT_LogFontAToW( plf, &lfW );
683 plfW = &lfW;
685 else plfW = NULL;
687 return FONT_EnumFontFamiliesEx( hDC, plfW, (FONTENUMPROCW)efproc, lParam, FALSE );
690 /***********************************************************************
691 * EnumFontFamiliesA (GDI32.@)
693 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
694 FONTENUMPROCA efproc, LPARAM lpData )
696 LOGFONTA lf, *plf;
698 if (lpFamily)
700 if (!*lpFamily) return 1;
701 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
702 lf.lfCharSet = DEFAULT_CHARSET;
703 lf.lfPitchAndFamily = 0;
704 plf = &lf;
706 else plf = NULL;
708 return EnumFontFamiliesExA( hDC, plf, efproc, lpData, 0 );
711 /***********************************************************************
712 * EnumFontFamiliesW (GDI32.@)
714 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
715 FONTENUMPROCW efproc, LPARAM lpData )
717 LOGFONTW lf, *plf;
719 if (lpFamily)
721 if (!*lpFamily) return 1;
722 lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
723 lf.lfCharSet = DEFAULT_CHARSET;
724 lf.lfPitchAndFamily = 0;
725 plf = &lf;
727 else plf = NULL;
729 return EnumFontFamiliesExW( hDC, plf, efproc, lpData, 0 );
732 /***********************************************************************
733 * EnumFontsA (GDI32.@)
735 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
736 LPARAM lpData )
738 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
741 /***********************************************************************
742 * EnumFontsW (GDI32.@)
744 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
745 LPARAM lpData )
747 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
751 /***********************************************************************
752 * GetTextCharacterExtra (GDI32.@)
754 INT WINAPI GetTextCharacterExtra( HDC hdc )
756 INT ret;
757 DC *dc = get_dc_ptr( hdc );
758 if (!dc) return 0x80000000;
759 ret = dc->charExtra;
760 release_dc_ptr( dc );
761 return ret;
765 /***********************************************************************
766 * SetTextCharacterExtra (GDI32.@)
768 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
770 INT ret = 0x80000000;
771 DC * dc = get_dc_ptr( hdc );
773 if (dc)
775 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetTextCharacterExtra );
776 extra = physdev->funcs->pSetTextCharacterExtra( physdev, extra );
777 if (extra != 0x80000000)
779 ret = dc->charExtra;
780 dc->charExtra = extra;
782 release_dc_ptr( dc );
784 return ret;
788 /***********************************************************************
789 * SetTextJustification (GDI32.@)
791 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
793 BOOL ret;
794 PHYSDEV physdev;
795 DC * dc = get_dc_ptr( hdc );
797 if (!dc) return FALSE;
799 physdev = GET_DC_PHYSDEV( dc, pSetTextJustification );
800 ret = physdev->funcs->pSetTextJustification( physdev, extra, breaks );
801 if (ret)
803 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
804 if (!extra) breaks = 0;
805 if (breaks)
807 dc->breakExtra = extra / breaks;
808 dc->breakRem = extra - (breaks * dc->breakExtra);
810 else
812 dc->breakExtra = 0;
813 dc->breakRem = 0;
816 release_dc_ptr( dc );
817 return ret;
821 /***********************************************************************
822 * GetTextFaceA (GDI32.@)
824 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
826 INT res = GetTextFaceW(hdc, 0, NULL);
827 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
828 GetTextFaceW( hdc, res, nameW );
830 if (name)
832 if (count)
834 res = WideCharToMultiByte(CP_ACP, 0, nameW, -1, name, count, NULL, NULL);
835 if (res == 0)
836 res = count;
837 name[count-1] = 0;
838 /* GetTextFaceA does NOT include the nul byte in the return count. */
839 res--;
841 else
842 res = 0;
844 else
845 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
846 HeapFree( GetProcessHeap(), 0, nameW );
847 return res;
850 /***********************************************************************
851 * GetTextFaceW (GDI32.@)
853 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
855 PHYSDEV dev;
856 INT ret;
858 DC * dc = get_dc_ptr( hdc );
859 if (!dc) return 0;
861 dev = GET_DC_PHYSDEV( dc, pGetTextFace );
862 ret = dev->funcs->pGetTextFace( dev, count, name );
863 release_dc_ptr( dc );
864 return ret;
868 /***********************************************************************
869 * GetTextExtentPoint32A (GDI32.@)
871 * See GetTextExtentPoint32W.
873 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
874 LPSIZE size )
876 BOOL ret = FALSE;
877 INT wlen;
878 LPWSTR p;
880 if (count < 0) return FALSE;
882 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
884 if (p)
886 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
887 HeapFree( GetProcessHeap(), 0, p );
890 TRACE("(%p %s %d %p): returning %d x %d\n",
891 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
892 return ret;
896 /***********************************************************************
897 * GetTextExtentPoint32W [GDI32.@]
899 * Computes width/height for a string.
901 * Computes width and height of the specified string.
903 * RETURNS
904 * Success: TRUE
905 * Failure: FALSE
907 BOOL WINAPI GetTextExtentPoint32W(
908 HDC hdc, /* [in] Handle of device context */
909 LPCWSTR str, /* [in] Address of text string */
910 INT count, /* [in] Number of characters in string */
911 LPSIZE size) /* [out] Address of structure for string size */
913 return GetTextExtentExPointW(hdc, str, count, 0, NULL, NULL, size);
916 /***********************************************************************
917 * GetTextExtentExPointI [GDI32.@]
919 * Computes width and height of the array of glyph indices.
921 * PARAMS
922 * hdc [I] Handle of device context.
923 * indices [I] Glyph index array.
924 * count [I] Number of glyphs in array.
925 * max_ext [I] Maximum width in glyphs.
926 * nfit [O] Maximum number of characters.
927 * dxs [O] Partial string widths.
928 * size [O] Returned string size.
930 * RETURNS
931 * Success: TRUE
932 * Failure: FALSE
934 BOOL WINAPI GetTextExtentExPointI( HDC hdc, const WORD *indices, INT count, INT max_ext,
935 LPINT nfit, LPINT dxs, LPSIZE size )
937 PHYSDEV dev;
938 BOOL ret;
939 DC *dc;
941 if (count < 0) return FALSE;
943 dc = get_dc_ptr( hdc );
944 if (!dc) return FALSE;
946 dev = GET_DC_PHYSDEV( dc, pGetTextExtentExPointI );
947 ret = dev->funcs->pGetTextExtentExPointI( dev, indices, count, max_ext, nfit, dxs, size );
948 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
949 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
950 size->cx += count * dc->charExtra;
951 release_dc_ptr( dc );
953 TRACE("(%p %p %d %p): returning %d x %d\n",
954 hdc, indices, count, size, size->cx, size->cy );
955 return ret;
958 /***********************************************************************
959 * GetTextExtentPointI [GDI32.@]
961 * Computes width and height of the array of glyph indices.
963 * PARAMS
964 * hdc [I] Handle of device context.
965 * indices [I] Glyph index array.
966 * count [I] Number of glyphs in array.
967 * size [O] Returned string size.
969 * RETURNS
970 * Success: TRUE
971 * Failure: FALSE
973 BOOL WINAPI GetTextExtentPointI( HDC hdc, const WORD *indices, INT count, LPSIZE size )
975 return GetTextExtentExPointI( hdc, indices, count, 0, NULL, NULL, size );
979 /***********************************************************************
980 * GetTextExtentPointA (GDI32.@)
982 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
983 LPSIZE size )
985 TRACE("not bug compatible.\n");
986 return GetTextExtentPoint32A( hdc, str, count, size );
989 /***********************************************************************
990 * GetTextExtentPointW (GDI32.@)
992 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
993 LPSIZE size )
995 TRACE("not bug compatible.\n");
996 return GetTextExtentPoint32W( hdc, str, count, size );
1000 /***********************************************************************
1001 * GetTextExtentExPointA (GDI32.@)
1003 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1004 INT maxExt, LPINT lpnFit,
1005 LPINT alpDx, LPSIZE size )
1007 BOOL ret;
1008 INT wlen;
1009 INT *walpDx = NULL;
1010 LPWSTR p = NULL;
1012 if (count < 0) return FALSE;
1014 if (alpDx)
1016 walpDx = HeapAlloc( GetProcessHeap(), 0, count * sizeof(INT) );
1017 if (!walpDx) return FALSE;
1020 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1021 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
1022 if (walpDx)
1024 INT n = lpnFit ? *lpnFit : wlen;
1025 INT i, j;
1026 for(i = 0, j = 0; i < n; i++, j++)
1028 alpDx[j] = walpDx[i];
1029 if (IsDBCSLeadByte(str[j])) alpDx[++j] = walpDx[i];
1032 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1033 HeapFree( GetProcessHeap(), 0, p );
1034 HeapFree( GetProcessHeap(), 0, walpDx );
1035 return ret;
1039 /***********************************************************************
1040 * GetTextExtentExPointW (GDI32.@)
1042 * Return the size of the string as it would be if it was output properly by
1043 * e.g. TextOut.
1045 * This should include
1046 * - Intercharacter spacing
1047 * - justification spacing (not yet done)
1048 * - kerning? see below
1050 * Kerning. Since kerning would be carried out by the rendering code it should
1051 * be done by the driver. However they don't support it yet. Also I am not
1052 * yet persuaded that (certainly under Win95) any kerning is actually done.
1054 * str: According to MSDN this should be null-terminated. That is not true; a
1055 * null will not terminate it early.
1056 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1057 * than count. I have seen it be either the size of the full string or
1058 * 1 less than the size of the full string. I have not seen it bear any
1059 * resemblance to the portion that would fit.
1060 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1061 * trailing intercharacter spacing and any trailing justification.
1063 * FIXME
1064 * Currently we do this by measuring each character etc. We should do it by
1065 * passing the request to the driver, perhaps by extending the
1066 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1067 * thinking about kerning issues and rounding issues in the justification.
1070 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1071 INT maxExt, LPINT lpnFit,
1072 LPINT alpDx, LPSIZE size )
1074 INT nFit = 0;
1075 LPINT dxs = NULL;
1076 DC *dc;
1077 BOOL ret = FALSE;
1078 TEXTMETRICW tm;
1079 PHYSDEV dev;
1081 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1083 if (count < 0) return FALSE;
1085 dc = get_dc_ptr(hdc);
1086 if (!dc) return FALSE;
1088 GetTextMetricsW(hdc, &tm);
1090 /* If we need to calculate nFit, then we need the partial extents even if
1091 the user hasn't provided us with an array. */
1092 if (lpnFit)
1094 dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]);
1095 if (! dxs)
1097 release_dc_ptr(dc);
1098 SetLastError(ERROR_OUTOFMEMORY);
1099 return FALSE;
1102 else
1103 dxs = alpDx;
1105 dev = GET_DC_PHYSDEV( dc, pGetTextExtentExPoint );
1106 ret = dev->funcs->pGetTextExtentExPoint(dev, str, count, 0, NULL, dxs, size);
1108 /* Perform device size to world size transformations. */
1109 if (ret)
1111 INT extra = dc->charExtra,
1112 breakExtra = dc->breakExtra,
1113 breakRem = dc->breakRem,
1116 if (dxs)
1118 for (i = 0; i < count; ++i)
1120 dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
1121 dxs[i] += (i+1) * extra;
1122 if (count > 1 && (breakExtra || breakRem) && str[i] == tm.tmBreakChar)
1124 dxs[i] += breakExtra;
1125 if (breakRem > 0)
1127 breakRem--;
1128 dxs[i]++;
1131 if (dxs[i] <= maxExt)
1132 ++nFit;
1134 breakRem = dc->breakRem;
1136 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1137 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1139 if (!dxs && count > 1 && (breakExtra || breakRem))
1141 for (i = 0; i < count; i++)
1143 if (str[i] == tm.tmBreakChar)
1145 size->cx += breakExtra;
1146 if (breakRem > 0)
1148 breakRem--;
1149 (size->cx)++;
1156 if (lpnFit)
1157 *lpnFit = nFit;
1159 if (! alpDx)
1160 HeapFree(GetProcessHeap(), 0, dxs);
1162 release_dc_ptr( dc );
1164 TRACE("returning %d %d x %d\n",nFit,size->cx,size->cy);
1165 return ret;
1168 /***********************************************************************
1169 * GetTextMetricsA (GDI32.@)
1171 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1173 TEXTMETRICW tm32;
1175 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1176 FONT_TextMetricWToA( &tm32, metrics );
1177 return TRUE;
1180 /***********************************************************************
1181 * GetTextMetricsW (GDI32.@)
1183 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1185 PHYSDEV physdev;
1186 BOOL ret = FALSE;
1187 DC * dc = get_dc_ptr( hdc );
1188 if (!dc) return FALSE;
1190 physdev = GET_DC_PHYSDEV( dc, pGetTextMetrics );
1191 ret = physdev->funcs->pGetTextMetrics( physdev, metrics );
1193 if (ret)
1195 /* device layer returns values in device units
1196 * therefore we have to convert them to logical */
1198 metrics->tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1199 metrics->tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1201 #define WDPTOLP(x) ((x<0)? \
1202 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1203 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1204 #define HDPTOLP(y) ((y<0)? \
1205 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1206 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1208 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1209 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1210 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1211 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1212 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1213 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1214 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1215 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1216 ret = TRUE;
1217 #undef WDPTOLP
1218 #undef HDPTOLP
1219 TRACE("text metrics:\n"
1220 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1221 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1222 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1223 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1224 " PitchAndFamily = %02x\n"
1225 " --------------------\n"
1226 " InternalLeading = %i\n"
1227 " Ascent = %i\n"
1228 " Descent = %i\n"
1229 " Height = %i\n",
1230 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1231 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1232 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1233 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1234 metrics->tmPitchAndFamily,
1235 metrics->tmInternalLeading,
1236 metrics->tmAscent,
1237 metrics->tmDescent,
1238 metrics->tmHeight );
1240 release_dc_ptr( dc );
1241 return ret;
1245 /***********************************************************************
1246 * GetOutlineTextMetricsA (GDI32.@)
1247 * Gets metrics for TrueType fonts.
1249 * NOTES
1250 * If the supplied buffer isn't big enough Windows partially fills it up to
1251 * its given length and returns that length.
1253 * RETURNS
1254 * Success: Non-zero or size of required buffer
1255 * Failure: 0
1257 UINT WINAPI GetOutlineTextMetricsA(
1258 HDC hdc, /* [in] Handle of device context */
1259 UINT cbData, /* [in] Size of metric data array */
1260 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1262 char buf[512], *ptr;
1263 UINT ret, needed;
1264 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1265 OUTLINETEXTMETRICA *output = lpOTM;
1266 INT left, len;
1268 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1269 return 0;
1270 if(ret > sizeof(buf))
1271 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1272 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1274 needed = sizeof(OUTLINETEXTMETRICA);
1275 if(lpOTMW->otmpFamilyName)
1276 needed += WideCharToMultiByte(CP_ACP, 0,
1277 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1278 NULL, 0, NULL, NULL);
1279 if(lpOTMW->otmpFaceName)
1280 needed += WideCharToMultiByte(CP_ACP, 0,
1281 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1282 NULL, 0, NULL, NULL);
1283 if(lpOTMW->otmpStyleName)
1284 needed += WideCharToMultiByte(CP_ACP, 0,
1285 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1286 NULL, 0, NULL, NULL);
1287 if(lpOTMW->otmpFullName)
1288 needed += WideCharToMultiByte(CP_ACP, 0,
1289 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1290 NULL, 0, NULL, NULL);
1292 if(!lpOTM) {
1293 ret = needed;
1294 goto end;
1297 TRACE("needed = %d\n", needed);
1298 if(needed > cbData)
1299 /* Since the supplied buffer isn't big enough, we'll alloc one
1300 that is and memcpy the first cbData bytes into the lpOTM at
1301 the end. */
1302 output = HeapAlloc(GetProcessHeap(), 0, needed);
1304 ret = output->otmSize = min(needed, cbData);
1305 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1306 output->otmFiller = 0;
1307 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1308 output->otmfsSelection = lpOTMW->otmfsSelection;
1309 output->otmfsType = lpOTMW->otmfsType;
1310 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1311 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1312 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1313 output->otmEMSquare = lpOTMW->otmEMSquare;
1314 output->otmAscent = lpOTMW->otmAscent;
1315 output->otmDescent = lpOTMW->otmDescent;
1316 output->otmLineGap = lpOTMW->otmLineGap;
1317 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1318 output->otmsXHeight = lpOTMW->otmsXHeight;
1319 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1320 output->otmMacAscent = lpOTMW->otmMacAscent;
1321 output->otmMacDescent = lpOTMW->otmMacDescent;
1322 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1323 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1324 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1325 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1326 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1327 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1328 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1329 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1330 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1331 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1334 ptr = (char*)(output + 1);
1335 left = needed - sizeof(*output);
1337 if(lpOTMW->otmpFamilyName) {
1338 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1339 len = WideCharToMultiByte(CP_ACP, 0,
1340 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1341 ptr, left, NULL, NULL);
1342 left -= len;
1343 ptr += len;
1344 } else
1345 output->otmpFamilyName = 0;
1347 if(lpOTMW->otmpFaceName) {
1348 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1349 len = WideCharToMultiByte(CP_ACP, 0,
1350 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1351 ptr, left, NULL, NULL);
1352 left -= len;
1353 ptr += len;
1354 } else
1355 output->otmpFaceName = 0;
1357 if(lpOTMW->otmpStyleName) {
1358 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1359 len = WideCharToMultiByte(CP_ACP, 0,
1360 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1361 ptr, left, NULL, NULL);
1362 left -= len;
1363 ptr += len;
1364 } else
1365 output->otmpStyleName = 0;
1367 if(lpOTMW->otmpFullName) {
1368 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1369 len = WideCharToMultiByte(CP_ACP, 0,
1370 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1371 ptr, left, NULL, NULL);
1372 left -= len;
1373 } else
1374 output->otmpFullName = 0;
1376 assert(left == 0);
1378 if(output != lpOTM) {
1379 memcpy(lpOTM, output, cbData);
1380 HeapFree(GetProcessHeap(), 0, output);
1382 /* check if the string offsets really fit into the provided size */
1383 /* FIXME: should we check string length as well? */
1384 /* make sure that we don't read/write beyond the provided buffer */
1385 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(LPSTR))
1387 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1388 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1391 /* make sure that we don't read/write beyond the provided buffer */
1392 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(LPSTR))
1394 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1395 lpOTM->otmpFaceName = 0; /* doesn't fit */
1398 /* make sure that we don't read/write beyond the provided buffer */
1399 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(LPSTR))
1401 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1402 lpOTM->otmpStyleName = 0; /* doesn't fit */
1405 /* make sure that we don't read/write beyond the provided buffer */
1406 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(LPSTR))
1408 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1409 lpOTM->otmpFullName = 0; /* doesn't fit */
1413 end:
1414 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1415 HeapFree(GetProcessHeap(), 0, lpOTMW);
1417 return ret;
1421 /***********************************************************************
1422 * GetOutlineTextMetricsW [GDI32.@]
1424 UINT WINAPI GetOutlineTextMetricsW(
1425 HDC hdc, /* [in] Handle of device context */
1426 UINT cbData, /* [in] Size of metric data array */
1427 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1429 DC *dc = get_dc_ptr( hdc );
1430 OUTLINETEXTMETRICW *output = lpOTM;
1431 PHYSDEV dev;
1432 UINT ret;
1434 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1435 if(!dc) return 0;
1437 dev = GET_DC_PHYSDEV( dc, pGetOutlineTextMetrics );
1438 ret = dev->funcs->pGetOutlineTextMetrics( dev, cbData, output );
1440 if (lpOTM && ret > cbData)
1442 output = HeapAlloc(GetProcessHeap(), 0, ret);
1443 ret = dev->funcs->pGetOutlineTextMetrics( dev, ret, output );
1446 if (lpOTM && ret)
1448 output->otmTextMetrics.tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1449 output->otmTextMetrics.tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1451 #define WDPTOLP(x) ((x<0)? \
1452 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1453 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1454 #define HDPTOLP(y) ((y<0)? \
1455 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1456 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1458 output->otmTextMetrics.tmHeight = HDPTOLP(output->otmTextMetrics.tmHeight);
1459 output->otmTextMetrics.tmAscent = HDPTOLP(output->otmTextMetrics.tmAscent);
1460 output->otmTextMetrics.tmDescent = HDPTOLP(output->otmTextMetrics.tmDescent);
1461 output->otmTextMetrics.tmInternalLeading = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1462 output->otmTextMetrics.tmExternalLeading = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1463 output->otmTextMetrics.tmAveCharWidth = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1464 output->otmTextMetrics.tmMaxCharWidth = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1465 output->otmTextMetrics.tmOverhang = WDPTOLP(output->otmTextMetrics.tmOverhang);
1466 output->otmAscent = HDPTOLP(output->otmAscent);
1467 output->otmDescent = HDPTOLP(output->otmDescent);
1468 output->otmLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmLineGap));
1469 output->otmsCapEmHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsCapEmHeight));
1470 output->otmsXHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsXHeight));
1471 output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1472 output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1473 output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1474 output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1475 output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1476 output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1477 output->otmMacLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmMacLineGap));
1478 output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1479 output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1480 output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1481 output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1482 output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1483 output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1484 output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1485 output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1486 output->otmsStrikeoutSize = abs(INTERNAL_YDSTOWS(dc,output->otmsStrikeoutSize));
1487 output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1488 output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1489 output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1490 #undef WDPTOLP
1491 #undef HDPTOLP
1492 if(output != lpOTM)
1494 memcpy(lpOTM, output, cbData);
1495 HeapFree(GetProcessHeap(), 0, output);
1496 ret = cbData;
1499 release_dc_ptr(dc);
1500 return ret;
1503 static LPSTR FONT_GetCharsByRangeA(HDC hdc, UINT firstChar, UINT lastChar, PINT pByteLen)
1505 INT i, count = lastChar - firstChar + 1;
1506 UINT c;
1507 LPSTR str;
1509 if (count <= 0)
1510 return NULL;
1512 switch (GdiGetCodePage(hdc))
1514 case 932:
1515 case 936:
1516 case 949:
1517 case 950:
1518 case 1361:
1519 if (lastChar > 0xffff)
1520 return NULL;
1521 if ((firstChar ^ lastChar) > 0xff)
1522 return NULL;
1523 break;
1524 default:
1525 if (lastChar > 0xff)
1526 return NULL;
1527 break;
1530 str = HeapAlloc(GetProcessHeap(), 0, count * 2 + 1);
1531 if (str == NULL)
1532 return NULL;
1534 for(i = 0, c = firstChar; c <= lastChar; i++, c++)
1536 if (c > 0xff)
1537 str[i++] = (BYTE)(c >> 8);
1538 str[i] = (BYTE)c;
1540 str[i] = '\0';
1542 *pByteLen = i;
1544 return str;
1547 /***********************************************************************
1548 * GetCharWidthW (GDI32.@)
1549 * GetCharWidth32W (GDI32.@)
1551 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1552 LPINT buffer )
1554 UINT i;
1555 BOOL ret;
1556 PHYSDEV dev;
1557 DC * dc = get_dc_ptr( hdc );
1559 if (!dc) return FALSE;
1561 dev = GET_DC_PHYSDEV( dc, pGetCharWidth );
1562 ret = dev->funcs->pGetCharWidth( dev, firstChar, lastChar, buffer );
1564 if (ret)
1566 /* convert device units to logical */
1567 for( i = firstChar; i <= lastChar; i++, buffer++ )
1568 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1570 release_dc_ptr( dc );
1571 return ret;
1575 /***********************************************************************
1576 * GetCharWidthA (GDI32.@)
1577 * GetCharWidth32A (GDI32.@)
1579 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1580 LPINT buffer )
1582 INT i, wlen;
1583 LPSTR str;
1584 LPWSTR wstr;
1585 BOOL ret = TRUE;
1587 str = FONT_GetCharsByRangeA(hdc, firstChar, lastChar, &i);
1588 if(str == NULL)
1589 return FALSE;
1591 wstr = FONT_mbtowc(hdc, str, i, &wlen, NULL);
1593 for(i = 0; i < wlen; i++)
1595 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1597 ret = FALSE;
1598 break;
1600 buffer++;
1603 HeapFree(GetProcessHeap(), 0, str);
1604 HeapFree(GetProcessHeap(), 0, wstr);
1606 return ret;
1610 /***********************************************************************
1611 * ExtTextOutA (GDI32.@)
1613 * See ExtTextOutW.
1615 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1616 const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1618 INT wlen;
1619 UINT codepage;
1620 LPWSTR p;
1621 BOOL ret;
1622 LPINT lpDxW = NULL;
1624 if (flags & ETO_GLYPH_INDEX)
1625 return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
1627 p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
1629 if (lpDx) {
1630 unsigned int i = 0, j = 0;
1632 /* allocate enough for a ETO_PDY */
1633 lpDxW = HeapAlloc( GetProcessHeap(), 0, 2*wlen*sizeof(INT));
1634 while(i < count) {
1635 if(IsDBCSLeadByteEx(codepage, str[i]))
1637 if(flags & ETO_PDY)
1639 lpDxW[j++] = lpDx[i * 2] + lpDx[(i + 1) * 2];
1640 lpDxW[j++] = lpDx[i * 2 + 1] + lpDx[(i + 1) * 2 + 1];
1642 else
1643 lpDxW[j++] = lpDx[i] + lpDx[i + 1];
1644 i = i + 2;
1646 else
1648 if(flags & ETO_PDY)
1650 lpDxW[j++] = lpDx[i * 2];
1651 lpDxW[j++] = lpDx[i * 2 + 1];
1653 else
1654 lpDxW[j++] = lpDx[i];
1655 i = i + 1;
1660 ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1662 HeapFree( GetProcessHeap(), 0, p );
1663 HeapFree( GetProcessHeap(), 0, lpDxW );
1664 return ret;
1668 /***********************************************************************
1669 * ExtTextOutW (GDI32.@)
1671 * Draws text using the currently selected font, background color, and text color.
1674 * PARAMS
1675 * x,y [I] coordinates of string
1676 * flags [I]
1677 * ETO_GRAYED - undocumented on MSDN
1678 * ETO_OPAQUE - use background color for fill the rectangle
1679 * ETO_CLIPPED - clipping text to the rectangle
1680 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1681 * than encoded characters. Implies ETO_IGNORELANGUAGE
1682 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1683 * Affects BiDi ordering
1684 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1685 * ETO_PDY - unimplemented
1686 * ETO_NUMERICSLATIN - unimplemented always assumed -
1687 * do not translate numbers into locale representations
1688 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1689 * lprect [I] dimensions for clipping or/and opaquing
1690 * str [I] text string
1691 * count [I] number of symbols in string
1692 * lpDx [I] optional parameter with distance between drawing characters
1694 * RETURNS
1695 * Success: TRUE
1696 * Failure: FALSE
1698 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1699 const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1701 BOOL ret = FALSE;
1702 LPWSTR reordered_str = (LPWSTR)str;
1703 WORD *glyphs = NULL;
1704 UINT align = GetTextAlign( hdc );
1705 DWORD layout = GetLayout( hdc );
1706 POINT pt;
1707 TEXTMETRICW tm;
1708 LOGFONTW lf;
1709 double cosEsc, sinEsc;
1710 INT char_extra;
1711 SIZE sz;
1712 RECT rc;
1713 BOOL done_extents = FALSE;
1714 POINT *deltas = NULL, width = {0, 0};
1715 DWORD type;
1716 DC * dc = get_dc_ptr( hdc );
1717 PHYSDEV physdev;
1718 INT breakRem;
1719 static int quietfixme = 0;
1721 if (!dc) return FALSE;
1723 breakRem = dc->breakRem;
1725 if (quietfixme == 0 && flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN))
1727 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN unimplemented\n");
1728 quietfixme = 1;
1731 update_dc( dc );
1732 physdev = GET_DC_PHYSDEV( dc, pExtTextOut );
1733 type = GetObjectType(hdc);
1734 if(type == OBJ_METADC || type == OBJ_ENHMETADC)
1736 ret = physdev->funcs->pExtTextOut( physdev, x, y, flags, lprect, str, count, lpDx );
1737 release_dc_ptr( dc );
1738 return ret;
1741 if (!lprect)
1742 flags &= ~ETO_CLIPPED;
1744 if (flags & ETO_RTLREADING) align |= TA_RTLREADING;
1745 if (layout & LAYOUT_RTL)
1747 if ((align & TA_CENTER) != TA_CENTER) align ^= TA_RIGHT;
1748 align ^= TA_RTLREADING;
1751 if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && count > 0 )
1753 INT cGlyphs;
1754 reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1756 BIDI_Reorder( hdc, str, count, GCP_REORDER,
1757 (align & TA_RTLREADING) ? WINE_GCPW_FORCE_RTL : WINE_GCPW_FORCE_LTR,
1758 reordered_str, count, NULL, &glyphs, &cGlyphs);
1760 flags |= ETO_IGNORELANGUAGE;
1761 if (glyphs)
1763 flags |= ETO_GLYPH_INDEX;
1764 if (cGlyphs != count)
1765 count = cGlyphs;
1768 else if(flags & ETO_GLYPH_INDEX)
1769 glyphs = reordered_str;
1771 TRACE("%p, %d, %d, %08x, %s, %s, %d, %p)\n", hdc, x, y, flags,
1772 wine_dbgstr_rect(lprect), debugstr_wn(str, count), count, lpDx);
1773 TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
1775 if(align & TA_UPDATECP)
1777 GetCurrentPositionEx( hdc, &pt );
1778 x = pt.x;
1779 y = pt.y;
1782 GetTextMetricsW(hdc, &tm);
1783 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1785 if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
1786 lf.lfEscapement = 0;
1788 if(lf.lfEscapement != 0)
1790 cosEsc = cos(lf.lfEscapement * M_PI / 1800);
1791 sinEsc = sin(lf.lfEscapement * M_PI / 1800);
1793 else
1795 cosEsc = 1;
1796 sinEsc = 0;
1799 if(flags & (ETO_CLIPPED | ETO_OPAQUE))
1801 if(!lprect)
1803 if(flags & ETO_GLYPH_INDEX)
1804 GetTextExtentPointI(hdc, glyphs, count, &sz);
1805 else
1806 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1808 done_extents = TRUE;
1809 rc.left = x;
1810 rc.top = y;
1811 rc.right = x + sz.cx;
1812 rc.bottom = y + sz.cy;
1814 else
1816 rc = *lprect;
1819 LPtoDP(hdc, (POINT*)&rc, 2);
1821 if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
1822 if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
1825 if (flags & ETO_OPAQUE)
1826 physdev->funcs->pExtTextOut( physdev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL );
1828 if(count == 0)
1830 ret = TRUE;
1831 goto done;
1834 pt.x = x;
1835 pt.y = y;
1836 LPtoDP(hdc, &pt, 1);
1837 x = pt.x;
1838 y = pt.y;
1840 char_extra = GetTextCharacterExtra(hdc);
1841 if(char_extra || dc->breakExtra || breakRem || lpDx || lf.lfEscapement != 0)
1843 UINT i;
1844 SIZE tmpsz;
1845 POINT total = {0, 0}, desired[2];
1847 deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
1848 for(i = 0; i < count; i++)
1850 if(lpDx)
1852 if(flags & ETO_PDY)
1854 deltas[i].x = lpDx[i * 2] + char_extra;
1855 deltas[i].y = -lpDx[i * 2 + 1];
1857 else
1859 deltas[i].x = lpDx[i] + char_extra;
1860 deltas[i].y = 0;
1864 else
1866 if(flags & ETO_GLYPH_INDEX)
1867 GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
1868 else
1869 GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
1871 deltas[i].x = tmpsz.cx;
1872 deltas[i].y = 0;
1875 if (!(flags & ETO_GLYPH_INDEX) && (dc->breakExtra || breakRem) && reordered_str[i] == tm.tmBreakChar)
1877 deltas[i].x = deltas[i].x + dc->breakExtra;
1878 if (breakRem > 0)
1880 breakRem--;
1881 deltas[i].x++;
1884 total.x += deltas[i].x;
1885 total.y += deltas[i].y;
1887 desired[0].x = desired[0].y = 0;
1889 desired[1].x = cosEsc * total.x + sinEsc * total.y;
1890 desired[1].y = -sinEsc * total.x + cosEsc * total.y;
1892 LPtoDP(hdc, desired, 2);
1893 desired[1].x -= desired[0].x;
1894 desired[1].y -= desired[0].y;
1895 if (layout & LAYOUT_RTL) desired[1].x = -desired[1].x;
1897 deltas[i].x = desired[1].x - width.x;
1898 deltas[i].y = desired[1].y - width.y;
1900 width = desired[1];
1902 flags |= ETO_PDY;
1904 else
1906 if(!done_extents)
1908 if(flags & ETO_GLYPH_INDEX)
1909 GetTextExtentPointI(hdc, glyphs, count, &sz);
1910 else
1911 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1912 done_extents = TRUE;
1914 width.x = abs(INTERNAL_XWSTODS(dc, sz.cx));
1915 width.y = 0;
1918 tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
1919 tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
1920 switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
1922 case TA_LEFT:
1923 if (align & TA_UPDATECP)
1925 pt.x = x + width.x;
1926 pt.y = y + width.y;
1927 DPtoLP(hdc, &pt, 1);
1928 MoveToEx(hdc, pt.x, pt.y, NULL);
1930 break;
1932 case TA_CENTER:
1933 x -= width.x / 2;
1934 y -= width.y / 2;
1935 break;
1937 case TA_RIGHT:
1938 x -= width.x;
1939 y -= width.y;
1940 if (align & TA_UPDATECP)
1942 pt.x = x;
1943 pt.y = y;
1944 DPtoLP(hdc, &pt, 1);
1945 MoveToEx(hdc, pt.x, pt.y, NULL);
1947 break;
1950 switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
1952 case TA_TOP:
1953 y += tm.tmAscent * cosEsc;
1954 x += tm.tmAscent * sinEsc;
1955 break;
1957 case TA_BOTTOM:
1958 y -= tm.tmDescent * cosEsc;
1959 x -= tm.tmDescent * sinEsc;
1960 break;
1962 case TA_BASELINE:
1963 break;
1966 if (GetBkMode(hdc) != TRANSPARENT)
1968 if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
1970 if(!(flags & ETO_OPAQUE) || x < rc.left || x + width.x >= rc.right ||
1971 y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
1973 RECT rc;
1974 rc.left = x;
1975 rc.right = x + width.x;
1976 rc.top = y - tm.tmAscent;
1977 rc.bottom = y + tm.tmDescent;
1979 if(flags & ETO_CLIPPED)
1981 rc.left = max(lprect->left, rc.left);
1982 rc.right = min(lprect->right, rc.right);
1983 rc.top = max(lprect->top, rc.top);
1984 rc.bottom = min(lprect->bottom, rc.bottom);
1986 if(rc.left < rc.right && rc.top < rc.bottom)
1987 physdev->funcs->pExtTextOut( physdev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL );
1992 if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
1994 HFONT orig_font = dc->hFont, cur_font;
1995 UINT glyph;
1996 INT span = 0;
1997 POINT *offsets = NULL;
1998 unsigned int i;
2000 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2001 for(i = 0; i < count; i++)
2003 WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
2004 if(cur_font != dc->hFont)
2006 if(!offsets)
2008 unsigned int j;
2009 offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
2010 offsets[0].x = offsets[0].y = 0;
2012 if(!deltas)
2014 SIZE tmpsz;
2015 for(j = 1; j < count; j++)
2017 GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
2018 offsets[j].x = offsets[j - 1].x + abs(INTERNAL_XWSTODS(dc, tmpsz.cx));
2019 offsets[j].y = 0;
2022 else
2024 for(j = 1; j < count; j++)
2026 offsets[j].x = offsets[j - 1].x + deltas[j].x;
2027 offsets[j].y = offsets[j - 1].y + deltas[j].y;
2031 if(span)
2033 physdev->funcs->pExtTextOut( physdev, x + offsets[i - span].x,
2034 y + offsets[i - span].y,
2035 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc, glyphs,
2036 span, deltas ? (INT*)(deltas + (i - span)) : NULL);
2037 span = 0;
2039 SelectObject(hdc, cur_font);
2041 glyphs[span++] = glyph;
2043 if(i == count - 1)
2045 ret = physdev->funcs->pExtTextOut(physdev, x + (offsets ? offsets[count - span].x : 0),
2046 y + (offsets ? offsets[count - span].y : 0),
2047 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc, glyphs,
2048 span, deltas ? (INT*)(deltas + (count - span)) : NULL);
2049 SelectObject(hdc, orig_font);
2050 HeapFree(GetProcessHeap(), 0, offsets);
2054 else
2056 if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
2058 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2059 GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
2060 flags |= ETO_GLYPH_INDEX;
2062 ret = physdev->funcs->pExtTextOut( physdev, x, y, (flags & ~ETO_OPAQUE), &rc,
2063 glyphs ? glyphs : reordered_str, count, (INT*)deltas );
2066 done:
2067 HeapFree(GetProcessHeap(), 0, deltas);
2068 if(glyphs != reordered_str)
2069 HeapFree(GetProcessHeap(), 0, glyphs);
2070 if(reordered_str != str)
2071 HeapFree(GetProcessHeap(), 0, reordered_str);
2073 release_dc_ptr( dc );
2075 if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2077 int underlinePos, strikeoutPos;
2078 int underlineWidth, strikeoutWidth;
2079 UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2080 OUTLINETEXTMETRICW* otm = NULL;
2081 POINT pts[5];
2082 HPEN hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2083 HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2085 hbrush = SelectObject(hdc, hbrush);
2087 if(!size)
2089 underlinePos = 0;
2090 underlineWidth = tm.tmAscent / 20 + 1;
2091 strikeoutPos = tm.tmAscent / 2;
2092 strikeoutWidth = underlineWidth;
2094 else
2096 otm = HeapAlloc(GetProcessHeap(), 0, size);
2097 GetOutlineTextMetricsW(hdc, size, otm);
2098 underlinePos = abs( INTERNAL_YWSTODS( dc, otm->otmsUnderscorePosition ));
2099 if (otm->otmsUnderscorePosition < 0) underlinePos = -underlinePos;
2100 underlineWidth = abs( INTERNAL_YWSTODS( dc, otm->otmsUnderscoreSize ));
2101 if (otm->otmsUnderscoreSize < 0) underlineWidth = -underlineWidth;
2102 strikeoutPos = abs( INTERNAL_YWSTODS( dc, otm->otmsStrikeoutPosition ));
2103 if (otm->otmsStrikeoutPosition < 0) strikeoutPos = -strikeoutPos;
2104 strikeoutWidth = abs( INTERNAL_YWSTODS( dc, otm->otmsStrikeoutSize ));
2105 HeapFree(GetProcessHeap(), 0, otm);
2109 if (lf.lfUnderline)
2111 pts[0].x = x - (underlinePos + underlineWidth / 2) * sinEsc;
2112 pts[0].y = y - (underlinePos + underlineWidth / 2) * cosEsc;
2113 pts[1].x = x + width.x - (underlinePos + underlineWidth / 2) * sinEsc;
2114 pts[1].y = y + width.y - (underlinePos + underlineWidth / 2) * cosEsc;
2115 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2116 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2117 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2118 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2119 pts[4].x = pts[0].x;
2120 pts[4].y = pts[0].y;
2121 DPtoLP(hdc, pts, 5);
2122 Polygon(hdc, pts, 5);
2125 if (lf.lfStrikeOut)
2127 pts[0].x = x - (strikeoutPos + strikeoutWidth / 2) * sinEsc;
2128 pts[0].y = y - (strikeoutPos + strikeoutWidth / 2) * cosEsc;
2129 pts[1].x = x + width.x - (strikeoutPos + strikeoutWidth / 2) * sinEsc;
2130 pts[1].y = y + width.y - (strikeoutPos + strikeoutWidth / 2) * cosEsc;
2131 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2132 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2133 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2134 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2135 pts[4].x = pts[0].x;
2136 pts[4].y = pts[0].y;
2137 DPtoLP(hdc, pts, 5);
2138 Polygon(hdc, pts, 5);
2141 SelectObject(hdc, hpen);
2142 hbrush = SelectObject(hdc, hbrush);
2143 DeleteObject(hbrush);
2146 return ret;
2150 /***********************************************************************
2151 * TextOutA (GDI32.@)
2153 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2155 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2159 /***********************************************************************
2160 * TextOutW (GDI32.@)
2162 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2164 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2168 /***********************************************************************
2169 * PolyTextOutA (GDI32.@)
2171 * See PolyTextOutW.
2173 BOOL WINAPI PolyTextOutA( HDC hdc, const POLYTEXTA *pptxt, INT cStrings )
2175 for (; cStrings>0; cStrings--, pptxt++)
2176 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2177 return FALSE;
2178 return TRUE;
2183 /***********************************************************************
2184 * PolyTextOutW (GDI32.@)
2186 * Draw several Strings
2188 * RETURNS
2189 * TRUE: Success.
2190 * FALSE: Failure.
2192 BOOL WINAPI PolyTextOutW( HDC hdc, const POLYTEXTW *pptxt, INT cStrings )
2194 for (; cStrings>0; cStrings--, pptxt++)
2195 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2196 return FALSE;
2197 return TRUE;
2201 /***********************************************************************
2202 * SetMapperFlags (GDI32.@)
2204 DWORD WINAPI SetMapperFlags( HDC hdc, DWORD flags )
2206 DC *dc = get_dc_ptr( hdc );
2207 DWORD ret = GDI_ERROR;
2209 if (dc)
2211 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetMapperFlags );
2212 flags = physdev->funcs->pSetMapperFlags( physdev, flags );
2213 if (flags != GDI_ERROR)
2215 ret = dc->mapperFlags;
2216 dc->mapperFlags = flags;
2218 release_dc_ptr( dc );
2220 return ret;
2223 /***********************************************************************
2224 * GetAspectRatioFilterEx (GDI32.@)
2226 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2228 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2229 return FALSE;
2233 /***********************************************************************
2234 * GetCharABCWidthsA (GDI32.@)
2236 * See GetCharABCWidthsW.
2238 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2239 LPABC abc )
2241 INT i, wlen;
2242 LPSTR str;
2243 LPWSTR wstr;
2244 BOOL ret = TRUE;
2246 str = FONT_GetCharsByRangeA(hdc, firstChar, lastChar, &i);
2247 if (str == NULL)
2248 return FALSE;
2250 wstr = FONT_mbtowc(hdc, str, i, &wlen, NULL);
2251 if (wstr == NULL)
2253 HeapFree(GetProcessHeap(), 0, str);
2254 return FALSE;
2257 for(i = 0; i < wlen; i++)
2259 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2261 ret = FALSE;
2262 break;
2264 abc++;
2267 HeapFree(GetProcessHeap(), 0, str);
2268 HeapFree(GetProcessHeap(), 0, wstr);
2270 return ret;
2274 /******************************************************************************
2275 * GetCharABCWidthsW [GDI32.@]
2277 * Retrieves widths of characters in range.
2279 * PARAMS
2280 * hdc [I] Handle of device context
2281 * firstChar [I] First character in range to query
2282 * lastChar [I] Last character in range to query
2283 * abc [O] Address of character-width structure
2285 * NOTES
2286 * Only works with TrueType fonts
2288 * RETURNS
2289 * Success: TRUE
2290 * Failure: FALSE
2292 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2293 LPABC abc )
2295 DC *dc = get_dc_ptr(hdc);
2296 PHYSDEV dev;
2297 unsigned int i;
2298 BOOL ret;
2300 if (!dc) return FALSE;
2302 if (!abc)
2304 release_dc_ptr( dc );
2305 return FALSE;
2308 dev = GET_DC_PHYSDEV( dc, pGetCharABCWidths );
2309 ret = dev->funcs->pGetCharABCWidths( dev, firstChar, lastChar, abc );
2310 if (ret)
2312 /* convert device units to logical */
2313 for( i = firstChar; i <= lastChar; i++, abc++ ) {
2314 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2315 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2316 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2320 release_dc_ptr( dc );
2321 return ret;
2325 /******************************************************************************
2326 * GetCharABCWidthsI [GDI32.@]
2328 * Retrieves widths of characters in range.
2330 * PARAMS
2331 * hdc [I] Handle of device context
2332 * firstChar [I] First glyphs in range to query
2333 * count [I] Last glyphs in range to query
2334 * pgi [i] Array of glyphs to query
2335 * abc [O] Address of character-width structure
2337 * NOTES
2338 * Only works with TrueType fonts
2340 * RETURNS
2341 * Success: TRUE
2342 * Failure: FALSE
2344 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2345 LPWORD pgi, LPABC abc)
2347 DC *dc = get_dc_ptr(hdc);
2348 PHYSDEV dev;
2349 unsigned int i;
2350 BOOL ret;
2352 if (!dc) return FALSE;
2354 if (!abc)
2356 release_dc_ptr( dc );
2357 return FALSE;
2360 dev = GET_DC_PHYSDEV( dc, pGetCharABCWidthsI );
2361 ret = dev->funcs->pGetCharABCWidthsI( dev, firstChar, count, pgi, abc );
2362 if (ret)
2364 /* convert device units to logical */
2365 for( i = 0; i < count; i++, abc++ ) {
2366 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2367 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2368 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2372 release_dc_ptr( dc );
2373 return ret;
2377 /***********************************************************************
2378 * GetGlyphOutlineA (GDI32.@)
2380 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2381 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2382 LPVOID lpBuffer, const MAT2 *lpmat2 )
2384 if (!lpmat2) return GDI_ERROR;
2386 if(!(fuFormat & GGO_GLYPH_INDEX)) {
2387 UINT cp;
2388 int len;
2389 char mbchs[2];
2391 cp = GdiGetCodePage(hdc);
2392 if (IsDBCSLeadByteEx(cp, uChar >> 8)) {
2393 len = 2;
2394 mbchs[0] = (uChar & 0xff00) >> 8;
2395 mbchs[1] = (uChar & 0xff);
2396 } else {
2397 len = 1;
2398 mbchs[0] = (uChar & 0xff);
2400 uChar = 0;
2401 MultiByteToWideChar(cp, 0, mbchs, len, (LPWSTR)&uChar, 1);
2404 return GetGlyphOutlineW(hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer,
2405 lpmat2);
2408 /***********************************************************************
2409 * GetGlyphOutlineW (GDI32.@)
2411 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2412 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2413 LPVOID lpBuffer, const MAT2 *lpmat2 )
2415 DC *dc;
2416 DWORD ret;
2417 PHYSDEV dev;
2419 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2420 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2422 if (!lpmat2) return GDI_ERROR;
2424 dc = get_dc_ptr(hdc);
2425 if(!dc) return GDI_ERROR;
2427 dev = GET_DC_PHYSDEV( dc, pGetGlyphOutline );
2428 ret = dev->funcs->pGetGlyphOutline( dev, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2429 release_dc_ptr( dc );
2430 return ret;
2434 /***********************************************************************
2435 * CreateScalableFontResourceA (GDI32.@)
2437 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2438 LPCSTR lpszResourceFile,
2439 LPCSTR lpszFontFile,
2440 LPCSTR lpszCurrentPath )
2442 LPWSTR lpszResourceFileW = NULL;
2443 LPWSTR lpszFontFileW = NULL;
2444 LPWSTR lpszCurrentPathW = NULL;
2445 int len;
2446 BOOL ret;
2448 if (lpszResourceFile)
2450 len = MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, NULL, 0);
2451 lpszResourceFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2452 MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, lpszResourceFileW, len);
2455 if (lpszFontFile)
2457 len = MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, NULL, 0);
2458 lpszFontFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2459 MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, lpszFontFileW, len);
2462 if (lpszCurrentPath)
2464 len = MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, NULL, 0);
2465 lpszCurrentPathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2466 MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, lpszCurrentPathW, len);
2469 ret = CreateScalableFontResourceW(fHidden, lpszResourceFileW,
2470 lpszFontFileW, lpszCurrentPathW);
2472 HeapFree(GetProcessHeap(), 0, lpszResourceFileW);
2473 HeapFree(GetProcessHeap(), 0, lpszFontFileW);
2474 HeapFree(GetProcessHeap(), 0, lpszCurrentPathW);
2476 return ret;
2479 /***********************************************************************
2480 * CreateScalableFontResourceW (GDI32.@)
2482 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2483 LPCWSTR lpszResourceFile,
2484 LPCWSTR lpszFontFile,
2485 LPCWSTR lpszCurrentPath )
2487 HANDLE f;
2488 FIXME("(%d,%s,%s,%s): stub\n",
2489 fHidden, debugstr_w(lpszResourceFile), debugstr_w(lpszFontFile),
2490 debugstr_w(lpszCurrentPath) );
2492 /* fHidden=1 - only visible for the calling app, read-only, not
2493 * enumerated with EnumFonts/EnumFontFamilies
2494 * lpszCurrentPath can be NULL
2497 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2498 if ((f = CreateFileW(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2499 CloseHandle(f);
2500 SetLastError(ERROR_FILE_EXISTS);
2501 return FALSE;
2503 return FALSE; /* create failed */
2506 /*************************************************************************
2507 * GetKerningPairsA (GDI32.@)
2509 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2510 LPKERNINGPAIR kern_pairA )
2512 UINT cp;
2513 CPINFO cpi;
2514 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2515 KERNINGPAIR *kern_pairW;
2517 if (!cPairs && kern_pairA)
2519 SetLastError(ERROR_INVALID_PARAMETER);
2520 return 0;
2523 cp = GdiGetCodePage(hDC);
2525 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2526 * to fail on an invalid character for CP_SYMBOL.
2528 cpi.DefaultChar[0] = 0;
2529 if (cp != CP_SYMBOL && !GetCPInfo(cp, &cpi))
2531 FIXME("Can't find codepage %u info\n", cp);
2532 return 0;
2535 total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2536 if (!total_kern_pairs) return 0;
2538 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2539 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2541 for (i = 0; i < total_kern_pairs; i++)
2543 char first, second;
2545 if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2546 continue;
2548 if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2549 continue;
2551 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2552 continue;
2554 if (kern_pairA)
2556 if (kern_pairs_copied >= cPairs) break;
2558 kern_pairA->wFirst = (BYTE)first;
2559 kern_pairA->wSecond = (BYTE)second;
2560 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2561 kern_pairA++;
2563 kern_pairs_copied++;
2566 HeapFree(GetProcessHeap(), 0, kern_pairW);
2568 return kern_pairs_copied;
2571 /*************************************************************************
2572 * GetKerningPairsW (GDI32.@)
2574 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2575 LPKERNINGPAIR lpKerningPairs )
2577 DC *dc;
2578 DWORD ret;
2579 PHYSDEV dev;
2581 TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2583 if (!cPairs && lpKerningPairs)
2585 SetLastError(ERROR_INVALID_PARAMETER);
2586 return 0;
2589 dc = get_dc_ptr(hDC);
2590 if (!dc) return 0;
2592 dev = GET_DC_PHYSDEV( dc, pGetKerningPairs );
2593 ret = dev->funcs->pGetKerningPairs( dev, cPairs, lpKerningPairs );
2594 release_dc_ptr( dc );
2595 return ret;
2598 /*************************************************************************
2599 * TranslateCharsetInfo [GDI32.@]
2601 * Fills a CHARSETINFO structure for a character set, code page, or
2602 * font. This allows making the correspondence between different labels
2603 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2604 * of the same encoding.
2606 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2607 * only one codepage should be set in *lpSrc.
2609 * RETURNS
2610 * TRUE on success, FALSE on failure.
2613 BOOL WINAPI TranslateCharsetInfo(
2614 LPDWORD lpSrc, /* [in]
2615 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2616 if flags == TCI_SRCCHARSET: a character set value
2617 if flags == TCI_SRCCODEPAGE: a code page value
2619 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2620 DWORD flags /* [in] determines interpretation of lpSrc */)
2622 int index = 0;
2623 switch (flags) {
2624 case TCI_SRCFONTSIG:
2625 while (index < MAXTCIINDEX && !(*lpSrc>>index & 0x0001)) index++;
2626 break;
2627 case TCI_SRCCODEPAGE:
2628 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciACP) index++;
2629 break;
2630 case TCI_SRCCHARSET:
2631 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciCharset) index++;
2632 break;
2633 default:
2634 return FALSE;
2636 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2637 *lpCs = FONT_tci[index];
2638 return TRUE;
2641 /*************************************************************************
2642 * GetFontLanguageInfo (GDI32.@)
2644 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2646 FONTSIGNATURE fontsig;
2647 static const DWORD GCP_DBCS_MASK=0x003F0000,
2648 GCP_DIACRITIC_MASK=0x00000000,
2649 FLI_GLYPHS_MASK=0x00000000,
2650 GCP_GLYPHSHAPE_MASK=0x00000040,
2651 GCP_KASHIDA_MASK=0x00000000,
2652 GCP_LIGATE_MASK=0x00000000,
2653 GCP_USEKERNING_MASK=0x00000000,
2654 GCP_REORDER_MASK=0x00000060;
2656 DWORD result=0;
2658 GetTextCharsetInfo( hdc, &fontsig, 0 );
2659 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2661 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2662 result|=GCP_DBCS;
2664 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2665 result|=GCP_DIACRITIC;
2667 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2668 result|=FLI_GLYPHS;
2670 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2671 result|=GCP_GLYPHSHAPE;
2673 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2674 result|=GCP_KASHIDA;
2676 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2677 result|=GCP_LIGATE;
2679 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2680 result|=GCP_USEKERNING;
2682 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2683 if( GetTextAlign( hdc) & TA_RTLREADING )
2684 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2685 result|=GCP_REORDER;
2687 return result;
2691 /*************************************************************************
2692 * GetFontData [GDI32.@]
2694 * Retrieve data for TrueType font.
2696 * RETURNS
2698 * success: Number of bytes returned
2699 * failure: GDI_ERROR
2701 * NOTES
2703 * Calls SetLastError()
2706 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2707 LPVOID buffer, DWORD length)
2709 DC *dc = get_dc_ptr(hdc);
2710 PHYSDEV dev;
2711 DWORD ret;
2713 if(!dc) return GDI_ERROR;
2715 dev = GET_DC_PHYSDEV( dc, pGetFontData );
2716 ret = dev->funcs->pGetFontData( dev, table, offset, buffer, length );
2717 release_dc_ptr( dc );
2718 return ret;
2721 /*************************************************************************
2722 * GetGlyphIndicesA [GDI32.@]
2724 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2725 LPWORD pgi, DWORD flags)
2727 DWORD ret;
2728 WCHAR *lpstrW;
2729 INT countW;
2731 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2732 hdc, debugstr_an(lpstr, count), count, pgi, flags);
2734 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2735 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2736 HeapFree(GetProcessHeap(), 0, lpstrW);
2738 return ret;
2741 /*************************************************************************
2742 * GetGlyphIndicesW [GDI32.@]
2744 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2745 LPWORD pgi, DWORD flags)
2747 DC *dc = get_dc_ptr(hdc);
2748 PHYSDEV dev;
2749 DWORD ret;
2751 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2752 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2754 if(!dc) return GDI_ERROR;
2756 dev = GET_DC_PHYSDEV( dc, pGetGlyphIndices );
2757 ret = dev->funcs->pGetGlyphIndices( dev, lpstr, count, pgi, flags );
2758 release_dc_ptr( dc );
2759 return ret;
2762 /*************************************************************************
2763 * GetCharacterPlacementA [GDI32.@]
2765 * See GetCharacterPlacementW.
2767 * NOTES:
2768 * the web browser control of ie4 calls this with dwFlags=0
2770 DWORD WINAPI
2771 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2772 INT nMaxExtent, GCP_RESULTSA *lpResults,
2773 DWORD dwFlags)
2775 WCHAR *lpStringW;
2776 INT uCountW;
2777 GCP_RESULTSW resultsW;
2778 DWORD ret;
2779 UINT font_cp;
2781 TRACE("%s, %d, %d, 0x%08x\n",
2782 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2784 /* both structs are equal in size */
2785 memcpy(&resultsW, lpResults, sizeof(resultsW));
2787 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2788 if(lpResults->lpOutString)
2789 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2791 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2793 lpResults->nGlyphs = resultsW.nGlyphs;
2794 lpResults->nMaxFit = resultsW.nMaxFit;
2796 if(lpResults->lpOutString) {
2797 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2798 lpResults->lpOutString, uCount, NULL, NULL );
2801 HeapFree(GetProcessHeap(), 0, lpStringW);
2802 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2804 return ret;
2807 /*************************************************************************
2808 * GetCharacterPlacementW [GDI32.@]
2810 * Retrieve information about a string. This includes the width, reordering,
2811 * Glyphing and so on.
2813 * RETURNS
2815 * The width and height of the string if successful, 0 if failed.
2817 * BUGS
2819 * All flags except GCP_REORDER are not yet implemented.
2820 * Reordering is not 100% compliant to the Windows BiDi method.
2821 * Caret positioning is not yet implemented for BiDi.
2822 * Classes are not yet implemented.
2825 DWORD WINAPI
2826 GetCharacterPlacementW(
2827 HDC hdc, /* [in] Device context for which the rendering is to be done */
2828 LPCWSTR lpString, /* [in] The string for which information is to be returned */
2829 INT uCount, /* [in] Number of WORDS in string. */
2830 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
2831 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2832 DWORD dwFlags /* [in] Flags specifying how to process the string */
2835 DWORD ret=0;
2836 SIZE size;
2837 UINT i, nSet;
2839 TRACE("%s, %d, %d, 0x%08x\n",
2840 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2842 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2843 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2844 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2845 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2846 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2848 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08x ignored\n", dwFlags);
2849 if(lpResults->lpClass) FIXME("classes not implemented\n");
2850 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2851 FIXME("Caret positions for complex scripts not implemented\n");
2853 nSet = (UINT)uCount;
2854 if(nSet > lpResults->nGlyphs)
2855 nSet = lpResults->nGlyphs;
2857 /* return number of initialized fields */
2858 lpResults->nGlyphs = nSet;
2860 if((dwFlags&GCP_REORDER)==0 )
2862 /* Treat the case where no special handling was requested in a fastpath way */
2863 /* copy will do if the GCP_REORDER flag is not set */
2864 if(lpResults->lpOutString)
2865 memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
2867 if(lpResults->lpOrder)
2869 for(i = 0; i < nSet; i++)
2870 lpResults->lpOrder[i] = i;
2872 } else
2874 BIDI_Reorder(NULL, lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
2875 nSet, lpResults->lpOrder, NULL, NULL );
2878 /* FIXME: Will use the placement chars */
2879 if (lpResults->lpDx)
2881 int c;
2882 for (i = 0; i < nSet; i++)
2884 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
2885 lpResults->lpDx[i]= c;
2889 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
2891 int pos = 0;
2893 lpResults->lpCaretPos[0] = 0;
2894 for (i = 1; i < nSet; i++)
2895 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
2896 lpResults->lpCaretPos[i] = (pos += size.cx);
2899 if(lpResults->lpGlyphs)
2900 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
2902 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
2903 ret = MAKELONG(size.cx, size.cy);
2905 return ret;
2908 /*************************************************************************
2909 * GetCharABCWidthsFloatA [GDI32.@]
2911 * See GetCharABCWidthsFloatW.
2913 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
2915 INT i, wlen;
2916 LPSTR str;
2917 LPWSTR wstr;
2918 BOOL ret = TRUE;
2920 str = FONT_GetCharsByRangeA(hdc, first, last, &i);
2921 if (str == NULL)
2922 return FALSE;
2924 wstr = FONT_mbtowc( hdc, str, i, &wlen, NULL );
2926 for (i = 0; i < wlen; i++)
2928 if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
2930 ret = FALSE;
2931 break;
2933 abcf++;
2936 HeapFree( GetProcessHeap(), 0, str );
2937 HeapFree( GetProcessHeap(), 0, wstr );
2939 return ret;
2942 /*************************************************************************
2943 * GetCharABCWidthsFloatW [GDI32.@]
2945 * Retrieves widths of a range of characters.
2947 * PARAMS
2948 * hdc [I] Handle to device context.
2949 * first [I] First character in range to query.
2950 * last [I] Last character in range to query.
2951 * abcf [O] Array of LPABCFLOAT structures.
2953 * RETURNS
2954 * Success: TRUE
2955 * Failure: FALSE
2957 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
2959 UINT i;
2960 ABC *abc;
2961 PHYSDEV dev;
2962 BOOL ret = FALSE;
2963 DC *dc = get_dc_ptr( hdc );
2965 TRACE("%p, %d, %d, %p\n", hdc, first, last, abcf);
2967 if (!dc) return FALSE;
2969 if (!abcf) goto done;
2970 if (!(abc = HeapAlloc( GetProcessHeap(), 0, (last - first + 1) * sizeof(*abc) ))) goto done;
2972 dev = GET_DC_PHYSDEV( dc, pGetCharABCWidths );
2973 ret = dev->funcs->pGetCharABCWidths( dev, first, last, abc );
2974 if (ret)
2976 /* convert device units to logical */
2977 for (i = first; i <= last; i++, abcf++)
2979 abcf->abcfA = abc->abcA * dc->xformVport2World.eM11;
2980 abcf->abcfB = abc->abcB * dc->xformVport2World.eM11;
2981 abcf->abcfC = abc->abcC * dc->xformVport2World.eM11;
2984 HeapFree( GetProcessHeap(), 0, abc );
2986 done:
2987 release_dc_ptr( dc );
2988 return ret;
2991 /*************************************************************************
2992 * GetCharWidthFloatA [GDI32.@]
2994 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
2995 UINT iLastChar, PFLOAT pxBuffer)
2997 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
2998 return 0;
3001 /*************************************************************************
3002 * GetCharWidthFloatW [GDI32.@]
3004 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
3005 UINT iLastChar, PFLOAT pxBuffer)
3007 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3008 return 0;
3012 /***********************************************************************
3014 * Font Resource API *
3016 ***********************************************************************/
3018 /***********************************************************************
3019 * AddFontResourceA (GDI32.@)
3021 INT WINAPI AddFontResourceA( LPCSTR str )
3023 return AddFontResourceExA( str, 0, NULL);
3026 /***********************************************************************
3027 * AddFontResourceW (GDI32.@)
3029 INT WINAPI AddFontResourceW( LPCWSTR str )
3031 return AddFontResourceExW(str, 0, NULL);
3035 /***********************************************************************
3036 * AddFontResourceExA (GDI32.@)
3038 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3040 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3041 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3042 INT ret;
3044 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3045 ret = AddFontResourceExW(strW, fl, pdv);
3046 HeapFree(GetProcessHeap(), 0, strW);
3047 return ret;
3050 static BOOL CALLBACK load_enumed_resource(HMODULE hModule, LPCWSTR type, LPWSTR name, LONG_PTR lParam)
3052 HRSRC rsrc = FindResourceW(hModule, name, type);
3053 HGLOBAL hMem = LoadResource(hModule, rsrc);
3054 LPVOID *pMem = LockResource(hMem);
3055 int *num_total = (int *)lParam;
3056 DWORD num_in_res;
3058 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type));
3059 if (!AddFontMemResourceEx(pMem, SizeofResource(hModule, rsrc), NULL, &num_in_res))
3061 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule, hMem);
3062 return FALSE;
3065 *num_total += num_in_res;
3066 return TRUE;
3069 /***********************************************************************
3070 * AddFontResourceExW (GDI32.@)
3072 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3074 int ret = WineEngAddFontResourceEx(str, fl, pdv);
3075 if (ret == 0)
3077 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3078 HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
3079 if (hModule != NULL)
3081 int num_resources = 0;
3082 LPWSTR rt_font = (LPWSTR)((ULONG_PTR)8); /* we don't want to include winuser.h */
3084 TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3085 wine_dbgstr_w(str));
3086 if (EnumResourceNamesW(hModule, rt_font, load_enumed_resource, (LONG_PTR)&num_resources))
3087 ret = num_resources;
3088 FreeLibrary(hModule);
3091 return ret;
3094 /***********************************************************************
3095 * RemoveFontResourceA (GDI32.@)
3097 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3099 return RemoveFontResourceExA(str, 0, 0);
3102 /***********************************************************************
3103 * RemoveFontResourceW (GDI32.@)
3105 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3107 return RemoveFontResourceExW(str, 0, 0);
3110 /***********************************************************************
3111 * AddFontMemResourceEx (GDI32.@)
3113 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3115 HANDLE ret;
3116 DWORD num_fonts;
3118 if (!pbFont || !cbFont || !pcFonts)
3120 SetLastError(ERROR_INVALID_PARAMETER);
3121 return NULL;
3124 ret = WineEngAddFontMemResourceEx(pbFont, cbFont, pdv, &num_fonts);
3125 if (ret)
3127 __TRY
3129 *pcFonts = num_fonts;
3131 __EXCEPT_PAGE_FAULT
3133 WARN("page fault while writing to *pcFonts (%p)\n", pcFonts);
3134 RemoveFontMemResourceEx(ret);
3135 ret = 0;
3137 __ENDTRY
3139 return ret;
3142 /***********************************************************************
3143 * RemoveFontMemResourceEx (GDI32.@)
3145 BOOL WINAPI RemoveFontMemResourceEx( HANDLE fh )
3147 FIXME("(%p) stub\n", fh);
3148 return TRUE;
3151 /***********************************************************************
3152 * RemoveFontResourceExA (GDI32.@)
3154 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3156 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3157 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3158 INT ret;
3160 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3161 ret = RemoveFontResourceExW(strW, fl, pdv);
3162 HeapFree(GetProcessHeap(), 0, strW);
3163 return ret;
3166 /***********************************************************************
3167 * RemoveFontResourceExW (GDI32.@)
3169 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3171 return WineEngRemoveFontResourceEx(str, fl, pdv);
3174 /***********************************************************************
3175 * GetTextCharset (GDI32.@)
3177 UINT WINAPI GetTextCharset(HDC hdc)
3179 /* MSDN docs say this is equivalent */
3180 return GetTextCharsetInfo(hdc, NULL, 0);
3183 /***********************************************************************
3184 * GetTextCharsetInfo (GDI32.@)
3186 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3188 UINT ret = DEFAULT_CHARSET;
3189 DC *dc = get_dc_ptr(hdc);
3190 PHYSDEV dev;
3192 if (dc)
3194 dev = GET_DC_PHYSDEV( dc, pGetTextCharsetInfo );
3195 ret = dev->funcs->pGetTextCharsetInfo( dev, fs, flags );
3196 release_dc_ptr( dc );
3199 if (ret == DEFAULT_CHARSET && fs)
3200 memset(fs, 0, sizeof(FONTSIGNATURE));
3201 return ret;
3204 /***********************************************************************
3205 * GdiGetCharDimensions (GDI32.@)
3207 * Gets the average width of the characters in the English alphabet.
3209 * PARAMS
3210 * hdc [I] Handle to the device context to measure on.
3211 * lptm [O] Pointer to memory to store the text metrics into.
3212 * height [O] On exit, the maximum height of characters in the English alphabet.
3214 * RETURNS
3215 * The average width of characters in the English alphabet.
3217 * NOTES
3218 * This function is used by the dialog manager to get the size of a dialog
3219 * unit. It should also be used by other pieces of code that need to know
3220 * the size of a dialog unit in logical units without having access to the
3221 * window handle of the dialog.
3222 * Windows caches the font metrics from this function, but we don't and
3223 * there doesn't appear to be an immediate advantage to do so.
3225 * SEE ALSO
3226 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3228 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3230 SIZE sz;
3231 static const WCHAR alphabet[] = {
3232 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3233 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3234 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3236 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3238 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3240 if (height) *height = sz.cy;
3241 return (sz.cx / 26 + 1) / 2;
3244 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3246 FIXME("(%d): stub\n", fEnableEUDC);
3247 return FALSE;
3250 /***********************************************************************
3251 * GetCharWidthI (GDI32.@)
3253 * Retrieve widths of characters.
3255 * PARAMS
3256 * hdc [I] Handle to a device context.
3257 * first [I] First glyph in range to query.
3258 * count [I] Number of glyph indices to query.
3259 * glyphs [I] Array of glyphs to query.
3260 * buffer [O] Buffer to receive character widths.
3262 * NOTES
3263 * Only works with TrueType fonts.
3265 * RETURNS
3266 * Success: TRUE
3267 * Failure: FALSE
3269 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3271 ABC *abc;
3272 unsigned int i;
3274 TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3276 if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3277 return FALSE;
3279 if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3281 HeapFree(GetProcessHeap(), 0, abc);
3282 return FALSE;
3285 for (i = 0; i < count; i++)
3286 buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3288 HeapFree(GetProcessHeap(), 0, abc);
3289 return TRUE;
3292 /***********************************************************************
3293 * GetFontUnicodeRanges (GDI32.@)
3295 * Retrieve a list of supported Unicode characters in a font.
3297 * PARAMS
3298 * hdc [I] Handle to a device context.
3299 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3301 * RETURNS
3302 * Success: Number of bytes written to the buffer pointed to by lpgs.
3303 * Failure: 0
3306 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3308 DWORD ret;
3309 PHYSDEV dev;
3310 DC *dc = get_dc_ptr(hdc);
3312 TRACE("(%p, %p)\n", hdc, lpgs);
3314 if (!dc) return 0;
3316 dev = GET_DC_PHYSDEV( dc, pGetFontUnicodeRanges );
3317 ret = dev->funcs->pGetFontUnicodeRanges( dev, lpgs );
3318 release_dc_ptr(dc);
3319 return ret;
3323 /*************************************************************
3324 * FontIsLinked (GDI32.@)
3326 BOOL WINAPI FontIsLinked(HDC hdc)
3328 DC *dc = get_dc_ptr(hdc);
3329 PHYSDEV dev;
3330 BOOL ret;
3332 if (!dc) return FALSE;
3333 dev = GET_DC_PHYSDEV( dc, pFontIsLinked );
3334 ret = dev->funcs->pFontIsLinked( dev );
3335 release_dc_ptr(dc);
3336 TRACE("returning %d\n", ret);
3337 return ret;
3340 /*************************************************************
3341 * GdiRealizationInfo (GDI32.@)
3343 * Returns a structure that contains some font information.
3345 BOOL WINAPI GdiRealizationInfo(HDC hdc, realization_info_t *info)
3347 DC *dc = get_dc_ptr(hdc);
3348 PHYSDEV dev;
3349 BOOL ret;
3351 if (!dc) return FALSE;
3352 dev = GET_DC_PHYSDEV( dc, pGdiRealizationInfo );
3353 ret = dev->funcs->pGdiRealizationInfo( dev, info );
3354 release_dc_ptr(dc);
3355 return ret;