wined3d: Make the shader parameter to init_output_registers() const.
[wine/multimedia.git] / dlls / gdi32 / font.c
blob10a7f1dbc38257edc83eb0c2e5dffc76c7933de7
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 = otm->otmsUnderscorePosition;
2099 underlineWidth = otm->otmsUnderscoreSize;
2100 strikeoutPos = otm->otmsStrikeoutPosition;
2101 strikeoutWidth = otm->otmsStrikeoutSize;
2102 HeapFree(GetProcessHeap(), 0, otm);
2106 if (lf.lfUnderline)
2108 pts[0].x = x - underlinePos * sinEsc;
2109 pts[0].y = y - underlinePos * cosEsc;
2110 pts[1].x = x + width.x - underlinePos * sinEsc;
2111 pts[1].y = y + width.y - underlinePos * cosEsc;
2112 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2113 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2114 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2115 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2116 pts[4].x = pts[0].x;
2117 pts[4].y = pts[0].y;
2118 DPtoLP(hdc, pts, 5);
2119 Polygon(hdc, pts, 5);
2122 if (lf.lfStrikeOut)
2124 pts[0].x = x - strikeoutPos * sinEsc;
2125 pts[0].y = y - strikeoutPos * cosEsc;
2126 pts[1].x = x + width.x - strikeoutPos * sinEsc;
2127 pts[1].y = y + width.y - strikeoutPos * cosEsc;
2128 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2129 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2130 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2131 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2132 pts[4].x = pts[0].x;
2133 pts[4].y = pts[0].y;
2134 DPtoLP(hdc, pts, 5);
2135 Polygon(hdc, pts, 5);
2138 SelectObject(hdc, hpen);
2139 hbrush = SelectObject(hdc, hbrush);
2140 DeleteObject(hbrush);
2143 return ret;
2147 /***********************************************************************
2148 * TextOutA (GDI32.@)
2150 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2152 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2156 /***********************************************************************
2157 * TextOutW (GDI32.@)
2159 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2161 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2165 /***********************************************************************
2166 * PolyTextOutA (GDI32.@)
2168 * See PolyTextOutW.
2170 BOOL WINAPI PolyTextOutA( HDC hdc, const POLYTEXTA *pptxt, INT cStrings )
2172 for (; cStrings>0; cStrings--, pptxt++)
2173 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2174 return FALSE;
2175 return TRUE;
2180 /***********************************************************************
2181 * PolyTextOutW (GDI32.@)
2183 * Draw several Strings
2185 * RETURNS
2186 * TRUE: Success.
2187 * FALSE: Failure.
2189 BOOL WINAPI PolyTextOutW( HDC hdc, const POLYTEXTW *pptxt, INT cStrings )
2191 for (; cStrings>0; cStrings--, pptxt++)
2192 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2193 return FALSE;
2194 return TRUE;
2198 /***********************************************************************
2199 * SetMapperFlags (GDI32.@)
2201 DWORD WINAPI SetMapperFlags( HDC hdc, DWORD flags )
2203 DC *dc = get_dc_ptr( hdc );
2204 DWORD ret = GDI_ERROR;
2206 if (dc)
2208 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetMapperFlags );
2209 flags = physdev->funcs->pSetMapperFlags( physdev, flags );
2210 if (flags != GDI_ERROR)
2212 ret = dc->mapperFlags;
2213 dc->mapperFlags = flags;
2215 release_dc_ptr( dc );
2217 return ret;
2220 /***********************************************************************
2221 * GetAspectRatioFilterEx (GDI32.@)
2223 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2225 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2226 return FALSE;
2230 /***********************************************************************
2231 * GetCharABCWidthsA (GDI32.@)
2233 * See GetCharABCWidthsW.
2235 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2236 LPABC abc )
2238 INT i, wlen;
2239 LPSTR str;
2240 LPWSTR wstr;
2241 BOOL ret = TRUE;
2243 str = FONT_GetCharsByRangeA(hdc, firstChar, lastChar, &i);
2244 if (str == NULL)
2245 return FALSE;
2247 wstr = FONT_mbtowc(hdc, str, i, &wlen, NULL);
2248 if (wstr == NULL)
2250 HeapFree(GetProcessHeap(), 0, str);
2251 return FALSE;
2254 for(i = 0; i < wlen; i++)
2256 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2258 ret = FALSE;
2259 break;
2261 abc++;
2264 HeapFree(GetProcessHeap(), 0, str);
2265 HeapFree(GetProcessHeap(), 0, wstr);
2267 return ret;
2271 /******************************************************************************
2272 * GetCharABCWidthsW [GDI32.@]
2274 * Retrieves widths of characters in range.
2276 * PARAMS
2277 * hdc [I] Handle of device context
2278 * firstChar [I] First character in range to query
2279 * lastChar [I] Last character in range to query
2280 * abc [O] Address of character-width structure
2282 * NOTES
2283 * Only works with TrueType fonts
2285 * RETURNS
2286 * Success: TRUE
2287 * Failure: FALSE
2289 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2290 LPABC abc )
2292 DC *dc = get_dc_ptr(hdc);
2293 PHYSDEV dev;
2294 unsigned int i;
2295 BOOL ret;
2297 if (!dc) return FALSE;
2299 if (!abc)
2301 release_dc_ptr( dc );
2302 return FALSE;
2305 dev = GET_DC_PHYSDEV( dc, pGetCharABCWidths );
2306 ret = dev->funcs->pGetCharABCWidths( dev, firstChar, lastChar, abc );
2307 if (ret)
2309 /* convert device units to logical */
2310 for( i = firstChar; i <= lastChar; i++, abc++ ) {
2311 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2312 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2313 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2317 release_dc_ptr( dc );
2318 return ret;
2322 /******************************************************************************
2323 * GetCharABCWidthsI [GDI32.@]
2325 * Retrieves widths of characters in range.
2327 * PARAMS
2328 * hdc [I] Handle of device context
2329 * firstChar [I] First glyphs in range to query
2330 * count [I] Last glyphs in range to query
2331 * pgi [i] Array of glyphs to query
2332 * abc [O] Address of character-width structure
2334 * NOTES
2335 * Only works with TrueType fonts
2337 * RETURNS
2338 * Success: TRUE
2339 * Failure: FALSE
2341 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2342 LPWORD pgi, LPABC abc)
2344 DC *dc = get_dc_ptr(hdc);
2345 PHYSDEV dev;
2346 unsigned int i;
2347 BOOL ret;
2349 if (!dc) return FALSE;
2351 if (!abc)
2353 release_dc_ptr( dc );
2354 return FALSE;
2357 dev = GET_DC_PHYSDEV( dc, pGetCharABCWidthsI );
2358 ret = dev->funcs->pGetCharABCWidthsI( dev, firstChar, count, pgi, abc );
2359 if (ret)
2361 /* convert device units to logical */
2362 for( i = 0; i < count; i++, abc++ ) {
2363 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2364 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2365 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2369 release_dc_ptr( dc );
2370 return ret;
2374 /***********************************************************************
2375 * GetGlyphOutlineA (GDI32.@)
2377 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2378 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2379 LPVOID lpBuffer, const MAT2 *lpmat2 )
2381 if (!lpmat2) return GDI_ERROR;
2383 if(!(fuFormat & GGO_GLYPH_INDEX)) {
2384 UINT cp;
2385 int len;
2386 char mbchs[2];
2388 cp = GdiGetCodePage(hdc);
2389 if (IsDBCSLeadByteEx(cp, uChar >> 8)) {
2390 len = 2;
2391 mbchs[0] = (uChar & 0xff00) >> 8;
2392 mbchs[1] = (uChar & 0xff);
2393 } else {
2394 len = 1;
2395 mbchs[0] = (uChar & 0xff);
2397 uChar = 0;
2398 MultiByteToWideChar(cp, 0, mbchs, len, (LPWSTR)&uChar, 1);
2401 return GetGlyphOutlineW(hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer,
2402 lpmat2);
2405 /***********************************************************************
2406 * GetGlyphOutlineW (GDI32.@)
2408 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2409 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2410 LPVOID lpBuffer, const MAT2 *lpmat2 )
2412 DC *dc;
2413 DWORD ret;
2414 PHYSDEV dev;
2416 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2417 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2419 if (!lpmat2) return GDI_ERROR;
2421 dc = get_dc_ptr(hdc);
2422 if(!dc) return GDI_ERROR;
2424 dev = GET_DC_PHYSDEV( dc, pGetGlyphOutline );
2425 ret = dev->funcs->pGetGlyphOutline( dev, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2426 release_dc_ptr( dc );
2427 return ret;
2431 /***********************************************************************
2432 * CreateScalableFontResourceA (GDI32.@)
2434 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2435 LPCSTR lpszResourceFile,
2436 LPCSTR lpszFontFile,
2437 LPCSTR lpszCurrentPath )
2439 LPWSTR lpszResourceFileW = NULL;
2440 LPWSTR lpszFontFileW = NULL;
2441 LPWSTR lpszCurrentPathW = NULL;
2442 int len;
2443 BOOL ret;
2445 if (lpszResourceFile)
2447 len = MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, NULL, 0);
2448 lpszResourceFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2449 MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, lpszResourceFileW, len);
2452 if (lpszFontFile)
2454 len = MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, NULL, 0);
2455 lpszFontFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2456 MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, lpszFontFileW, len);
2459 if (lpszCurrentPath)
2461 len = MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, NULL, 0);
2462 lpszCurrentPathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2463 MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, lpszCurrentPathW, len);
2466 ret = CreateScalableFontResourceW(fHidden, lpszResourceFileW,
2467 lpszFontFileW, lpszCurrentPathW);
2469 HeapFree(GetProcessHeap(), 0, lpszResourceFileW);
2470 HeapFree(GetProcessHeap(), 0, lpszFontFileW);
2471 HeapFree(GetProcessHeap(), 0, lpszCurrentPathW);
2473 return ret;
2476 /***********************************************************************
2477 * CreateScalableFontResourceW (GDI32.@)
2479 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2480 LPCWSTR lpszResourceFile,
2481 LPCWSTR lpszFontFile,
2482 LPCWSTR lpszCurrentPath )
2484 HANDLE f;
2485 FIXME("(%d,%s,%s,%s): stub\n",
2486 fHidden, debugstr_w(lpszResourceFile), debugstr_w(lpszFontFile),
2487 debugstr_w(lpszCurrentPath) );
2489 /* fHidden=1 - only visible for the calling app, read-only, not
2490 * enumerated with EnumFonts/EnumFontFamilies
2491 * lpszCurrentPath can be NULL
2494 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2495 if ((f = CreateFileW(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2496 CloseHandle(f);
2497 SetLastError(ERROR_FILE_EXISTS);
2498 return FALSE;
2500 return FALSE; /* create failed */
2503 /*************************************************************************
2504 * GetKerningPairsA (GDI32.@)
2506 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2507 LPKERNINGPAIR kern_pairA )
2509 UINT cp;
2510 CPINFO cpi;
2511 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2512 KERNINGPAIR *kern_pairW;
2514 if (!cPairs && kern_pairA)
2516 SetLastError(ERROR_INVALID_PARAMETER);
2517 return 0;
2520 cp = GdiGetCodePage(hDC);
2522 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2523 * to fail on an invalid character for CP_SYMBOL.
2525 cpi.DefaultChar[0] = 0;
2526 if (cp != CP_SYMBOL && !GetCPInfo(cp, &cpi))
2528 FIXME("Can't find codepage %u info\n", cp);
2529 return 0;
2532 total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2533 if (!total_kern_pairs) return 0;
2535 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2536 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2538 for (i = 0; i < total_kern_pairs; i++)
2540 char first, second;
2542 if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2543 continue;
2545 if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2546 continue;
2548 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2549 continue;
2551 if (kern_pairA)
2553 if (kern_pairs_copied >= cPairs) break;
2555 kern_pairA->wFirst = (BYTE)first;
2556 kern_pairA->wSecond = (BYTE)second;
2557 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2558 kern_pairA++;
2560 kern_pairs_copied++;
2563 HeapFree(GetProcessHeap(), 0, kern_pairW);
2565 return kern_pairs_copied;
2568 /*************************************************************************
2569 * GetKerningPairsW (GDI32.@)
2571 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2572 LPKERNINGPAIR lpKerningPairs )
2574 DC *dc;
2575 DWORD ret;
2576 PHYSDEV dev;
2578 TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2580 if (!cPairs && lpKerningPairs)
2582 SetLastError(ERROR_INVALID_PARAMETER);
2583 return 0;
2586 dc = get_dc_ptr(hDC);
2587 if (!dc) return 0;
2589 dev = GET_DC_PHYSDEV( dc, pGetKerningPairs );
2590 ret = dev->funcs->pGetKerningPairs( dev, cPairs, lpKerningPairs );
2591 release_dc_ptr( dc );
2592 return ret;
2595 /*************************************************************************
2596 * TranslateCharsetInfo [GDI32.@]
2598 * Fills a CHARSETINFO structure for a character set, code page, or
2599 * font. This allows making the correspondence between different labels
2600 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2601 * of the same encoding.
2603 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2604 * only one codepage should be set in *lpSrc.
2606 * RETURNS
2607 * TRUE on success, FALSE on failure.
2610 BOOL WINAPI TranslateCharsetInfo(
2611 LPDWORD lpSrc, /* [in]
2612 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2613 if flags == TCI_SRCCHARSET: a character set value
2614 if flags == TCI_SRCCODEPAGE: a code page value
2616 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2617 DWORD flags /* [in] determines interpretation of lpSrc */)
2619 int index = 0;
2620 switch (flags) {
2621 case TCI_SRCFONTSIG:
2622 while (index < MAXTCIINDEX && !(*lpSrc>>index & 0x0001)) index++;
2623 break;
2624 case TCI_SRCCODEPAGE:
2625 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciACP) index++;
2626 break;
2627 case TCI_SRCCHARSET:
2628 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciCharset) index++;
2629 break;
2630 default:
2631 return FALSE;
2633 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2634 *lpCs = FONT_tci[index];
2635 return TRUE;
2638 /*************************************************************************
2639 * GetFontLanguageInfo (GDI32.@)
2641 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2643 FONTSIGNATURE fontsig;
2644 static const DWORD GCP_DBCS_MASK=0x003F0000,
2645 GCP_DIACRITIC_MASK=0x00000000,
2646 FLI_GLYPHS_MASK=0x00000000,
2647 GCP_GLYPHSHAPE_MASK=0x00000040,
2648 GCP_KASHIDA_MASK=0x00000000,
2649 GCP_LIGATE_MASK=0x00000000,
2650 GCP_USEKERNING_MASK=0x00000000,
2651 GCP_REORDER_MASK=0x00000060;
2653 DWORD result=0;
2655 GetTextCharsetInfo( hdc, &fontsig, 0 );
2656 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2658 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2659 result|=GCP_DBCS;
2661 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2662 result|=GCP_DIACRITIC;
2664 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2665 result|=FLI_GLYPHS;
2667 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2668 result|=GCP_GLYPHSHAPE;
2670 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2671 result|=GCP_KASHIDA;
2673 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2674 result|=GCP_LIGATE;
2676 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2677 result|=GCP_USEKERNING;
2679 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2680 if( GetTextAlign( hdc) & TA_RTLREADING )
2681 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2682 result|=GCP_REORDER;
2684 return result;
2688 /*************************************************************************
2689 * GetFontData [GDI32.@]
2691 * Retrieve data for TrueType font.
2693 * RETURNS
2695 * success: Number of bytes returned
2696 * failure: GDI_ERROR
2698 * NOTES
2700 * Calls SetLastError()
2703 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2704 LPVOID buffer, DWORD length)
2706 DC *dc = get_dc_ptr(hdc);
2707 PHYSDEV dev;
2708 DWORD ret;
2710 if(!dc) return GDI_ERROR;
2712 dev = GET_DC_PHYSDEV( dc, pGetFontData );
2713 ret = dev->funcs->pGetFontData( dev, table, offset, buffer, length );
2714 release_dc_ptr( dc );
2715 return ret;
2718 /*************************************************************************
2719 * GetGlyphIndicesA [GDI32.@]
2721 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2722 LPWORD pgi, DWORD flags)
2724 DWORD ret;
2725 WCHAR *lpstrW;
2726 INT countW;
2728 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2729 hdc, debugstr_an(lpstr, count), count, pgi, flags);
2731 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2732 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2733 HeapFree(GetProcessHeap(), 0, lpstrW);
2735 return ret;
2738 /*************************************************************************
2739 * GetGlyphIndicesW [GDI32.@]
2741 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2742 LPWORD pgi, DWORD flags)
2744 DC *dc = get_dc_ptr(hdc);
2745 PHYSDEV dev;
2746 DWORD ret;
2748 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2749 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2751 if(!dc) return GDI_ERROR;
2753 dev = GET_DC_PHYSDEV( dc, pGetGlyphIndices );
2754 ret = dev->funcs->pGetGlyphIndices( dev, lpstr, count, pgi, flags );
2755 release_dc_ptr( dc );
2756 return ret;
2759 /*************************************************************************
2760 * GetCharacterPlacementA [GDI32.@]
2762 * See GetCharacterPlacementW.
2764 * NOTES:
2765 * the web browser control of ie4 calls this with dwFlags=0
2767 DWORD WINAPI
2768 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2769 INT nMaxExtent, GCP_RESULTSA *lpResults,
2770 DWORD dwFlags)
2772 WCHAR *lpStringW;
2773 INT uCountW;
2774 GCP_RESULTSW resultsW;
2775 DWORD ret;
2776 UINT font_cp;
2778 TRACE("%s, %d, %d, 0x%08x\n",
2779 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2781 /* both structs are equal in size */
2782 memcpy(&resultsW, lpResults, sizeof(resultsW));
2784 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2785 if(lpResults->lpOutString)
2786 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2788 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2790 lpResults->nGlyphs = resultsW.nGlyphs;
2791 lpResults->nMaxFit = resultsW.nMaxFit;
2793 if(lpResults->lpOutString) {
2794 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2795 lpResults->lpOutString, uCount, NULL, NULL );
2798 HeapFree(GetProcessHeap(), 0, lpStringW);
2799 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2801 return ret;
2804 /*************************************************************************
2805 * GetCharacterPlacementW [GDI32.@]
2807 * Retrieve information about a string. This includes the width, reordering,
2808 * Glyphing and so on.
2810 * RETURNS
2812 * The width and height of the string if successful, 0 if failed.
2814 * BUGS
2816 * All flags except GCP_REORDER are not yet implemented.
2817 * Reordering is not 100% compliant to the Windows BiDi method.
2818 * Caret positioning is not yet implemented for BiDi.
2819 * Classes are not yet implemented.
2822 DWORD WINAPI
2823 GetCharacterPlacementW(
2824 HDC hdc, /* [in] Device context for which the rendering is to be done */
2825 LPCWSTR lpString, /* [in] The string for which information is to be returned */
2826 INT uCount, /* [in] Number of WORDS in string. */
2827 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
2828 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2829 DWORD dwFlags /* [in] Flags specifying how to process the string */
2832 DWORD ret=0;
2833 SIZE size;
2834 UINT i, nSet;
2836 TRACE("%s, %d, %d, 0x%08x\n",
2837 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2839 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2840 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2841 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2842 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2843 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2845 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08x ignored\n", dwFlags);
2846 if(lpResults->lpClass) FIXME("classes not implemented\n");
2847 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2848 FIXME("Caret positions for complex scripts not implemented\n");
2850 nSet = (UINT)uCount;
2851 if(nSet > lpResults->nGlyphs)
2852 nSet = lpResults->nGlyphs;
2854 /* return number of initialized fields */
2855 lpResults->nGlyphs = nSet;
2857 if((dwFlags&GCP_REORDER)==0 )
2859 /* Treat the case where no special handling was requested in a fastpath way */
2860 /* copy will do if the GCP_REORDER flag is not set */
2861 if(lpResults->lpOutString)
2862 memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
2864 if(lpResults->lpOrder)
2866 for(i = 0; i < nSet; i++)
2867 lpResults->lpOrder[i] = i;
2869 } else
2871 BIDI_Reorder(NULL, lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
2872 nSet, lpResults->lpOrder, NULL, NULL );
2875 /* FIXME: Will use the placement chars */
2876 if (lpResults->lpDx)
2878 int c;
2879 for (i = 0; i < nSet; i++)
2881 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
2882 lpResults->lpDx[i]= c;
2886 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
2888 int pos = 0;
2890 lpResults->lpCaretPos[0] = 0;
2891 for (i = 1; i < nSet; i++)
2892 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
2893 lpResults->lpCaretPos[i] = (pos += size.cx);
2896 if(lpResults->lpGlyphs)
2897 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
2899 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
2900 ret = MAKELONG(size.cx, size.cy);
2902 return ret;
2905 /*************************************************************************
2906 * GetCharABCWidthsFloatA [GDI32.@]
2908 * See GetCharABCWidthsFloatW.
2910 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
2912 INT i, wlen;
2913 LPSTR str;
2914 LPWSTR wstr;
2915 BOOL ret = TRUE;
2917 str = FONT_GetCharsByRangeA(hdc, first, last, &i);
2918 if (str == NULL)
2919 return FALSE;
2921 wstr = FONT_mbtowc( hdc, str, i, &wlen, NULL );
2923 for (i = 0; i < wlen; i++)
2925 if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
2927 ret = FALSE;
2928 break;
2930 abcf++;
2933 HeapFree( GetProcessHeap(), 0, str );
2934 HeapFree( GetProcessHeap(), 0, wstr );
2936 return ret;
2939 /*************************************************************************
2940 * GetCharABCWidthsFloatW [GDI32.@]
2942 * Retrieves widths of a range of characters.
2944 * PARAMS
2945 * hdc [I] Handle to device context.
2946 * first [I] First character in range to query.
2947 * last [I] Last character in range to query.
2948 * abcf [O] Array of LPABCFLOAT structures.
2950 * RETURNS
2951 * Success: TRUE
2952 * Failure: FALSE
2954 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
2956 UINT i;
2957 ABC *abc;
2958 PHYSDEV dev;
2959 BOOL ret = FALSE;
2960 DC *dc = get_dc_ptr( hdc );
2962 TRACE("%p, %d, %d, %p\n", hdc, first, last, abcf);
2964 if (!dc) return FALSE;
2966 if (!abcf) goto done;
2967 if (!(abc = HeapAlloc( GetProcessHeap(), 0, (last - first + 1) * sizeof(*abc) ))) goto done;
2969 dev = GET_DC_PHYSDEV( dc, pGetCharABCWidths );
2970 ret = dev->funcs->pGetCharABCWidths( dev, first, last, abc );
2971 if (ret)
2973 /* convert device units to logical */
2974 for (i = first; i <= last; i++, abcf++)
2976 abcf->abcfA = abc->abcA * dc->xformVport2World.eM11;
2977 abcf->abcfB = abc->abcB * dc->xformVport2World.eM11;
2978 abcf->abcfC = abc->abcC * dc->xformVport2World.eM11;
2981 HeapFree( GetProcessHeap(), 0, abc );
2983 done:
2984 release_dc_ptr( dc );
2985 return ret;
2988 /*************************************************************************
2989 * GetCharWidthFloatA [GDI32.@]
2991 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
2992 UINT iLastChar, PFLOAT pxBuffer)
2994 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
2995 return 0;
2998 /*************************************************************************
2999 * GetCharWidthFloatW [GDI32.@]
3001 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
3002 UINT iLastChar, PFLOAT pxBuffer)
3004 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3005 return 0;
3009 /***********************************************************************
3011 * Font Resource API *
3013 ***********************************************************************/
3015 /***********************************************************************
3016 * AddFontResourceA (GDI32.@)
3018 INT WINAPI AddFontResourceA( LPCSTR str )
3020 return AddFontResourceExA( str, 0, NULL);
3023 /***********************************************************************
3024 * AddFontResourceW (GDI32.@)
3026 INT WINAPI AddFontResourceW( LPCWSTR str )
3028 return AddFontResourceExW(str, 0, NULL);
3032 /***********************************************************************
3033 * AddFontResourceExA (GDI32.@)
3035 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3037 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3038 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3039 INT ret;
3041 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3042 ret = AddFontResourceExW(strW, fl, pdv);
3043 HeapFree(GetProcessHeap(), 0, strW);
3044 return ret;
3047 static BOOL CALLBACK load_enumed_resource(HMODULE hModule, LPCWSTR type, LPWSTR name, LONG_PTR lParam)
3049 HRSRC rsrc = FindResourceW(hModule, name, type);
3050 HGLOBAL hMem = LoadResource(hModule, rsrc);
3051 LPVOID *pMem = LockResource(hMem);
3052 int *num_total = (int *)lParam;
3053 DWORD num_in_res;
3055 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type));
3056 if (!AddFontMemResourceEx(pMem, SizeofResource(hModule, rsrc), NULL, &num_in_res))
3058 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule, hMem);
3059 return FALSE;
3062 *num_total += num_in_res;
3063 return TRUE;
3066 /***********************************************************************
3067 * AddFontResourceExW (GDI32.@)
3069 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3071 int ret = WineEngAddFontResourceEx(str, fl, pdv);
3072 if (ret == 0)
3074 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3075 HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
3076 if (hModule != NULL)
3078 int num_resources = 0;
3079 LPWSTR rt_font = (LPWSTR)((ULONG_PTR)8); /* we don't want to include winuser.h */
3081 TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3082 wine_dbgstr_w(str));
3083 if (EnumResourceNamesW(hModule, rt_font, load_enumed_resource, (LONG_PTR)&num_resources))
3084 ret = num_resources;
3085 FreeLibrary(hModule);
3088 return ret;
3091 /***********************************************************************
3092 * RemoveFontResourceA (GDI32.@)
3094 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3096 return RemoveFontResourceExA(str, 0, 0);
3099 /***********************************************************************
3100 * RemoveFontResourceW (GDI32.@)
3102 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3104 return RemoveFontResourceExW(str, 0, 0);
3107 /***********************************************************************
3108 * AddFontMemResourceEx (GDI32.@)
3110 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3112 HANDLE ret;
3113 DWORD num_fonts;
3115 if (!pbFont || !cbFont || !pcFonts)
3117 SetLastError(ERROR_INVALID_PARAMETER);
3118 return NULL;
3121 ret = WineEngAddFontMemResourceEx(pbFont, cbFont, pdv, &num_fonts);
3122 if (ret)
3124 __TRY
3126 *pcFonts = num_fonts;
3128 __EXCEPT_PAGE_FAULT
3130 WARN("page fault while writing to *pcFonts (%p)\n", pcFonts);
3131 RemoveFontMemResourceEx(ret);
3132 ret = 0;
3134 __ENDTRY
3136 return ret;
3139 /***********************************************************************
3140 * RemoveFontMemResourceEx (GDI32.@)
3142 BOOL WINAPI RemoveFontMemResourceEx( HANDLE fh )
3144 FIXME("(%p) stub\n", fh);
3145 return TRUE;
3148 /***********************************************************************
3149 * RemoveFontResourceExA (GDI32.@)
3151 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3153 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3154 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3155 INT ret;
3157 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3158 ret = RemoveFontResourceExW(strW, fl, pdv);
3159 HeapFree(GetProcessHeap(), 0, strW);
3160 return ret;
3163 /***********************************************************************
3164 * RemoveFontResourceExW (GDI32.@)
3166 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3168 return WineEngRemoveFontResourceEx(str, fl, pdv);
3171 /***********************************************************************
3172 * GetTextCharset (GDI32.@)
3174 UINT WINAPI GetTextCharset(HDC hdc)
3176 /* MSDN docs say this is equivalent */
3177 return GetTextCharsetInfo(hdc, NULL, 0);
3180 /***********************************************************************
3181 * GetTextCharsetInfo (GDI32.@)
3183 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3185 UINT ret = DEFAULT_CHARSET;
3186 DC *dc = get_dc_ptr(hdc);
3187 PHYSDEV dev;
3189 if (dc)
3191 dev = GET_DC_PHYSDEV( dc, pGetTextCharsetInfo );
3192 ret = dev->funcs->pGetTextCharsetInfo( dev, fs, flags );
3193 release_dc_ptr( dc );
3196 if (ret == DEFAULT_CHARSET && fs)
3197 memset(fs, 0, sizeof(FONTSIGNATURE));
3198 return ret;
3201 /***********************************************************************
3202 * GdiGetCharDimensions (GDI32.@)
3204 * Gets the average width of the characters in the English alphabet.
3206 * PARAMS
3207 * hdc [I] Handle to the device context to measure on.
3208 * lptm [O] Pointer to memory to store the text metrics into.
3209 * height [O] On exit, the maximum height of characters in the English alphabet.
3211 * RETURNS
3212 * The average width of characters in the English alphabet.
3214 * NOTES
3215 * This function is used by the dialog manager to get the size of a dialog
3216 * unit. It should also be used by other pieces of code that need to know
3217 * the size of a dialog unit in logical units without having access to the
3218 * window handle of the dialog.
3219 * Windows caches the font metrics from this function, but we don't and
3220 * there doesn't appear to be an immediate advantage to do so.
3222 * SEE ALSO
3223 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3225 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3227 SIZE sz;
3228 static const WCHAR alphabet[] = {
3229 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3230 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3231 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3233 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3235 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3237 if (height) *height = sz.cy;
3238 return (sz.cx / 26 + 1) / 2;
3241 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3243 FIXME("(%d): stub\n", fEnableEUDC);
3244 return FALSE;
3247 /***********************************************************************
3248 * GetCharWidthI (GDI32.@)
3250 * Retrieve widths of characters.
3252 * PARAMS
3253 * hdc [I] Handle to a device context.
3254 * first [I] First glyph in range to query.
3255 * count [I] Number of glyph indices to query.
3256 * glyphs [I] Array of glyphs to query.
3257 * buffer [O] Buffer to receive character widths.
3259 * NOTES
3260 * Only works with TrueType fonts.
3262 * RETURNS
3263 * Success: TRUE
3264 * Failure: FALSE
3266 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3268 ABC *abc;
3269 unsigned int i;
3271 TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3273 if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3274 return FALSE;
3276 if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3278 HeapFree(GetProcessHeap(), 0, abc);
3279 return FALSE;
3282 for (i = 0; i < count; i++)
3283 buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3285 HeapFree(GetProcessHeap(), 0, abc);
3286 return TRUE;
3289 /***********************************************************************
3290 * GetFontUnicodeRanges (GDI32.@)
3292 * Retrieve a list of supported Unicode characters in a font.
3294 * PARAMS
3295 * hdc [I] Handle to a device context.
3296 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3298 * RETURNS
3299 * Success: Number of bytes written to the buffer pointed to by lpgs.
3300 * Failure: 0
3303 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3305 DWORD ret;
3306 PHYSDEV dev;
3307 DC *dc = get_dc_ptr(hdc);
3309 TRACE("(%p, %p)\n", hdc, lpgs);
3311 if (!dc) return 0;
3313 dev = GET_DC_PHYSDEV( dc, pGetFontUnicodeRanges );
3314 ret = dev->funcs->pGetFontUnicodeRanges( dev, lpgs );
3315 release_dc_ptr(dc);
3316 return ret;
3320 /*************************************************************
3321 * FontIsLinked (GDI32.@)
3323 BOOL WINAPI FontIsLinked(HDC hdc)
3325 DC *dc = get_dc_ptr(hdc);
3326 PHYSDEV dev;
3327 BOOL ret;
3329 if (!dc) return FALSE;
3330 dev = GET_DC_PHYSDEV( dc, pFontIsLinked );
3331 ret = dev->funcs->pFontIsLinked( dev );
3332 release_dc_ptr(dc);
3333 TRACE("returning %d\n", ret);
3334 return ret;
3337 /*************************************************************
3338 * GdiRealizationInfo (GDI32.@)
3340 * Returns a structure that contains some font information.
3342 BOOL WINAPI GdiRealizationInfo(HDC hdc, realization_info_t *info)
3344 DC *dc = get_dc_ptr(hdc);
3345 PHYSDEV dev;
3346 BOOL ret;
3348 if (!dc) return FALSE;
3349 dev = GET_DC_PHYSDEV( dc, pGdiRealizationInfo );
3350 ret = dev->funcs->pGdiRealizationInfo( dev, info );
3351 release_dc_ptr(dc);
3352 return ret;