push 378fe7a60681a28e8b22f62dcfe122d585b92570
[wine/hacks.git] / dlls / gdi32 / font.c
blob4e271eaadecb94b9cb718ce8a1934b2ff41f1502
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 "wownt32.h"
35 #include "gdi_private.h"
36 #include "wine/unicode.h"
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(font);
41 /* Device -> World size conversion */
43 /* Performs a device to world transformation on the specified width (which
44 * is in integer format).
46 static inline INT INTERNAL_XDSTOWS(DC *dc, INT width)
48 double floatWidth;
50 /* Perform operation with floating point */
51 floatWidth = (double)width * dc->xformVport2World.eM11;
52 /* Round to integers */
53 return GDI_ROUND(floatWidth);
56 /* Performs a device to world transformation on the specified size (which
57 * is in integer format).
59 static inline INT INTERNAL_YDSTOWS(DC *dc, INT height)
61 double floatHeight;
63 /* Perform operation with floating point */
64 floatHeight = (double)height * dc->xformVport2World.eM22;
65 /* Round to integers */
66 return GDI_ROUND(floatHeight);
69 static inline INT INTERNAL_XWSTODS(DC *dc, INT width)
71 POINT pt[2];
72 pt[0].x = pt[0].y = 0;
73 pt[1].x = width;
74 pt[1].y = 0;
75 LPtoDP(dc->hSelf, pt, 2);
76 return pt[1].x - pt[0].x;
79 static inline INT INTERNAL_YWSTODS(DC *dc, INT height)
81 POINT pt[2];
82 pt[0].x = pt[0].y = 0;
83 pt[1].x = 0;
84 pt[1].y = height;
85 LPtoDP(dc->hSelf, pt, 2);
86 return pt[1].y - pt[0].y;
89 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc );
90 static INT FONT_GetObjectA( HGDIOBJ handle, INT count, LPVOID buffer );
91 static INT FONT_GetObjectW( HGDIOBJ handle, INT count, LPVOID buffer );
92 static BOOL FONT_DeleteObject( HGDIOBJ handle );
94 static const struct gdi_obj_funcs font_funcs =
96 FONT_SelectObject, /* pSelectObject */
97 FONT_GetObjectA, /* pGetObjectA */
98 FONT_GetObjectW, /* pGetObjectW */
99 NULL, /* pUnrealizeObject */
100 FONT_DeleteObject /* pDeleteObject */
103 #define ENUM_UNICODE 0x00000001
104 #define ENUM_CALLED 0x00000002
106 typedef struct
108 GDIOBJHDR header;
109 LOGFONTW logfont;
110 } FONTOBJ;
112 typedef struct
114 LPLOGFONTW lpLogFontParam;
115 FONTENUMPROCW lpEnumFunc;
116 LPARAM lpData;
117 DWORD dwFlags;
118 HDC hdc;
119 } fontEnum32;
122 * For TranslateCharsetInfo
124 #define MAXTCIINDEX 32
125 static const CHARSETINFO FONT_tci[MAXTCIINDEX] = {
126 /* ANSI */
127 { ANSI_CHARSET, 1252, {{0,0,0,0},{FS_LATIN1,0}} },
128 { EASTEUROPE_CHARSET, 1250, {{0,0,0,0},{FS_LATIN2,0}} },
129 { RUSSIAN_CHARSET, 1251, {{0,0,0,0},{FS_CYRILLIC,0}} },
130 { GREEK_CHARSET, 1253, {{0,0,0,0},{FS_GREEK,0}} },
131 { TURKISH_CHARSET, 1254, {{0,0,0,0},{FS_TURKISH,0}} },
132 { HEBREW_CHARSET, 1255, {{0,0,0,0},{FS_HEBREW,0}} },
133 { ARABIC_CHARSET, 1256, {{0,0,0,0},{FS_ARABIC,0}} },
134 { BALTIC_CHARSET, 1257, {{0,0,0,0},{FS_BALTIC,0}} },
135 { VIETNAMESE_CHARSET, 1258, {{0,0,0,0},{FS_VIETNAMESE,0}} },
136 /* reserved by ANSI */
137 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
138 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
139 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
140 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
141 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
142 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
143 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
144 /* ANSI and OEM */
145 { THAI_CHARSET, 874, {{0,0,0,0},{FS_THAI,0}} },
146 { SHIFTJIS_CHARSET, 932, {{0,0,0,0},{FS_JISJAPAN,0}} },
147 { GB2312_CHARSET, 936, {{0,0,0,0},{FS_CHINESESIMP,0}} },
148 { HANGEUL_CHARSET, 949, {{0,0,0,0},{FS_WANSUNG,0}} },
149 { CHINESEBIG5_CHARSET, 950, {{0,0,0,0},{FS_CHINESETRAD,0}} },
150 { JOHAB_CHARSET, 1361, {{0,0,0,0},{FS_JOHAB,0}} },
151 /* reserved for alternate ANSI and OEM */
152 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
153 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
154 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
155 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
156 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
157 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
158 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
159 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
160 /* reserved for system */
161 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
162 { SYMBOL_CHARSET, CP_SYMBOL, {{0,0,0,0},{FS_SYMBOL,0}} }
165 static void FONT_LogFontAToW( const LOGFONTA *fontA, LPLOGFONTW fontW )
167 memcpy(fontW, fontA, sizeof(LOGFONTA) - LF_FACESIZE);
168 MultiByteToWideChar(CP_ACP, 0, fontA->lfFaceName, -1, fontW->lfFaceName,
169 LF_FACESIZE);
170 fontW->lfFaceName[LF_FACESIZE-1] = 0;
173 static void FONT_LogFontWToA( const LOGFONTW *fontW, LPLOGFONTA fontA )
175 memcpy(fontA, fontW, sizeof(LOGFONTA) - LF_FACESIZE);
176 WideCharToMultiByte(CP_ACP, 0, fontW->lfFaceName, -1, fontA->lfFaceName,
177 LF_FACESIZE, NULL, NULL);
178 fontA->lfFaceName[LF_FACESIZE-1] = 0;
181 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEXA fontA )
183 FONT_LogFontWToA( (const LOGFONTW *)fontW, (LPLOGFONTA)fontA);
185 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
186 (LPSTR) fontA->elfFullName, LF_FULLFACESIZE, NULL, NULL );
187 fontA->elfFullName[LF_FULLFACESIZE-1] = '\0';
188 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
189 (LPSTR) fontA->elfStyle, LF_FACESIZE, NULL, NULL );
190 fontA->elfStyle[LF_FACESIZE-1] = '\0';
191 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
192 (LPSTR) fontA->elfScript, LF_FACESIZE, NULL, NULL );
193 fontA->elfScript[LF_FACESIZE-1] = '\0';
196 /***********************************************************************
197 * TEXTMETRIC conversion functions.
199 static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
201 ptmA->tmHeight = ptmW->tmHeight;
202 ptmA->tmAscent = ptmW->tmAscent;
203 ptmA->tmDescent = ptmW->tmDescent;
204 ptmA->tmInternalLeading = ptmW->tmInternalLeading;
205 ptmA->tmExternalLeading = ptmW->tmExternalLeading;
206 ptmA->tmAveCharWidth = ptmW->tmAveCharWidth;
207 ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth;
208 ptmA->tmWeight = ptmW->tmWeight;
209 ptmA->tmOverhang = ptmW->tmOverhang;
210 ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX;
211 ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
212 ptmA->tmFirstChar = min(ptmW->tmFirstChar, 255);
213 if (ptmW->tmCharSet == SYMBOL_CHARSET)
215 UINT last_char = ptmW->tmLastChar;
216 if (last_char > 0xf000) last_char -= 0xf000;
217 ptmA->tmLastChar = min(last_char, 255);
219 else
220 ptmA->tmLastChar = min(ptmW->tmLastChar, 255);
221 ptmA->tmDefaultChar = min(ptmW->tmDefaultChar, 255);
222 ptmA->tmBreakChar = min(ptmW->tmBreakChar, 255);
223 ptmA->tmItalic = ptmW->tmItalic;
224 ptmA->tmUnderlined = ptmW->tmUnderlined;
225 ptmA->tmStruckOut = ptmW->tmStruckOut;
226 ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
227 ptmA->tmCharSet = ptmW->tmCharSet;
231 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW *ptmW, NEWTEXTMETRICEXA *ptmA )
233 FONT_TextMetricWToA((const TEXTMETRICW *)ptmW, (LPTEXTMETRICA)ptmA);
234 ptmA->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
235 ptmA->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
236 ptmA->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
237 ptmA->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
238 memcpy(&ptmA->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
242 /***********************************************************************
243 * GdiGetCodePage (GDI32.@)
245 DWORD WINAPI GdiGetCodePage( HDC hdc )
247 UINT cp = CP_ACP;
248 CHARSETINFO csi;
249 int charset = GetTextCharset(hdc);
251 /* Hmm, nicely designed api this one! */
252 if(TranslateCharsetInfo(ULongToPtr(charset), &csi, TCI_SRCCHARSET))
253 cp = csi.ciACP;
254 else {
255 switch(charset) {
256 case OEM_CHARSET:
257 cp = GetOEMCP();
258 break;
259 case DEFAULT_CHARSET:
260 cp = GetACP();
261 break;
263 case VISCII_CHARSET:
264 case TCVN_CHARSET:
265 case KOI8_CHARSET:
266 case ISO3_CHARSET:
267 case ISO4_CHARSET:
268 case ISO10_CHARSET:
269 case CELTIC_CHARSET:
270 /* FIXME: These have no place here, but because x11drv
271 enumerates fonts with these (made up) charsets some apps
272 might use them and then the FIXME below would become
273 annoying. Now we could pick the intended codepage for
274 each of these, but since it's broken anyway we'll just
275 use CP_ACP and hope it'll go away...
277 cp = CP_ACP;
278 break;
280 default:
281 FIXME("Can't find codepage for charset %d\n", charset);
282 break;
286 TRACE("charset %d => cp %d\n", charset, cp);
287 return cp;
290 /***********************************************************************
291 * FONT_mbtowc
293 * Returns a Unicode translation of str using the charset of the
294 * currently selected font in hdc. If count is -1 then str is assumed
295 * to be '\0' terminated, otherwise it contains the number of bytes to
296 * convert. If plenW is non-NULL, on return it will point to the
297 * number of WCHARs that have been written. If pCP is non-NULL, on
298 * return it will point to the codepage used in the conversion. The
299 * caller should free the returned LPWSTR from the process heap
300 * itself.
302 static LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
304 UINT cp;
305 INT lenW;
306 LPWSTR strW;
308 cp = GdiGetCodePage( hdc );
310 if(count == -1) count = strlen(str);
311 lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
312 strW = HeapAlloc(GetProcessHeap(), 0, lenW*sizeof(WCHAR));
313 MultiByteToWideChar(cp, 0, str, count, strW, lenW);
314 TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW));
315 if(plenW) *plenW = lenW;
316 if(pCP) *pCP = cp;
317 return strW;
321 /***********************************************************************
322 * CreateFontIndirectA (GDI32.@)
324 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *plfA )
326 LOGFONTW lfW;
328 if (!plfA) return 0;
330 FONT_LogFontAToW( plfA, &lfW );
331 return CreateFontIndirectW( &lfW );
334 /***********************************************************************
335 * CreateFontIndirectW (GDI32.@)
337 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
339 static const WCHAR ItalicW[] = {' ','I','t','a','l','i','c','\0'};
340 static const WCHAR BoldW[] = {' ','B','o','l','d','\0'};
341 WCHAR *pFaceNameItalicSuffix, *pFaceNameBoldSuffix;
342 WCHAR *pFaceNameSuffix = NULL;
343 HFONT hFont;
344 FONTOBJ *fontPtr;
346 if (!plf) return 0;
348 if (!(fontPtr = HeapAlloc( GetProcessHeap(), 0, sizeof(*fontPtr) ))) return 0;
350 fontPtr->logfont = *plf;
352 if (plf->lfEscapement != plf->lfOrientation)
354 /* this should really depend on whether GM_ADVANCED is set */
355 fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
356 WARN("orientation angle %f set to "
357 "escapement angle %f for new font %p\n",
358 plf->lfOrientation/10., plf->lfEscapement/10., fontPtr);
361 pFaceNameItalicSuffix = strstrW(fontPtr->logfont.lfFaceName, ItalicW);
362 if (pFaceNameItalicSuffix)
364 fontPtr->logfont.lfItalic = TRUE;
365 pFaceNameSuffix = pFaceNameItalicSuffix;
368 pFaceNameBoldSuffix = strstrW(fontPtr->logfont.lfFaceName, BoldW);
369 if (pFaceNameBoldSuffix)
371 if (fontPtr->logfont.lfWeight < FW_BOLD)
372 fontPtr->logfont.lfWeight = FW_BOLD;
373 if (!pFaceNameSuffix || (pFaceNameBoldSuffix < pFaceNameSuffix))
374 pFaceNameSuffix = pFaceNameBoldSuffix;
377 if (pFaceNameSuffix) *pFaceNameSuffix = 0;
379 if (!(hFont = alloc_gdi_handle( &fontPtr->header, OBJ_FONT, &font_funcs )))
381 HeapFree( GetProcessHeap(), 0, fontPtr );
382 return 0;
385 TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
386 plf->lfHeight, plf->lfWidth,
387 plf->lfEscapement, plf->lfOrientation,
388 plf->lfPitchAndFamily,
389 plf->lfOutPrecision, plf->lfClipPrecision,
390 plf->lfQuality, plf->lfCharSet,
391 debugstr_w(plf->lfFaceName),
392 plf->lfWeight > 400 ? "Bold" : "",
393 plf->lfItalic ? "Italic" : "",
394 plf->lfUnderline ? "Underline" : "", hFont);
396 return hFont;
399 /*************************************************************************
400 * CreateFontA (GDI32.@)
402 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
403 INT orient, INT weight, DWORD italic,
404 DWORD underline, DWORD strikeout, DWORD charset,
405 DWORD outpres, DWORD clippres, DWORD quality,
406 DWORD pitch, LPCSTR name )
408 LOGFONTA logfont;
410 logfont.lfHeight = height;
411 logfont.lfWidth = width;
412 logfont.lfEscapement = esc;
413 logfont.lfOrientation = orient;
414 logfont.lfWeight = weight;
415 logfont.lfItalic = italic;
416 logfont.lfUnderline = underline;
417 logfont.lfStrikeOut = strikeout;
418 logfont.lfCharSet = charset;
419 logfont.lfOutPrecision = outpres;
420 logfont.lfClipPrecision = clippres;
421 logfont.lfQuality = quality;
422 logfont.lfPitchAndFamily = pitch;
424 if (name)
425 lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
426 else
427 logfont.lfFaceName[0] = '\0';
429 return CreateFontIndirectA( &logfont );
432 /*************************************************************************
433 * CreateFontW (GDI32.@)
435 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
436 INT orient, INT weight, DWORD italic,
437 DWORD underline, DWORD strikeout, DWORD charset,
438 DWORD outpres, DWORD clippres, DWORD quality,
439 DWORD pitch, LPCWSTR name )
441 LOGFONTW logfont;
443 logfont.lfHeight = height;
444 logfont.lfWidth = width;
445 logfont.lfEscapement = esc;
446 logfont.lfOrientation = orient;
447 logfont.lfWeight = weight;
448 logfont.lfItalic = italic;
449 logfont.lfUnderline = underline;
450 logfont.lfStrikeOut = strikeout;
451 logfont.lfCharSet = charset;
452 logfont.lfOutPrecision = outpres;
453 logfont.lfClipPrecision = clippres;
454 logfont.lfQuality = quality;
455 logfont.lfPitchAndFamily = pitch;
457 if (name)
458 lstrcpynW(logfont.lfFaceName, name,
459 sizeof(logfont.lfFaceName) / sizeof(WCHAR));
460 else
461 logfont.lfFaceName[0] = '\0';
463 return CreateFontIndirectW( &logfont );
467 /***********************************************************************
468 * FONT_SelectObject
470 * If the driver supports vector fonts we create a gdi font first and
471 * then call the driver to give it a chance to supply its own device
472 * font. If the driver wants to do this it returns TRUE and we can
473 * delete the gdi font, if the driver wants to use the gdi font it
474 * should return FALSE, to signal an error return GDI_ERROR. For
475 * drivers that don't support vector fonts they must supply their own
476 * font.
478 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc )
480 HGDIOBJ ret = 0;
481 DC *dc = get_dc_ptr( hdc );
483 if (!dc) return 0;
485 if (!GDI_inc_ref_count( handle ))
487 release_dc_ptr( dc );
488 return 0;
491 if (GetDeviceCaps( dc->hSelf, TEXTCAPS ) & TC_VA_ABLE)
492 dc->gdiFont = WineEngCreateFontInstance( dc, handle );
494 if (dc->funcs->pSelectFont) ret = dc->funcs->pSelectFont( dc->physDev, handle, dc->gdiFont );
496 if (ret && dc->gdiFont) dc->gdiFont = 0;
498 if (ret == HGDI_ERROR)
500 GDI_dec_ref_count( handle );
501 ret = 0; /* SelectObject returns 0 on error */
503 else
505 ret = dc->hFont;
506 dc->hFont = handle;
507 GDI_dec_ref_count( ret );
509 release_dc_ptr( dc );
510 return ret;
514 /***********************************************************************
515 * FONT_GetObjectA
517 static INT FONT_GetObjectA( HGDIOBJ handle, INT count, LPVOID buffer )
519 FONTOBJ *font = GDI_GetObjPtr( handle, OBJ_FONT );
520 LOGFONTA lfA;
522 if (!font) return 0;
523 if (buffer)
525 FONT_LogFontWToA( &font->logfont, &lfA );
526 if (count > sizeof(lfA)) count = sizeof(lfA);
527 memcpy( buffer, &lfA, count );
529 else count = sizeof(lfA);
530 GDI_ReleaseObj( handle );
531 return count;
534 /***********************************************************************
535 * FONT_GetObjectW
537 static INT FONT_GetObjectW( HGDIOBJ handle, INT count, LPVOID buffer )
539 FONTOBJ *font = GDI_GetObjPtr( handle, OBJ_FONT );
541 if (!font) return 0;
542 if (buffer)
544 if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
545 memcpy( buffer, &font->logfont, count );
547 else count = sizeof(LOGFONTW);
548 GDI_ReleaseObj( handle );
549 return count;
553 /***********************************************************************
554 * FONT_DeleteObject
556 static BOOL FONT_DeleteObject( HGDIOBJ handle )
558 FONTOBJ *obj;
560 WineEngDestroyFontInstance( handle );
562 if (!(obj = free_gdi_handle( handle ))) return FALSE;
563 return HeapFree( GetProcessHeap(), 0, obj );
567 /***********************************************************************
568 * FONT_EnumInstance
570 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
571 * We have to use other types because of the FONTENUMPROCW definition.
573 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
574 DWORD fType, LPARAM lp )
576 fontEnum32 *pfe = (fontEnum32*)lp;
577 INT ret = 1;
579 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
580 if ((!pfe->lpLogFontParam ||
581 pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
582 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
583 (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
585 /* convert font metrics */
586 ENUMLOGFONTEXA logfont;
587 NEWTEXTMETRICEXA tmA;
589 pfe->dwFlags |= ENUM_CALLED;
590 if (!(pfe->dwFlags & ENUM_UNICODE))
592 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
593 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
594 plf = (LOGFONTW *)&logfont.elfLogFont;
595 ptm = (TEXTMETRICW *)&tmA;
598 ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
600 return ret;
603 /***********************************************************************
604 * FONT_EnumFontFamiliesEx
606 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf,
607 FONTENUMPROCW efproc,
608 LPARAM lParam, DWORD dwUnicode)
610 INT ret = 1, ret2;
611 DC *dc = get_dc_ptr( hDC );
612 fontEnum32 fe32;
613 BOOL enum_gdi_fonts;
615 if (!dc) return 0;
617 if (plf)
618 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName),
619 plf->lfCharSet);
620 fe32.lpLogFontParam = plf;
621 fe32.lpEnumFunc = efproc;
622 fe32.lpData = lParam;
623 fe32.dwFlags = dwUnicode;
624 fe32.hdc = hDC;
626 enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE;
628 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
630 ret = 0;
631 goto done;
634 if (enum_gdi_fonts)
635 ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
636 fe32.dwFlags &= ~ENUM_CALLED;
637 if (ret && dc->funcs->pEnumDeviceFonts) {
638 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, plf, FONT_EnumInstance, (LPARAM)&fe32 );
639 if(fe32.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
640 ret = ret2;
642 done:
643 release_dc_ptr( dc );
644 return ret;
647 /***********************************************************************
648 * EnumFontFamiliesExW (GDI32.@)
650 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
651 FONTENUMPROCW efproc,
652 LPARAM lParam, DWORD dwFlags )
654 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, ENUM_UNICODE );
657 /***********************************************************************
658 * EnumFontFamiliesExA (GDI32.@)
660 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
661 FONTENUMPROCA efproc,
662 LPARAM lParam, DWORD dwFlags)
664 LOGFONTW lfW, *plfW;
666 if (plf)
668 FONT_LogFontAToW( plf, &lfW );
669 plfW = &lfW;
671 else plfW = NULL;
673 return FONT_EnumFontFamiliesEx( hDC, plfW, (FONTENUMPROCW)efproc, lParam, 0);
676 /***********************************************************************
677 * EnumFontFamiliesA (GDI32.@)
679 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
680 FONTENUMPROCA efproc, LPARAM lpData )
682 LOGFONTA lf, *plf;
684 if (lpFamily)
686 if (!*lpFamily) return 1;
687 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
688 lf.lfCharSet = DEFAULT_CHARSET;
689 lf.lfPitchAndFamily = 0;
690 plf = &lf;
692 else plf = NULL;
694 return EnumFontFamiliesExA( hDC, plf, efproc, lpData, 0 );
697 /***********************************************************************
698 * EnumFontFamiliesW (GDI32.@)
700 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
701 FONTENUMPROCW efproc, LPARAM lpData )
703 LOGFONTW lf, *plf;
705 if (lpFamily)
707 if (!*lpFamily) return 1;
708 lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
709 lf.lfCharSet = DEFAULT_CHARSET;
710 lf.lfPitchAndFamily = 0;
711 plf = &lf;
713 else plf = NULL;
715 return EnumFontFamiliesExW( hDC, plf, efproc, lpData, 0 );
718 /***********************************************************************
719 * EnumFontsA (GDI32.@)
721 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
722 LPARAM lpData )
724 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
727 /***********************************************************************
728 * EnumFontsW (GDI32.@)
730 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
731 LPARAM lpData )
733 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
737 /***********************************************************************
738 * GetTextCharacterExtra (GDI32.@)
740 INT WINAPI GetTextCharacterExtra( HDC hdc )
742 INT ret;
743 DC *dc = get_dc_ptr( hdc );
744 if (!dc) return 0x80000000;
745 ret = dc->charExtra;
746 release_dc_ptr( dc );
747 return ret;
751 /***********************************************************************
752 * SetTextCharacterExtra (GDI32.@)
754 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
756 INT prev;
757 DC * dc = get_dc_ptr( hdc );
758 if (!dc) return 0x80000000;
759 if (dc->funcs->pSetTextCharacterExtra)
760 prev = dc->funcs->pSetTextCharacterExtra( dc->physDev, extra );
761 else
763 prev = dc->charExtra;
764 dc->charExtra = extra;
766 release_dc_ptr( dc );
767 return prev;
771 /***********************************************************************
772 * SetTextJustification (GDI32.@)
774 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
776 BOOL ret = TRUE;
777 DC * dc = get_dc_ptr( hdc );
778 if (!dc) return FALSE;
779 if (dc->funcs->pSetTextJustification)
780 ret = dc->funcs->pSetTextJustification( dc->physDev, extra, breaks );
781 else
783 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
784 if (!extra) breaks = 0;
785 if (breaks)
787 dc->breakExtra = extra / breaks;
788 dc->breakRem = extra - (breaks * dc->breakExtra);
790 else
792 dc->breakExtra = 0;
793 dc->breakRem = 0;
796 release_dc_ptr( dc );
797 return ret;
801 /***********************************************************************
802 * GetTextFaceA (GDI32.@)
804 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
806 INT res = GetTextFaceW(hdc, 0, NULL);
807 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
808 GetTextFaceW( hdc, res, nameW );
810 if (name)
812 if (count)
814 res = WideCharToMultiByte(CP_ACP, 0, nameW, -1, name, count, NULL, NULL);
815 if (res == 0)
816 res = count;
817 name[count-1] = 0;
818 /* GetTextFaceA does NOT include the nul byte in the return count. */
819 res--;
821 else
822 res = 0;
824 else
825 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
826 HeapFree( GetProcessHeap(), 0, nameW );
827 return res;
830 /***********************************************************************
831 * GetTextFaceW (GDI32.@)
833 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
835 FONTOBJ *font;
836 INT ret = 0;
838 DC * dc = get_dc_ptr( hdc );
839 if (!dc) return 0;
841 if(dc->gdiFont)
842 ret = WineEngGetTextFace(dc->gdiFont, count, name);
843 else if ((font = GDI_GetObjPtr( dc->hFont, OBJ_FONT )))
845 INT n = strlenW(font->logfont.lfFaceName) + 1;
846 if (name)
848 lstrcpynW( name, font->logfont.lfFaceName, count );
849 ret = min(count, n);
851 else ret = n;
852 GDI_ReleaseObj( dc->hFont );
854 release_dc_ptr( dc );
855 return ret;
859 /***********************************************************************
860 * GetTextExtentPoint32A (GDI32.@)
862 * See GetTextExtentPoint32W.
864 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
865 LPSIZE size )
867 BOOL ret = FALSE;
868 INT wlen;
869 LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
871 if (p) {
872 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
873 HeapFree( GetProcessHeap(), 0, p );
876 TRACE("(%p %s %d %p): returning %d x %d\n",
877 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
878 return ret;
882 /***********************************************************************
883 * GetTextExtentPoint32W [GDI32.@]
885 * Computes width/height for a string.
887 * Computes width and height of the specified string.
889 * RETURNS
890 * Success: TRUE
891 * Failure: FALSE
893 BOOL WINAPI GetTextExtentPoint32W(
894 HDC hdc, /* [in] Handle of device context */
895 LPCWSTR str, /* [in] Address of text string */
896 INT count, /* [in] Number of characters in string */
897 LPSIZE size) /* [out] Address of structure for string size */
899 return GetTextExtentExPointW(hdc, str, count, 0, NULL, NULL, size);
902 /***********************************************************************
903 * GetTextExtentExPointI [GDI32.@]
905 * Computes width and height of the array of glyph indices.
907 * PARAMS
908 * hdc [I] Handle of device context.
909 * indices [I] Glyph index array.
910 * count [I] Number of glyphs in array.
911 * max_ext [I] Maximum width in glyphs.
912 * nfit [O] Maximum number of characters.
913 * dxs [O] Partial string widths.
914 * size [O] Returned string size.
916 * RETURNS
917 * Success: TRUE
918 * Failure: FALSE
920 BOOL WINAPI GetTextExtentExPointI( HDC hdc, const WORD *indices, INT count, INT max_ext,
921 LPINT nfit, LPINT dxs, LPSIZE size )
923 BOOL ret = FALSE;
924 DC * dc = get_dc_ptr( hdc );
925 if (!dc) return FALSE;
927 if(dc->gdiFont) {
928 ret = WineEngGetTextExtentExPointI(dc->gdiFont, indices, count, max_ext, nfit, dxs, size);
929 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
930 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
931 size->cx += count * dc->charExtra;
933 else if(dc->funcs->pGetTextExtentExPoint) {
934 FIXME("calling GetTextExtentExPoint\n");
935 ret = dc->funcs->pGetTextExtentExPoint( dc->physDev, indices, count,
936 max_ext, nfit, dxs, size );
939 release_dc_ptr( dc );
941 TRACE("(%p %p %d %p): returning %d x %d\n",
942 hdc, indices, count, size, size->cx, size->cy );
943 return ret;
946 /***********************************************************************
947 * GetTextExtentPointI [GDI32.@]
949 * Computes width and height of the array of glyph indices.
951 * PARAMS
952 * hdc [I] Handle of device context.
953 * indices [I] Glyph index array.
954 * count [I] Number of glyphs in array.
955 * size [O] Returned string size.
957 * RETURNS
958 * Success: TRUE
959 * Failure: FALSE
961 BOOL WINAPI GetTextExtentPointI( HDC hdc, const WORD *indices, INT count, LPSIZE size )
963 return GetTextExtentExPointI( hdc, indices, count, 0, NULL, NULL, size );
967 /***********************************************************************
968 * GetTextExtentPointA (GDI32.@)
970 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
971 LPSIZE size )
973 TRACE("not bug compatible.\n");
974 return GetTextExtentPoint32A( hdc, str, count, size );
977 /***********************************************************************
978 * GetTextExtentPointW (GDI32.@)
980 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
981 LPSIZE size )
983 TRACE("not bug compatible.\n");
984 return GetTextExtentPoint32W( hdc, str, count, size );
988 /***********************************************************************
989 * GetTextExtentExPointA (GDI32.@)
991 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
992 INT maxExt, LPINT lpnFit,
993 LPINT alpDx, LPSIZE size )
995 BOOL ret;
996 INT wlen;
997 INT *walpDx = NULL;
998 LPWSTR p = NULL;
1000 if (alpDx &&
1001 NULL == (walpDx = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT))))
1002 return FALSE;
1004 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1005 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
1006 if (walpDx)
1008 INT n = lpnFit ? *lpnFit : wlen;
1009 INT i, j;
1010 for(i = 0, j = 0; i < n; i++, j++)
1012 alpDx[j] = walpDx[i];
1013 if (IsDBCSLeadByte(str[j])) alpDx[++j] = walpDx[i];
1016 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1017 HeapFree( GetProcessHeap(), 0, p );
1018 HeapFree( GetProcessHeap(), 0, walpDx );
1019 return ret;
1023 /***********************************************************************
1024 * GetTextExtentExPointW (GDI32.@)
1026 * Return the size of the string as it would be if it was output properly by
1027 * e.g. TextOut.
1029 * This should include
1030 * - Intercharacter spacing
1031 * - justification spacing (not yet done)
1032 * - kerning? see below
1034 * Kerning. Since kerning would be carried out by the rendering code it should
1035 * be done by the driver. However they don't support it yet. Also I am not
1036 * yet persuaded that (certainly under Win95) any kerning is actually done.
1038 * str: According to MSDN this should be null-terminated. That is not true; a
1039 * null will not terminate it early.
1040 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1041 * than count. I have seen it be either the size of the full string or
1042 * 1 less than the size of the full string. I have not seen it bear any
1043 * resemblance to the portion that would fit.
1044 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1045 * trailing intercharacter spacing and any trailing justification.
1047 * FIXME
1048 * Currently we do this by measuring each character etc. We should do it by
1049 * passing the request to the driver, perhaps by extending the
1050 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1051 * thinking about kerning issues and rounding issues in the justification.
1054 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1055 INT maxExt, LPINT lpnFit,
1056 LPINT alpDx, LPSIZE size )
1058 INT nFit = 0;
1059 LPINT dxs = NULL;
1060 DC *dc;
1061 BOOL ret = FALSE;
1062 TEXTMETRICW tm;
1064 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1066 dc = get_dc_ptr(hdc);
1067 if (! dc)
1068 return FALSE;
1070 GetTextMetricsW(hdc, &tm);
1072 /* If we need to calculate nFit, then we need the partial extents even if
1073 the user hasn't provided us with an array. */
1074 if (lpnFit)
1076 dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]);
1077 if (! dxs)
1079 release_dc_ptr(dc);
1080 SetLastError(ERROR_OUTOFMEMORY);
1081 return FALSE;
1084 else
1085 dxs = alpDx;
1087 if (dc->gdiFont)
1088 ret = WineEngGetTextExtentExPoint(dc->gdiFont, str, count,
1089 0, NULL, dxs, size);
1090 else if (dc->funcs->pGetTextExtentExPoint)
1091 ret = dc->funcs->pGetTextExtentExPoint(dc->physDev, str, count,
1092 0, NULL, dxs, size);
1094 /* Perform device size to world size transformations. */
1095 if (ret)
1097 INT extra = dc->charExtra,
1098 breakExtra = dc->breakExtra,
1099 breakRem = dc->breakRem,
1102 if (dxs)
1104 for (i = 0; i < count; ++i)
1106 dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
1107 dxs[i] += (i+1) * extra;
1108 if (count > 1 && (breakExtra || breakRem) && str[i] == tm.tmBreakChar)
1110 dxs[i] += breakExtra;
1111 if (breakRem > 0)
1113 breakRem--;
1114 dxs[i]++;
1117 if (dxs[i] <= maxExt)
1118 ++nFit;
1120 breakRem = dc->breakRem;
1122 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1123 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1125 if (!dxs && count > 1 && (breakExtra || breakRem))
1127 for (i = 0; i < count; i++)
1129 if (str[i] == tm.tmBreakChar)
1131 size->cx += breakExtra;
1132 if (breakRem > 0)
1134 breakRem--;
1135 (size->cx)++;
1142 if (lpnFit)
1143 *lpnFit = nFit;
1145 if (! alpDx)
1146 HeapFree(GetProcessHeap(), 0, dxs);
1148 release_dc_ptr( dc );
1150 TRACE("returning %d %d x %d\n",nFit,size->cx,size->cy);
1151 return ret;
1154 /***********************************************************************
1155 * GetTextMetricsA (GDI32.@)
1157 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1159 TEXTMETRICW tm32;
1161 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1162 FONT_TextMetricWToA( &tm32, metrics );
1163 return TRUE;
1166 /***********************************************************************
1167 * GetTextMetricsW (GDI32.@)
1169 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1171 BOOL ret = FALSE;
1172 DC * dc = get_dc_ptr( hdc );
1173 if (!dc) return FALSE;
1175 if (dc->gdiFont)
1176 ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1177 else if (dc->funcs->pGetTextMetrics)
1178 ret = dc->funcs->pGetTextMetrics( dc->physDev, metrics );
1180 if (ret)
1182 /* device layer returns values in device units
1183 * therefore we have to convert them to logical */
1185 metrics->tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1186 metrics->tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1188 #define WDPTOLP(x) ((x<0)? \
1189 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1190 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1191 #define HDPTOLP(y) ((y<0)? \
1192 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1193 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1195 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1196 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1197 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1198 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1199 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1200 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1201 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1202 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1203 ret = TRUE;
1204 #undef WDPTOLP
1205 #undef HDPTOLP
1206 TRACE("text metrics:\n"
1207 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1208 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1209 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1210 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1211 " PitchAndFamily = %02x\n"
1212 " --------------------\n"
1213 " InternalLeading = %i\n"
1214 " Ascent = %i\n"
1215 " Descent = %i\n"
1216 " Height = %i\n",
1217 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1218 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1219 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1220 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1221 metrics->tmPitchAndFamily,
1222 metrics->tmInternalLeading,
1223 metrics->tmAscent,
1224 metrics->tmDescent,
1225 metrics->tmHeight );
1227 release_dc_ptr( dc );
1228 return ret;
1232 /***********************************************************************
1233 * GetOutlineTextMetricsA (GDI32.@)
1234 * Gets metrics for TrueType fonts.
1236 * NOTES
1237 * If the supplied buffer isn't big enough Windows partially fills it up to
1238 * its given length and returns that length.
1240 * RETURNS
1241 * Success: Non-zero or size of required buffer
1242 * Failure: 0
1244 UINT WINAPI GetOutlineTextMetricsA(
1245 HDC hdc, /* [in] Handle of device context */
1246 UINT cbData, /* [in] Size of metric data array */
1247 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1249 char buf[512], *ptr;
1250 UINT ret, needed;
1251 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1252 OUTLINETEXTMETRICA *output = lpOTM;
1253 INT left, len;
1255 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1256 return 0;
1257 if(ret > sizeof(buf))
1258 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1259 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1261 needed = sizeof(OUTLINETEXTMETRICA);
1262 if(lpOTMW->otmpFamilyName)
1263 needed += WideCharToMultiByte(CP_ACP, 0,
1264 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1265 NULL, 0, NULL, NULL);
1266 if(lpOTMW->otmpFaceName)
1267 needed += WideCharToMultiByte(CP_ACP, 0,
1268 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1269 NULL, 0, NULL, NULL);
1270 if(lpOTMW->otmpStyleName)
1271 needed += WideCharToMultiByte(CP_ACP, 0,
1272 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1273 NULL, 0, NULL, NULL);
1274 if(lpOTMW->otmpFullName)
1275 needed += WideCharToMultiByte(CP_ACP, 0,
1276 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1277 NULL, 0, NULL, NULL);
1279 if(!lpOTM) {
1280 ret = needed;
1281 goto end;
1284 TRACE("needed = %d\n", needed);
1285 if(needed > cbData)
1286 /* Since the supplied buffer isn't big enough, we'll alloc one
1287 that is and memcpy the first cbData bytes into the lpOTM at
1288 the end. */
1289 output = HeapAlloc(GetProcessHeap(), 0, needed);
1291 ret = output->otmSize = min(needed, cbData);
1292 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1293 output->otmFiller = 0;
1294 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1295 output->otmfsSelection = lpOTMW->otmfsSelection;
1296 output->otmfsType = lpOTMW->otmfsType;
1297 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1298 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1299 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1300 output->otmEMSquare = lpOTMW->otmEMSquare;
1301 output->otmAscent = lpOTMW->otmAscent;
1302 output->otmDescent = lpOTMW->otmDescent;
1303 output->otmLineGap = lpOTMW->otmLineGap;
1304 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1305 output->otmsXHeight = lpOTMW->otmsXHeight;
1306 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1307 output->otmMacAscent = lpOTMW->otmMacAscent;
1308 output->otmMacDescent = lpOTMW->otmMacDescent;
1309 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1310 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1311 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1312 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1313 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1314 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1315 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1316 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1317 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1318 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1321 ptr = (char*)(output + 1);
1322 left = needed - sizeof(*output);
1324 if(lpOTMW->otmpFamilyName) {
1325 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1326 len = WideCharToMultiByte(CP_ACP, 0,
1327 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1328 ptr, left, NULL, NULL);
1329 left -= len;
1330 ptr += len;
1331 } else
1332 output->otmpFamilyName = 0;
1334 if(lpOTMW->otmpFaceName) {
1335 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1336 len = WideCharToMultiByte(CP_ACP, 0,
1337 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1338 ptr, left, NULL, NULL);
1339 left -= len;
1340 ptr += len;
1341 } else
1342 output->otmpFaceName = 0;
1344 if(lpOTMW->otmpStyleName) {
1345 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1346 len = WideCharToMultiByte(CP_ACP, 0,
1347 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1348 ptr, left, NULL, NULL);
1349 left -= len;
1350 ptr += len;
1351 } else
1352 output->otmpStyleName = 0;
1354 if(lpOTMW->otmpFullName) {
1355 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1356 len = WideCharToMultiByte(CP_ACP, 0,
1357 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1358 ptr, left, NULL, NULL);
1359 left -= len;
1360 } else
1361 output->otmpFullName = 0;
1363 assert(left == 0);
1365 if(output != lpOTM) {
1366 memcpy(lpOTM, output, cbData);
1367 HeapFree(GetProcessHeap(), 0, output);
1369 /* check if the string offsets really fit into the provided size */
1370 /* FIXME: should we check string length as well? */
1371 /* make sure that we don't read/write beyond the provided buffer */
1372 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(LPSTR))
1374 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1375 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1378 /* make sure that we don't read/write beyond the provided buffer */
1379 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(LPSTR))
1381 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1382 lpOTM->otmpFaceName = 0; /* doesn't fit */
1385 /* make sure that we don't read/write beyond the provided buffer */
1386 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(LPSTR))
1388 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1389 lpOTM->otmpStyleName = 0; /* doesn't fit */
1392 /* make sure that we don't read/write beyond the provided buffer */
1393 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(LPSTR))
1395 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1396 lpOTM->otmpFullName = 0; /* doesn't fit */
1400 end:
1401 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1402 HeapFree(GetProcessHeap(), 0, lpOTMW);
1404 return ret;
1408 /***********************************************************************
1409 * GetOutlineTextMetricsW [GDI32.@]
1411 UINT WINAPI GetOutlineTextMetricsW(
1412 HDC hdc, /* [in] Handle of device context */
1413 UINT cbData, /* [in] Size of metric data array */
1414 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1416 DC *dc = get_dc_ptr( hdc );
1417 OUTLINETEXTMETRICW *output = lpOTM;
1418 UINT ret;
1420 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1421 if(!dc) return 0;
1423 if(dc->gdiFont) {
1424 ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, output);
1425 if(lpOTM && ret) {
1426 if(ret > cbData) {
1427 output = HeapAlloc(GetProcessHeap(), 0, ret);
1428 WineEngGetOutlineTextMetrics(dc->gdiFont, ret, output);
1431 output->otmTextMetrics.tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1432 output->otmTextMetrics.tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1434 #define WDPTOLP(x) ((x<0)? \
1435 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1436 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1437 #define HDPTOLP(y) ((y<0)? \
1438 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1439 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1441 output->otmTextMetrics.tmHeight = HDPTOLP(output->otmTextMetrics.tmHeight);
1442 output->otmTextMetrics.tmAscent = HDPTOLP(output->otmTextMetrics.tmAscent);
1443 output->otmTextMetrics.tmDescent = HDPTOLP(output->otmTextMetrics.tmDescent);
1444 output->otmTextMetrics.tmInternalLeading = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1445 output->otmTextMetrics.tmExternalLeading = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1446 output->otmTextMetrics.tmAveCharWidth = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1447 output->otmTextMetrics.tmMaxCharWidth = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1448 output->otmTextMetrics.tmOverhang = WDPTOLP(output->otmTextMetrics.tmOverhang);
1449 output->otmAscent = HDPTOLP(output->otmAscent);
1450 output->otmDescent = HDPTOLP(output->otmDescent);
1451 output->otmLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmLineGap));
1452 output->otmsCapEmHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsCapEmHeight));
1453 output->otmsXHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsXHeight));
1454 output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1455 output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1456 output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1457 output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1458 output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1459 output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1460 output->otmMacLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmMacLineGap));
1461 output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1462 output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1463 output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1464 output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1465 output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1466 output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1467 output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1468 output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1469 output->otmsStrikeoutSize = abs(INTERNAL_YDSTOWS(dc,output->otmsStrikeoutSize));
1470 output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1471 output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1472 output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1473 #undef WDPTOLP
1474 #undef HDPTOLP
1475 if(output != lpOTM) {
1476 memcpy(lpOTM, output, cbData);
1477 HeapFree(GetProcessHeap(), 0, output);
1478 ret = cbData;
1483 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1484 but really this should just be a return 0. */
1486 ret = sizeof(*lpOTM);
1487 if (lpOTM) {
1488 if(cbData < ret)
1489 ret = 0;
1490 else {
1491 memset(lpOTM, 0, ret);
1492 lpOTM->otmSize = sizeof(*lpOTM);
1493 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1495 Further fill of the structure not implemented,
1496 Needs real values for the structure members
1501 release_dc_ptr(dc);
1502 return ret;
1506 /***********************************************************************
1507 * GetCharWidthW (GDI32.@)
1508 * GetCharWidth32W (GDI32.@)
1510 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1511 LPINT buffer )
1513 UINT i;
1514 BOOL ret = FALSE;
1515 DC * dc = get_dc_ptr( hdc );
1516 if (!dc) return FALSE;
1518 if (dc->gdiFont)
1519 ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1520 else if (dc->funcs->pGetCharWidth)
1521 ret = dc->funcs->pGetCharWidth( dc->physDev, firstChar, lastChar, buffer);
1523 if (ret)
1525 /* convert device units to logical */
1526 for( i = firstChar; i <= lastChar; i++, buffer++ )
1527 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1528 ret = TRUE;
1530 release_dc_ptr( dc );
1531 return ret;
1535 /***********************************************************************
1536 * GetCharWidthA (GDI32.@)
1537 * GetCharWidth32A (GDI32.@)
1539 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1540 LPINT buffer )
1542 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1543 LPSTR str;
1544 LPWSTR wstr;
1545 BOOL ret = TRUE;
1547 if(count <= 0) return FALSE;
1549 str = HeapAlloc(GetProcessHeap(), 0, count);
1550 for(i = 0; i < count; i++)
1551 str[i] = (BYTE)(firstChar + i);
1553 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1555 for(i = 0; i < wlen; i++)
1557 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1559 ret = FALSE;
1560 break;
1562 buffer++;
1565 HeapFree(GetProcessHeap(), 0, str);
1566 HeapFree(GetProcessHeap(), 0, wstr);
1568 return ret;
1572 /***********************************************************************
1573 * ExtTextOutA (GDI32.@)
1575 * See ExtTextOutW.
1577 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1578 const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1580 INT wlen;
1581 UINT codepage;
1582 LPWSTR p;
1583 BOOL ret;
1584 LPINT lpDxW = NULL;
1586 if (flags & ETO_GLYPH_INDEX)
1587 return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
1589 p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
1591 if (lpDx) {
1592 unsigned int i = 0, j = 0;
1594 lpDxW = HeapAlloc( GetProcessHeap(), 0, wlen*sizeof(INT));
1595 while(i < count) {
1596 if(IsDBCSLeadByteEx(codepage, str[i])) {
1597 lpDxW[j++] = lpDx[i] + lpDx[i+1];
1598 i = i + 2;
1599 } else {
1600 lpDxW[j++] = lpDx[i];
1601 i = i + 1;
1606 ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1608 HeapFree( GetProcessHeap(), 0, p );
1609 HeapFree( GetProcessHeap(), 0, lpDxW );
1610 return ret;
1614 /***********************************************************************
1615 * ExtTextOutW (GDI32.@)
1617 * Draws text using the currently selected font, background color, and text color.
1620 * PARAMS
1621 * x,y [I] coordinates of string
1622 * flags [I]
1623 * ETO_GRAYED - undocumented on MSDN
1624 * ETO_OPAQUE - use background color for fill the rectangle
1625 * ETO_CLIPPED - clipping text to the rectangle
1626 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1627 * than encoded characters. Implies ETO_IGNORELANGUAGE
1628 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1629 * Affects BiDi ordering
1630 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1631 * ETO_PDY - unimplemented
1632 * ETO_NUMERICSLATIN - unimplemented always assumed -
1633 * do not translate numbers into locale representations
1634 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1635 * lprect [I] dimensions for clipping or/and opaquing
1636 * str [I] text string
1637 * count [I] number of symbols in string
1638 * lpDx [I] optional parameter with distance between drawing characters
1640 * RETURNS
1641 * Success: TRUE
1642 * Failure: FALSE
1644 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1645 const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1647 BOOL ret = FALSE;
1648 LPWSTR reordered_str = (LPWSTR)str;
1649 WORD *glyphs = NULL;
1650 UINT align = GetTextAlign( hdc );
1651 POINT pt;
1652 TEXTMETRICW tm;
1653 LOGFONTW lf;
1654 double cosEsc, sinEsc;
1655 INT *deltas = NULL, char_extra;
1656 SIZE sz;
1657 RECT rc;
1658 BOOL done_extents = FALSE;
1659 INT width = 0, xwidth = 0, ywidth = 0;
1660 DWORD type;
1661 DC * dc = get_dc_ptr( hdc );
1662 INT breakRem;
1663 static int quietfixme = 0;
1665 if (!dc) return FALSE;
1667 breakRem = dc->breakRem;
1669 if (quietfixme == 0 && flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY))
1671 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY unimplemented\n");
1672 quietfixme = 1;
1674 if (!dc->funcs->pExtTextOut && !PATH_IsPathOpen(dc->path))
1676 release_dc_ptr( dc );
1677 return ret;
1680 update_dc( dc );
1681 type = GetObjectType(hdc);
1682 if(type == OBJ_METADC || type == OBJ_ENHMETADC)
1684 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, flags, lprect, str, count, lpDx);
1685 release_dc_ptr( dc );
1686 return ret;
1689 if (!lprect)
1690 flags &= ~ETO_CLIPPED;
1692 if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && count > 0 )
1694 reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1696 BIDI_Reorder( str, count, GCP_REORDER,
1697 ((flags&ETO_RTLREADING)!=0 || (GetTextAlign(hdc)&TA_RTLREADING)!=0)?
1698 WINE_GCPW_FORCE_RTL:WINE_GCPW_FORCE_LTR,
1699 reordered_str, count, NULL );
1701 flags |= ETO_IGNORELANGUAGE;
1704 TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc, x, y, flags,
1705 lprect, debugstr_wn(str, count), count, lpDx);
1707 if(flags & ETO_GLYPH_INDEX)
1708 glyphs = reordered_str;
1710 if(lprect)
1711 TRACE("rect: %d,%d - %d,%d\n", lprect->left, lprect->top, lprect->right,
1712 lprect->bottom);
1713 TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
1715 if(align & TA_UPDATECP)
1717 GetCurrentPositionEx( hdc, &pt );
1718 x = pt.x;
1719 y = pt.y;
1722 GetTextMetricsW(hdc, &tm);
1723 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1725 if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
1726 lf.lfEscapement = 0;
1728 if(lf.lfEscapement != 0)
1730 cosEsc = cos(lf.lfEscapement * M_PI / 1800);
1731 sinEsc = sin(lf.lfEscapement * M_PI / 1800);
1733 else
1735 cosEsc = 1;
1736 sinEsc = 0;
1739 if(flags & (ETO_CLIPPED | ETO_OPAQUE))
1741 if(!lprect)
1743 if(flags & ETO_GLYPH_INDEX)
1744 GetTextExtentPointI(hdc, glyphs, count, &sz);
1745 else
1746 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1748 done_extents = TRUE;
1749 rc.left = x;
1750 rc.top = y;
1751 rc.right = x + sz.cx;
1752 rc.bottom = y + sz.cy;
1754 else
1756 rc = *lprect;
1759 LPtoDP(hdc, (POINT*)&rc, 2);
1761 if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
1762 if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
1765 if ((flags & ETO_OPAQUE) && !PATH_IsPathOpen(dc->path))
1766 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1768 if(count == 0)
1770 ret = TRUE;
1771 goto done;
1774 pt.x = x;
1775 pt.y = y;
1776 LPtoDP(hdc, &pt, 1);
1777 x = pt.x;
1778 y = pt.y;
1780 char_extra = GetTextCharacterExtra(hdc);
1781 if(char_extra || dc->breakExtra || breakRem || lpDx || lf.lfEscapement != 0)
1783 UINT i;
1784 SIZE tmpsz;
1785 deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT));
1786 for(i = 0; i < count; i++)
1788 if(lpDx && (flags & ETO_PDY))
1789 deltas[i] = lpDx[i*2] + char_extra;
1790 else if(lpDx)
1791 deltas[i] = lpDx[i] + char_extra;
1792 else
1794 if(flags & ETO_GLYPH_INDEX)
1795 GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
1796 else
1797 GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
1799 deltas[i] = tmpsz.cx;
1802 if (!(flags & ETO_GLYPH_INDEX) && (dc->breakExtra || breakRem) && reordered_str[i] == tm.tmBreakChar)
1804 deltas[i] = deltas[i] + dc->breakExtra;
1805 if (breakRem > 0)
1807 breakRem--;
1808 deltas[i]++;
1811 deltas[i] = INTERNAL_XWSTODS(dc, deltas[i]);
1812 width += deltas[i];
1815 else
1817 if(!done_extents)
1819 if(flags & ETO_GLYPH_INDEX)
1820 GetTextExtentPointI(hdc, glyphs, count, &sz);
1821 else
1822 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1823 done_extents = TRUE;
1825 width = INTERNAL_XWSTODS(dc, sz.cx);
1827 xwidth = width * cosEsc;
1828 ywidth = width * sinEsc;
1830 tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
1831 tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
1832 switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
1834 case TA_LEFT:
1835 if (align & TA_UPDATECP)
1837 pt.x = x + xwidth;
1838 pt.y = y - ywidth;
1839 DPtoLP(hdc, &pt, 1);
1840 MoveToEx(hdc, pt.x, pt.y, NULL);
1842 break;
1844 case TA_CENTER:
1845 x -= xwidth / 2;
1846 y += ywidth / 2;
1847 break;
1849 case TA_RIGHT:
1850 x -= xwidth;
1851 y += ywidth;
1852 if (align & TA_UPDATECP)
1854 pt.x = x;
1855 pt.y = y;
1856 DPtoLP(hdc, &pt, 1);
1857 MoveToEx(hdc, pt.x, pt.y, NULL);
1859 break;
1862 switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
1864 case TA_TOP:
1865 y += tm.tmAscent * cosEsc;
1866 x += tm.tmAscent * sinEsc;
1867 break;
1869 case TA_BOTTOM:
1870 y -= tm.tmDescent * cosEsc;
1871 x -= tm.tmDescent * sinEsc;
1872 break;
1874 case TA_BASELINE:
1875 break;
1878 if (GetBkMode(hdc) != TRANSPARENT && !PATH_IsPathOpen(dc->path))
1880 if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
1882 if(!(flags & ETO_OPAQUE) || x < rc.left || x + width >= rc.right ||
1883 y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
1885 RECT rc;
1886 rc.left = x;
1887 rc.right = x + width;
1888 rc.top = y - tm.tmAscent;
1889 rc.bottom = y + tm.tmDescent;
1890 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1895 if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
1897 HFONT orig_font = dc->hFont, cur_font;
1898 UINT glyph;
1899 INT span = 0, *offsets = NULL;
1900 unsigned int i;
1902 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
1903 for(i = 0; i < count; i++)
1905 WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
1906 if(cur_font != dc->hFont)
1908 if(!offsets)
1910 unsigned int j;
1911 offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
1912 offsets[0] = 0;
1913 if(!deltas)
1915 SIZE tmpsz;
1916 for(j = 1; j < count; j++)
1918 GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
1919 offsets[j] = offsets[j-1] + INTERNAL_XWSTODS(dc, tmpsz.cx);
1922 else
1924 for(j = 1; j < count; j++)
1925 offsets[j] = offsets[j-1] + deltas[j];
1928 if(span)
1930 if (PATH_IsPathOpen(dc->path))
1931 ret = PATH_ExtTextOut(dc, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
1932 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
1933 glyphs, span, deltas ? deltas + i - span : NULL);
1934 else
1935 dc->funcs->pExtTextOut(dc->physDev, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
1936 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
1937 glyphs, span, deltas ? deltas + i - span : NULL);
1938 span = 0;
1940 SelectObject(hdc, cur_font);
1942 glyphs[span++] = glyph;
1944 if(i == count - 1)
1946 if (PATH_IsPathOpen(dc->path))
1947 ret = PATH_ExtTextOut(dc, x + (offsets ? offsets[count - span] * cosEsc : 0),
1948 y - (offsets ? offsets[count - span] * sinEsc : 0),
1949 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
1950 glyphs, span, deltas ? deltas + count - span : NULL);
1951 else
1952 ret = dc->funcs->pExtTextOut(dc->physDev, x + (offsets ? offsets[count - span] * cosEsc : 0),
1953 y - (offsets ? offsets[count - span] * sinEsc : 0),
1954 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
1955 glyphs, span, deltas ? deltas + count - span : NULL);
1956 SelectObject(hdc, orig_font);
1957 HeapFree(GetProcessHeap(), 0, offsets);
1961 else
1963 if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
1965 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
1966 GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
1967 flags |= ETO_GLYPH_INDEX;
1970 if (PATH_IsPathOpen(dc->path))
1971 ret = PATH_ExtTextOut(dc, x, y, (flags & ~ETO_OPAQUE), &rc,
1972 glyphs ? glyphs : reordered_str, count, deltas);
1973 else
1974 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, (flags & ~ETO_OPAQUE), &rc,
1975 glyphs ? glyphs : reordered_str, count, deltas);
1978 done:
1979 HeapFree(GetProcessHeap(), 0, deltas);
1980 if(glyphs != reordered_str)
1981 HeapFree(GetProcessHeap(), 0, glyphs);
1982 if(reordered_str != str)
1983 HeapFree(GetProcessHeap(), 0, reordered_str);
1985 release_dc_ptr( dc );
1987 if (ret && (lf.lfUnderline || lf.lfStrikeOut))
1989 int underlinePos, strikeoutPos;
1990 int underlineWidth, strikeoutWidth;
1991 UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
1992 OUTLINETEXTMETRICW* otm = NULL;
1994 if(!size)
1996 underlinePos = 0;
1997 underlineWidth = tm.tmAscent / 20 + 1;
1998 strikeoutPos = tm.tmAscent / 2;
1999 strikeoutWidth = underlineWidth;
2001 else
2003 otm = HeapAlloc(GetProcessHeap(), 0, size);
2004 GetOutlineTextMetricsW(hdc, size, otm);
2005 underlinePos = otm->otmsUnderscorePosition;
2006 underlineWidth = otm->otmsUnderscoreSize;
2007 strikeoutPos = otm->otmsStrikeoutPosition;
2008 strikeoutWidth = otm->otmsStrikeoutSize;
2009 HeapFree(GetProcessHeap(), 0, otm);
2012 if (PATH_IsPathOpen(dc->path))
2014 POINT pts[5];
2015 HPEN hpen;
2016 HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2018 hbrush = SelectObject(hdc, hbrush);
2019 hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2021 if (lf.lfUnderline)
2023 pts[0].x = x - underlinePos * sinEsc;
2024 pts[0].y = y - underlinePos * cosEsc;
2025 pts[1].x = x + xwidth - underlinePos * sinEsc;
2026 pts[1].y = y - ywidth - underlinePos * cosEsc;
2027 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2028 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2029 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2030 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2031 pts[4].x = pts[0].x;
2032 pts[4].y = pts[0].y;
2033 DPtoLP(hdc, pts, 5);
2034 Polygon(hdc, pts, 5);
2037 if (lf.lfStrikeOut)
2039 pts[0].x = x - strikeoutPos * sinEsc;
2040 pts[0].y = y - strikeoutPos * cosEsc;
2041 pts[1].x = x + xwidth - strikeoutPos * sinEsc;
2042 pts[1].y = y - ywidth - strikeoutPos * cosEsc;
2043 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2044 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2045 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2046 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2047 pts[4].x = pts[0].x;
2048 pts[4].y = pts[0].y;
2049 DPtoLP(hdc, pts, 5);
2050 Polygon(hdc, pts, 5);
2053 SelectObject(hdc, hpen);
2054 hbrush = SelectObject(hdc, hbrush);
2055 DeleteObject(hbrush);
2057 else
2059 POINT pts[2], oldpt;
2060 HPEN hpen;
2062 if (lf.lfUnderline)
2064 hpen = CreatePen(PS_SOLID, underlineWidth, GetTextColor(hdc));
2065 hpen = SelectObject(hdc, hpen);
2066 pts[0].x = x;
2067 pts[0].y = y;
2068 pts[1].x = x + xwidth;
2069 pts[1].y = y - ywidth;
2070 DPtoLP(hdc, pts, 2);
2071 MoveToEx(hdc, pts[0].x - underlinePos * sinEsc, pts[0].y - underlinePos * cosEsc, &oldpt);
2072 LineTo(hdc, pts[1].x - underlinePos * sinEsc, pts[1].y - underlinePos * cosEsc);
2073 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2074 DeleteObject(SelectObject(hdc, hpen));
2077 if (lf.lfStrikeOut)
2079 hpen = CreatePen(PS_SOLID, strikeoutWidth, GetTextColor(hdc));
2080 hpen = SelectObject(hdc, hpen);
2081 pts[0].x = x;
2082 pts[0].y = y;
2083 pts[1].x = x + xwidth;
2084 pts[1].y = y - ywidth;
2085 DPtoLP(hdc, pts, 2);
2086 MoveToEx(hdc, pts[0].x - strikeoutPos * sinEsc, pts[0].y - strikeoutPos * cosEsc, &oldpt);
2087 LineTo(hdc, pts[1].x - strikeoutPos * sinEsc, pts[1].y - strikeoutPos * cosEsc);
2088 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2089 DeleteObject(SelectObject(hdc, hpen));
2094 return ret;
2098 /***********************************************************************
2099 * TextOutA (GDI32.@)
2101 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2103 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2107 /***********************************************************************
2108 * TextOutW (GDI32.@)
2110 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2112 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2116 /***********************************************************************
2117 * PolyTextOutA (GDI32.@)
2119 * See PolyTextOutW.
2121 BOOL WINAPI PolyTextOutA( HDC hdc, const POLYTEXTA *pptxt, INT cStrings )
2123 for (; cStrings>0; cStrings--, pptxt++)
2124 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2125 return FALSE;
2126 return TRUE;
2131 /***********************************************************************
2132 * PolyTextOutW (GDI32.@)
2134 * Draw several Strings
2136 * RETURNS
2137 * TRUE: Success.
2138 * FALSE: Failure.
2140 BOOL WINAPI PolyTextOutW( HDC hdc, const POLYTEXTW *pptxt, INT cStrings )
2142 for (; cStrings>0; cStrings--, pptxt++)
2143 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2144 return FALSE;
2145 return TRUE;
2149 /* FIXME: all following APIs ******************************************/
2152 /***********************************************************************
2153 * SetMapperFlags (GDI32.@)
2155 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
2157 DC *dc = get_dc_ptr( hDC );
2158 DWORD ret = 0;
2159 if(!dc) return 0;
2160 if(dc->funcs->pSetMapperFlags)
2162 ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
2163 /* FIXME: ret is just a success flag, we should return a proper value */
2165 else
2166 FIXME("(%p, 0x%08x): stub - harmless\n", hDC, dwFlag);
2167 release_dc_ptr( dc );
2168 return ret;
2171 /***********************************************************************
2172 * GetAspectRatioFilterEx (GDI32.@)
2174 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2176 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2177 return FALSE;
2181 /***********************************************************************
2182 * GetCharABCWidthsA (GDI32.@)
2184 * See GetCharABCWidthsW.
2186 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2187 LPABC abc )
2189 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
2190 LPSTR str;
2191 LPWSTR wstr;
2192 BOOL ret = TRUE;
2194 if(count <= 0) return FALSE;
2196 str = HeapAlloc(GetProcessHeap(), 0, count);
2197 for(i = 0; i < count; i++)
2198 str[i] = (BYTE)(firstChar + i);
2200 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
2202 for(i = 0; i < wlen; i++)
2204 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2206 ret = FALSE;
2207 break;
2209 abc++;
2212 HeapFree(GetProcessHeap(), 0, str);
2213 HeapFree(GetProcessHeap(), 0, wstr);
2215 return ret;
2219 /******************************************************************************
2220 * GetCharABCWidthsW [GDI32.@]
2222 * Retrieves widths of characters in range.
2224 * PARAMS
2225 * hdc [I] Handle of device context
2226 * firstChar [I] First character in range to query
2227 * lastChar [I] Last character in range to query
2228 * abc [O] Address of character-width structure
2230 * NOTES
2231 * Only works with TrueType fonts
2233 * RETURNS
2234 * Success: TRUE
2235 * Failure: FALSE
2237 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2238 LPABC abc )
2240 DC *dc = get_dc_ptr(hdc);
2241 unsigned int i;
2242 BOOL ret = FALSE;
2244 if (!dc) return FALSE;
2246 if (!abc)
2248 release_dc_ptr( dc );
2249 return FALSE;
2252 if(dc->gdiFont)
2253 ret = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
2254 else
2255 FIXME(": stub\n");
2257 if (ret)
2259 /* convert device units to logical */
2260 for( i = firstChar; i <= lastChar; i++, abc++ ) {
2261 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2262 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2263 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2265 ret = TRUE;
2268 release_dc_ptr( dc );
2269 return ret;
2273 /******************************************************************************
2274 * GetCharABCWidthsI [GDI32.@]
2276 * Retrieves widths of characters in range.
2278 * PARAMS
2279 * hdc [I] Handle of device context
2280 * firstChar [I] First glyphs in range to query
2281 * count [I] Last glyphs in range to query
2282 * pgi [i] Array of glyphs to query
2283 * abc [O] Address of character-width structure
2285 * NOTES
2286 * Only works with TrueType fonts
2288 * RETURNS
2289 * Success: TRUE
2290 * Failure: FALSE
2292 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2293 LPWORD pgi, LPABC abc)
2295 DC *dc = get_dc_ptr(hdc);
2296 unsigned int i;
2297 BOOL ret = FALSE;
2299 if (!dc) return FALSE;
2301 if (!abc)
2303 release_dc_ptr( dc );
2304 return FALSE;
2307 if(dc->gdiFont)
2308 ret = WineEngGetCharABCWidthsI( dc->gdiFont, firstChar, count, pgi, abc );
2309 else
2310 FIXME(": stub\n");
2312 if (ret)
2314 /* convert device units to logical */
2315 for( i = 0; i < count; i++, abc++ ) {
2316 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2317 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2318 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2320 ret = TRUE;
2323 release_dc_ptr( dc );
2324 return ret;
2328 /***********************************************************************
2329 * GetGlyphOutlineA (GDI32.@)
2331 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2332 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2333 LPVOID lpBuffer, const MAT2 *lpmat2 )
2335 LPWSTR p = NULL;
2336 DWORD ret;
2337 UINT c;
2339 if(!(fuFormat & GGO_GLYPH_INDEX)) {
2340 int len;
2341 char mbchs[2];
2342 if(uChar > 0xff) { /* but, 2 bytes character only */
2343 len = 2;
2344 mbchs[0] = (uChar & 0xff00) >> 8;
2345 mbchs[1] = (uChar & 0xff);
2346 } else {
2347 len = 1;
2348 mbchs[0] = (uChar & 0xff);
2350 p = FONT_mbtowc(hdc, mbchs, len, NULL, NULL);
2351 c = p[0];
2352 } else
2353 c = uChar;
2354 ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
2355 lpmat2);
2356 HeapFree(GetProcessHeap(), 0, p);
2357 return ret;
2360 /***********************************************************************
2361 * GetGlyphOutlineW (GDI32.@)
2363 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2364 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2365 LPVOID lpBuffer, const MAT2 *lpmat2 )
2367 DC *dc = get_dc_ptr(hdc);
2368 DWORD ret;
2370 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2371 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2373 if(!dc) return GDI_ERROR;
2375 if(dc->gdiFont)
2376 ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
2377 cbBuffer, lpBuffer, lpmat2);
2378 else
2379 ret = GDI_ERROR;
2381 release_dc_ptr( dc );
2382 return ret;
2386 /***********************************************************************
2387 * CreateScalableFontResourceA (GDI32.@)
2389 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2390 LPCSTR lpszResourceFile,
2391 LPCSTR lpszFontFile,
2392 LPCSTR lpszCurrentPath )
2394 LPWSTR lpszResourceFileW = NULL;
2395 LPWSTR lpszFontFileW = NULL;
2396 LPWSTR lpszCurrentPathW = NULL;
2397 int len;
2398 BOOL ret;
2400 if (lpszResourceFile)
2402 len = MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, NULL, 0);
2403 lpszResourceFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2404 MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, lpszResourceFileW, len);
2407 if (lpszFontFile)
2409 len = MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, NULL, 0);
2410 lpszFontFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2411 MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, lpszFontFileW, len);
2414 if (lpszCurrentPath)
2416 len = MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, NULL, 0);
2417 lpszCurrentPathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2418 MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, lpszCurrentPathW, len);
2421 ret = CreateScalableFontResourceW(fHidden, lpszResourceFileW,
2422 lpszFontFileW, lpszCurrentPathW);
2424 HeapFree(GetProcessHeap(), 0, lpszResourceFileW);
2425 HeapFree(GetProcessHeap(), 0, lpszFontFileW);
2426 HeapFree(GetProcessHeap(), 0, lpszCurrentPathW);
2428 return ret;
2431 /***********************************************************************
2432 * CreateScalableFontResourceW (GDI32.@)
2434 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2435 LPCWSTR lpszResourceFile,
2436 LPCWSTR lpszFontFile,
2437 LPCWSTR lpszCurrentPath )
2439 HANDLE f;
2440 FIXME("(%d,%s,%s,%s): stub\n",
2441 fHidden, debugstr_w(lpszResourceFile), debugstr_w(lpszFontFile),
2442 debugstr_w(lpszCurrentPath) );
2444 /* fHidden=1 - only visible for the calling app, read-only, not
2445 * enumerated with EnumFonts/EnumFontFamilies
2446 * lpszCurrentPath can be NULL
2449 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2450 if ((f = CreateFileW(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2451 CloseHandle(f);
2452 SetLastError(ERROR_FILE_EXISTS);
2453 return FALSE;
2455 return FALSE; /* create failed */
2458 /*************************************************************************
2459 * GetKerningPairsA (GDI32.@)
2461 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2462 LPKERNINGPAIR kern_pairA )
2464 INT charset;
2465 CHARSETINFO csi;
2466 CPINFO cpi;
2467 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2468 KERNINGPAIR *kern_pairW;
2470 if (!cPairs && kern_pairA)
2472 SetLastError(ERROR_INVALID_PARAMETER);
2473 return 0;
2476 charset = GetTextCharset(hDC);
2477 if (!TranslateCharsetInfo(ULongToPtr(charset), &csi, TCI_SRCCHARSET))
2479 FIXME("Can't find codepage for charset %d\n", charset);
2480 return 0;
2482 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2483 * to fail on an invalid character for CP_SYMBOL.
2485 cpi.DefaultChar[0] = 0;
2486 if (csi.ciACP != CP_SYMBOL && !GetCPInfo(csi.ciACP, &cpi))
2488 FIXME("Can't find codepage %u info\n", csi.ciACP);
2489 return 0;
2491 TRACE("charset %d => codepage %u\n", charset, csi.ciACP);
2493 total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2494 if (!total_kern_pairs) return 0;
2496 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2497 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2499 for (i = 0; i < total_kern_pairs; i++)
2501 char first, second;
2503 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2504 continue;
2506 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2507 continue;
2509 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2510 continue;
2512 if (kern_pairA)
2514 if (kern_pairs_copied >= cPairs) break;
2516 kern_pairA->wFirst = (BYTE)first;
2517 kern_pairA->wSecond = (BYTE)second;
2518 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2519 kern_pairA++;
2521 kern_pairs_copied++;
2524 HeapFree(GetProcessHeap(), 0, kern_pairW);
2526 return kern_pairs_copied;
2529 /*************************************************************************
2530 * GetKerningPairsW (GDI32.@)
2532 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2533 LPKERNINGPAIR lpKerningPairs )
2535 DC *dc;
2536 DWORD ret = 0;
2538 TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2540 if (!cPairs && lpKerningPairs)
2542 SetLastError(ERROR_INVALID_PARAMETER);
2543 return 0;
2546 dc = get_dc_ptr(hDC);
2547 if (!dc) return 0;
2549 if (dc->gdiFont)
2550 ret = WineEngGetKerningPairs(dc->gdiFont, cPairs, lpKerningPairs);
2552 release_dc_ptr( dc );
2553 return ret;
2556 /*************************************************************************
2557 * TranslateCharsetInfo [GDI32.@]
2559 * Fills a CHARSETINFO structure for a character set, code page, or
2560 * font. This allows making the correspondence between different labels
2561 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2562 * of the same encoding.
2564 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2565 * only one codepage should be set in *lpSrc.
2567 * RETURNS
2568 * TRUE on success, FALSE on failure.
2571 BOOL WINAPI TranslateCharsetInfo(
2572 LPDWORD lpSrc, /* [in]
2573 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2574 if flags == TCI_SRCCHARSET: a character set value
2575 if flags == TCI_SRCCODEPAGE: a code page value
2577 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2578 DWORD flags /* [in] determines interpretation of lpSrc */)
2580 int index = 0;
2581 switch (flags) {
2582 case TCI_SRCFONTSIG:
2583 while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
2584 break;
2585 case TCI_SRCCODEPAGE:
2586 while (PtrToUlong(lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
2587 break;
2588 case TCI_SRCCHARSET:
2589 while (PtrToUlong(lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
2590 break;
2591 default:
2592 return FALSE;
2594 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2595 *lpCs = FONT_tci[index];
2596 return TRUE;
2599 /*************************************************************************
2600 * GetFontLanguageInfo (GDI32.@)
2602 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2604 FONTSIGNATURE fontsig;
2605 static const DWORD GCP_DBCS_MASK=0x003F0000,
2606 GCP_DIACRITIC_MASK=0x00000000,
2607 FLI_GLYPHS_MASK=0x00000000,
2608 GCP_GLYPHSHAPE_MASK=0x00000040,
2609 GCP_KASHIDA_MASK=0x00000000,
2610 GCP_LIGATE_MASK=0x00000000,
2611 GCP_USEKERNING_MASK=0x00000000,
2612 GCP_REORDER_MASK=0x00000060;
2614 DWORD result=0;
2616 GetTextCharsetInfo( hdc, &fontsig, 0 );
2617 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2619 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2620 result|=GCP_DBCS;
2622 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2623 result|=GCP_DIACRITIC;
2625 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2626 result|=FLI_GLYPHS;
2628 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2629 result|=GCP_GLYPHSHAPE;
2631 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2632 result|=GCP_KASHIDA;
2634 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2635 result|=GCP_LIGATE;
2637 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2638 result|=GCP_USEKERNING;
2640 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2641 if( GetTextAlign( hdc) & TA_RTLREADING )
2642 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2643 result|=GCP_REORDER;
2645 return result;
2649 /*************************************************************************
2650 * GetFontData [GDI32.@]
2652 * Retrieve data for TrueType font.
2654 * RETURNS
2656 * success: Number of bytes returned
2657 * failure: GDI_ERROR
2659 * NOTES
2661 * Calls SetLastError()
2664 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2665 LPVOID buffer, DWORD length)
2667 DC *dc = get_dc_ptr(hdc);
2668 DWORD ret = GDI_ERROR;
2670 if(!dc) return GDI_ERROR;
2672 if(dc->gdiFont)
2673 ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2675 release_dc_ptr( dc );
2676 return ret;
2679 /*************************************************************************
2680 * GetGlyphIndicesA [GDI32.@]
2682 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2683 LPWORD pgi, DWORD flags)
2685 DWORD ret;
2686 WCHAR *lpstrW;
2687 INT countW;
2689 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2690 hdc, debugstr_an(lpstr, count), count, pgi, flags);
2692 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2693 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2694 HeapFree(GetProcessHeap(), 0, lpstrW);
2696 return ret;
2699 /*************************************************************************
2700 * GetGlyphIndicesW [GDI32.@]
2702 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2703 LPWORD pgi, DWORD flags)
2705 DC *dc = get_dc_ptr(hdc);
2706 DWORD ret = GDI_ERROR;
2708 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2709 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2711 if(!dc) return GDI_ERROR;
2713 if(dc->gdiFont)
2714 ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2716 release_dc_ptr( dc );
2717 return ret;
2720 /*************************************************************************
2721 * GetCharacterPlacementA [GDI32.@]
2723 * See GetCharacterPlacementW.
2725 * NOTES:
2726 * the web browser control of ie4 calls this with dwFlags=0
2728 DWORD WINAPI
2729 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2730 INT nMaxExtent, GCP_RESULTSA *lpResults,
2731 DWORD dwFlags)
2733 WCHAR *lpStringW;
2734 INT uCountW;
2735 GCP_RESULTSW resultsW;
2736 DWORD ret;
2737 UINT font_cp;
2739 TRACE("%s, %d, %d, 0x%08x\n",
2740 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2742 /* both structs are equal in size */
2743 memcpy(&resultsW, lpResults, sizeof(resultsW));
2745 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2746 if(lpResults->lpOutString)
2747 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2749 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2751 lpResults->nGlyphs = resultsW.nGlyphs;
2752 lpResults->nMaxFit = resultsW.nMaxFit;
2754 if(lpResults->lpOutString) {
2755 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2756 lpResults->lpOutString, uCount, NULL, NULL );
2759 HeapFree(GetProcessHeap(), 0, lpStringW);
2760 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2762 return ret;
2765 /*************************************************************************
2766 * GetCharacterPlacementW [GDI32.@]
2768 * Retrieve information about a string. This includes the width, reordering,
2769 * Glyphing and so on.
2771 * RETURNS
2773 * The width and height of the string if successful, 0 if failed.
2775 * BUGS
2777 * All flags except GCP_REORDER are not yet implemented.
2778 * Reordering is not 100% compliant to the Windows BiDi method.
2779 * Caret positioning is not yet implemented for BiDi.
2780 * Classes are not yet implemented.
2783 DWORD WINAPI
2784 GetCharacterPlacementW(
2785 HDC hdc, /* [in] Device context for which the rendering is to be done */
2786 LPCWSTR lpString, /* [in] The string for which information is to be returned */
2787 INT uCount, /* [in] Number of WORDS in string. */
2788 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
2789 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2790 DWORD dwFlags /* [in] Flags specifying how to process the string */
2793 DWORD ret=0;
2794 SIZE size;
2795 UINT i, nSet;
2797 TRACE("%s, %d, %d, 0x%08x\n",
2798 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2800 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2801 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2802 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2803 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2804 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2806 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08x ignored\n", dwFlags);
2807 if(lpResults->lpClass) FIXME("classes not implemented\n");
2808 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2809 FIXME("Caret positions for complex scripts not implemented\n");
2811 nSet = (UINT)uCount;
2812 if(nSet > lpResults->nGlyphs)
2813 nSet = lpResults->nGlyphs;
2815 /* return number of initialized fields */
2816 lpResults->nGlyphs = nSet;
2818 if((dwFlags&GCP_REORDER)==0 )
2820 /* Treat the case where no special handling was requested in a fastpath way */
2821 /* copy will do if the GCP_REORDER flag is not set */
2822 if(lpResults->lpOutString)
2823 memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
2825 if(lpResults->lpOrder)
2827 for(i = 0; i < nSet; i++)
2828 lpResults->lpOrder[i] = i;
2830 } else
2832 BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
2833 nSet, lpResults->lpOrder );
2836 /* FIXME: Will use the placement chars */
2837 if (lpResults->lpDx)
2839 int c;
2840 for (i = 0; i < nSet; i++)
2842 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
2843 lpResults->lpDx[i]= c;
2847 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
2849 int pos = 0;
2851 lpResults->lpCaretPos[0] = 0;
2852 for (i = 1; i < nSet; i++)
2853 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
2854 lpResults->lpCaretPos[i] = (pos += size.cx);
2857 if(lpResults->lpGlyphs)
2858 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
2860 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
2861 ret = MAKELONG(size.cx, size.cy);
2863 return ret;
2866 /*************************************************************************
2867 * GetCharABCWidthsFloatA [GDI32.@]
2869 * See GetCharABCWidthsFloatW.
2871 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
2873 INT i, wlen, count = (INT)(last - first + 1);
2874 LPSTR str;
2875 LPWSTR wstr;
2876 BOOL ret = TRUE;
2878 if (count <= 0) return FALSE;
2880 str = HeapAlloc(GetProcessHeap(), 0, count);
2882 for(i = 0; i < count; i++)
2883 str[i] = (BYTE)(first + i);
2885 wstr = FONT_mbtowc( hdc, str, count, &wlen, NULL );
2887 for (i = 0; i < wlen; i++)
2889 if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
2891 ret = FALSE;
2892 break;
2894 abcf++;
2897 HeapFree( GetProcessHeap(), 0, str );
2898 HeapFree( GetProcessHeap(), 0, wstr );
2900 return ret;
2903 /*************************************************************************
2904 * GetCharABCWidthsFloatW [GDI32.@]
2906 * Retrieves widths of a range of characters.
2908 * PARAMS
2909 * hdc [I] Handle to device context.
2910 * first [I] First character in range to query.
2911 * last [I] Last character in range to query.
2912 * abcf [O] Array of LPABCFLOAT structures.
2914 * RETURNS
2915 * Success: TRUE
2916 * Failure: FALSE
2918 * BUGS
2919 * Only works with TrueType fonts. It also doesn't return real
2920 * floats but converted integers because it's implemented on
2921 * top of GetCharABCWidthsW.
2923 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
2925 ABC *abc, *abc_base;
2926 unsigned int i, size = sizeof(ABC) * (last - first + 1);
2927 BOOL ret;
2929 TRACE("%p, %d, %d, %p - partial stub\n", hdc, first, last, abcf);
2931 abc = abc_base = HeapAlloc( GetProcessHeap(), 0, size );
2932 if (!abc) return FALSE;
2934 ret = GetCharABCWidthsW( hdc, first, last, abc );
2935 if (ret)
2937 for (i = first; i <= last; i++, abc++, abcf++)
2939 abcf->abcfA = abc->abcA;
2940 abcf->abcfB = abc->abcB;
2941 abcf->abcfC = abc->abcC;
2944 HeapFree( GetProcessHeap(), 0, abc_base );
2945 return ret;
2948 /*************************************************************************
2949 * GetCharWidthFloatA [GDI32.@]
2951 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
2952 UINT iLastChar, PFLOAT pxBuffer)
2954 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
2955 return 0;
2958 /*************************************************************************
2959 * GetCharWidthFloatW [GDI32.@]
2961 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
2962 UINT iLastChar, PFLOAT pxBuffer)
2964 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
2965 return 0;
2969 /***********************************************************************
2971 * Font Resource API *
2973 ***********************************************************************/
2975 /***********************************************************************
2976 * AddFontResourceA (GDI32.@)
2978 INT WINAPI AddFontResourceA( LPCSTR str )
2980 return AddFontResourceExA( str, 0, NULL);
2983 /***********************************************************************
2984 * AddFontResourceW (GDI32.@)
2986 INT WINAPI AddFontResourceW( LPCWSTR str )
2988 return AddFontResourceExW(str, 0, NULL);
2992 /***********************************************************************
2993 * AddFontResourceExA (GDI32.@)
2995 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
2997 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
2998 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2999 INT ret;
3001 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3002 ret = AddFontResourceExW(strW, fl, pdv);
3003 HeapFree(GetProcessHeap(), 0, strW);
3004 return ret;
3007 static BOOL CALLBACK load_enumed_resource(HMODULE hModule, LPCWSTR type, LPWSTR name, LONG_PTR lParam)
3009 HRSRC rsrc = FindResourceW(hModule, name, type);
3010 HGLOBAL hMem = LoadResource(hModule, rsrc);
3011 LPVOID *pMem = LockResource(hMem);
3012 int *num_total = (int *)lParam;
3013 DWORD num_in_res;
3015 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type));
3016 if (!AddFontMemResourceEx(pMem, SizeofResource(hModule, rsrc), NULL, &num_in_res))
3018 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule, hMem);
3019 return FALSE;
3022 *num_total += num_in_res;
3023 return TRUE;
3026 /***********************************************************************
3027 * AddFontResourceExW (GDI32.@)
3029 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3031 int ret = WineEngAddFontResourceEx(str, fl, pdv);
3032 if (ret == 0)
3034 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3035 HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
3036 if (hModule != NULL)
3038 int num_resources = 0;
3039 LPWSTR rt_font = (LPWSTR)((ULONG_PTR)8); /* we don't want to include winuser.h */
3041 TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3042 wine_dbgstr_w(str));
3043 if (EnumResourceNamesW(hModule, rt_font, load_enumed_resource, (LONG_PTR)&num_resources))
3044 ret = num_resources;
3045 FreeLibrary(hModule);
3048 return ret;
3051 /***********************************************************************
3052 * RemoveFontResourceA (GDI32.@)
3054 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3056 return RemoveFontResourceExA(str, 0, 0);
3059 /***********************************************************************
3060 * RemoveFontResourceW (GDI32.@)
3062 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3064 return RemoveFontResourceExW(str, 0, 0);
3067 /***********************************************************************
3068 * AddFontMemResourceEx (GDI32.@)
3070 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3072 return WineEngAddFontMemResourceEx(pbFont, cbFont, pdv, pcFonts);
3075 /***********************************************************************
3076 * RemoveFontMemResourceEx (GDI32.@)
3078 BOOL WINAPI RemoveFontMemResourceEx( HANDLE fh )
3080 FIXME("(%p) stub\n", fh);
3081 return TRUE;
3084 /***********************************************************************
3085 * RemoveFontResourceExA (GDI32.@)
3087 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3089 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3090 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3091 INT ret;
3093 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3094 ret = RemoveFontResourceExW(strW, fl, pdv);
3095 HeapFree(GetProcessHeap(), 0, strW);
3096 return ret;
3099 /***********************************************************************
3100 * RemoveFontResourceExW (GDI32.@)
3102 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3104 return WineEngRemoveFontResourceEx(str, fl, pdv);
3107 /***********************************************************************
3108 * GetTextCharset (GDI32.@)
3110 UINT WINAPI GetTextCharset(HDC hdc)
3112 /* MSDN docs say this is equivalent */
3113 return GetTextCharsetInfo(hdc, NULL, 0);
3116 /***********************************************************************
3117 * GetTextCharsetInfo (GDI32.@)
3119 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3121 UINT ret = DEFAULT_CHARSET;
3122 DC *dc = get_dc_ptr(hdc);
3124 if (dc)
3126 if (dc->gdiFont)
3127 ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
3129 release_dc_ptr( dc );
3132 if (ret == DEFAULT_CHARSET && fs)
3133 memset(fs, 0, sizeof(FONTSIGNATURE));
3134 return ret;
3137 /***********************************************************************
3138 * GdiGetCharDimensions (GDI32.@)
3140 * Gets the average width of the characters in the English alphabet.
3142 * PARAMS
3143 * hdc [I] Handle to the device context to measure on.
3144 * lptm [O] Pointer to memory to store the text metrics into.
3145 * height [O] On exit, the maximum height of characters in the English alphabet.
3147 * RETURNS
3148 * The average width of characters in the English alphabet.
3150 * NOTES
3151 * This function is used by the dialog manager to get the size of a dialog
3152 * unit. It should also be used by other pieces of code that need to know
3153 * the size of a dialog unit in logical units without having access to the
3154 * window handle of the dialog.
3155 * Windows caches the font metrics from this function, but we don't and
3156 * there doesn't appear to be an immediate advantage to do so.
3158 * SEE ALSO
3159 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3161 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3163 SIZE sz;
3164 static const WCHAR alphabet[] = {
3165 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3166 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3167 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3169 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3171 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3173 if (height) *height = sz.cy;
3174 return (sz.cx / 26 + 1) / 2;
3177 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3179 FIXME("(%d): stub\n", fEnableEUDC);
3180 return FALSE;
3183 /***********************************************************************
3184 * GetCharWidthI (GDI32.@)
3186 * Retrieve widths of characters.
3188 * PARAMS
3189 * hdc [I] Handle to a device context.
3190 * first [I] First glyph in range to query.
3191 * count [I] Number of glyph indices to query.
3192 * glyphs [I] Array of glyphs to query.
3193 * buffer [O] Buffer to receive character widths.
3195 * NOTES
3196 * Only works with TrueType fonts.
3198 * RETURNS
3199 * Success: TRUE
3200 * Failure: FALSE
3202 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3204 ABC *abc;
3205 unsigned int i;
3207 TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3209 if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3210 return FALSE;
3212 if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3214 HeapFree(GetProcessHeap(), 0, abc);
3215 return FALSE;
3218 for (i = 0; i < count; i++)
3219 buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3221 HeapFree(GetProcessHeap(), 0, abc);
3222 return TRUE;
3225 /***********************************************************************
3226 * GetFontUnicodeRanges (GDI32.@)
3228 * Retrieve a list of supported Unicode characters in a font.
3230 * PARAMS
3231 * hdc [I] Handle to a device context.
3232 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3234 * RETURNS
3235 * Success: Number of bytes written to the buffer pointed to by lpgs.
3236 * Failure: 0
3239 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3241 DWORD ret = 0;
3242 DC *dc = get_dc_ptr(hdc);
3244 TRACE("(%p, %p)\n", hdc, lpgs);
3246 if (!dc) return 0;
3248 if (dc->gdiFont) ret = WineEngGetFontUnicodeRanges(dc->gdiFont, lpgs);
3249 release_dc_ptr(dc);
3250 return ret;
3254 /*************************************************************
3255 * FontIsLinked (GDI32.@)
3257 BOOL WINAPI FontIsLinked(HDC hdc)
3259 DC *dc = get_dc_ptr(hdc);
3260 BOOL ret = FALSE;
3262 if (!dc) return FALSE;
3263 if (dc->gdiFont) ret = WineEngFontIsLinked(dc->gdiFont);
3264 release_dc_ptr(dc);
3265 TRACE("returning %d\n", ret);
3266 return ret;
3269 /*************************************************************
3270 * GdiRealizationInfo (GDI32.@)
3272 * Returns a structure that contains some font information.
3274 BOOL WINAPI GdiRealizationInfo(HDC hdc, realization_info_t *info)
3276 DC *dc = get_dc_ptr(hdc);
3277 BOOL ret = FALSE;
3279 if (!dc) return FALSE;
3280 if (dc->gdiFont) ret = WineEngRealizationInfo(dc->gdiFont, info);
3281 release_dc_ptr(dc);
3283 return ret;