push d1f5df181c120dbe494f7c89b454752c2e0dcc04
[wine/hacks.git] / dlls / gdi32 / font.c
blob205224bd8fedf8a0fc49fed61ee0cd53a95408bf
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 (!lpmat2) return GDI_ERROR;
2341 if(!(fuFormat & GGO_GLYPH_INDEX)) {
2342 int len;
2343 char mbchs[2];
2344 if(uChar > 0xff) { /* but, 2 bytes character only */
2345 len = 2;
2346 mbchs[0] = (uChar & 0xff00) >> 8;
2347 mbchs[1] = (uChar & 0xff);
2348 } else {
2349 len = 1;
2350 mbchs[0] = (uChar & 0xff);
2352 p = FONT_mbtowc(hdc, mbchs, len, NULL, NULL);
2353 c = p[0];
2354 } else
2355 c = uChar;
2356 ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
2357 lpmat2);
2358 HeapFree(GetProcessHeap(), 0, p);
2359 return ret;
2362 /***********************************************************************
2363 * GetGlyphOutlineW (GDI32.@)
2365 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2366 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2367 LPVOID lpBuffer, const MAT2 *lpmat2 )
2369 DC *dc;
2370 DWORD ret;
2372 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2373 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2375 if (!lpmat2) return GDI_ERROR;
2377 dc = get_dc_ptr(hdc);
2378 if(!dc) return GDI_ERROR;
2380 if(dc->gdiFont)
2381 ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
2382 cbBuffer, lpBuffer, lpmat2);
2383 else
2384 ret = GDI_ERROR;
2386 release_dc_ptr( dc );
2387 return ret;
2391 /***********************************************************************
2392 * CreateScalableFontResourceA (GDI32.@)
2394 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2395 LPCSTR lpszResourceFile,
2396 LPCSTR lpszFontFile,
2397 LPCSTR lpszCurrentPath )
2399 LPWSTR lpszResourceFileW = NULL;
2400 LPWSTR lpszFontFileW = NULL;
2401 LPWSTR lpszCurrentPathW = NULL;
2402 int len;
2403 BOOL ret;
2405 if (lpszResourceFile)
2407 len = MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, NULL, 0);
2408 lpszResourceFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2409 MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, lpszResourceFileW, len);
2412 if (lpszFontFile)
2414 len = MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, NULL, 0);
2415 lpszFontFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2416 MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, lpszFontFileW, len);
2419 if (lpszCurrentPath)
2421 len = MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, NULL, 0);
2422 lpszCurrentPathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2423 MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, lpszCurrentPathW, len);
2426 ret = CreateScalableFontResourceW(fHidden, lpszResourceFileW,
2427 lpszFontFileW, lpszCurrentPathW);
2429 HeapFree(GetProcessHeap(), 0, lpszResourceFileW);
2430 HeapFree(GetProcessHeap(), 0, lpszFontFileW);
2431 HeapFree(GetProcessHeap(), 0, lpszCurrentPathW);
2433 return ret;
2436 /***********************************************************************
2437 * CreateScalableFontResourceW (GDI32.@)
2439 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2440 LPCWSTR lpszResourceFile,
2441 LPCWSTR lpszFontFile,
2442 LPCWSTR lpszCurrentPath )
2444 HANDLE f;
2445 FIXME("(%d,%s,%s,%s): stub\n",
2446 fHidden, debugstr_w(lpszResourceFile), debugstr_w(lpszFontFile),
2447 debugstr_w(lpszCurrentPath) );
2449 /* fHidden=1 - only visible for the calling app, read-only, not
2450 * enumerated with EnumFonts/EnumFontFamilies
2451 * lpszCurrentPath can be NULL
2454 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2455 if ((f = CreateFileW(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2456 CloseHandle(f);
2457 SetLastError(ERROR_FILE_EXISTS);
2458 return FALSE;
2460 return FALSE; /* create failed */
2463 /*************************************************************************
2464 * GetKerningPairsA (GDI32.@)
2466 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2467 LPKERNINGPAIR kern_pairA )
2469 INT charset;
2470 CHARSETINFO csi;
2471 CPINFO cpi;
2472 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2473 KERNINGPAIR *kern_pairW;
2475 if (!cPairs && kern_pairA)
2477 SetLastError(ERROR_INVALID_PARAMETER);
2478 return 0;
2481 charset = GetTextCharset(hDC);
2482 if (!TranslateCharsetInfo(ULongToPtr(charset), &csi, TCI_SRCCHARSET))
2484 FIXME("Can't find codepage for charset %d\n", charset);
2485 return 0;
2487 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2488 * to fail on an invalid character for CP_SYMBOL.
2490 cpi.DefaultChar[0] = 0;
2491 if (csi.ciACP != CP_SYMBOL && !GetCPInfo(csi.ciACP, &cpi))
2493 FIXME("Can't find codepage %u info\n", csi.ciACP);
2494 return 0;
2496 TRACE("charset %d => codepage %u\n", charset, csi.ciACP);
2498 total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2499 if (!total_kern_pairs) return 0;
2501 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2502 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2504 for (i = 0; i < total_kern_pairs; i++)
2506 char first, second;
2508 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2509 continue;
2511 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2512 continue;
2514 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2515 continue;
2517 if (kern_pairA)
2519 if (kern_pairs_copied >= cPairs) break;
2521 kern_pairA->wFirst = (BYTE)first;
2522 kern_pairA->wSecond = (BYTE)second;
2523 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2524 kern_pairA++;
2526 kern_pairs_copied++;
2529 HeapFree(GetProcessHeap(), 0, kern_pairW);
2531 return kern_pairs_copied;
2534 /*************************************************************************
2535 * GetKerningPairsW (GDI32.@)
2537 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2538 LPKERNINGPAIR lpKerningPairs )
2540 DC *dc;
2541 DWORD ret = 0;
2543 TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2545 if (!cPairs && lpKerningPairs)
2547 SetLastError(ERROR_INVALID_PARAMETER);
2548 return 0;
2551 dc = get_dc_ptr(hDC);
2552 if (!dc) return 0;
2554 if (dc->gdiFont)
2555 ret = WineEngGetKerningPairs(dc->gdiFont, cPairs, lpKerningPairs);
2557 release_dc_ptr( dc );
2558 return ret;
2561 /*************************************************************************
2562 * TranslateCharsetInfo [GDI32.@]
2564 * Fills a CHARSETINFO structure for a character set, code page, or
2565 * font. This allows making the correspondence between different labels
2566 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2567 * of the same encoding.
2569 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2570 * only one codepage should be set in *lpSrc.
2572 * RETURNS
2573 * TRUE on success, FALSE on failure.
2576 BOOL WINAPI TranslateCharsetInfo(
2577 LPDWORD lpSrc, /* [in]
2578 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2579 if flags == TCI_SRCCHARSET: a character set value
2580 if flags == TCI_SRCCODEPAGE: a code page value
2582 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2583 DWORD flags /* [in] determines interpretation of lpSrc */)
2585 int index = 0;
2586 switch (flags) {
2587 case TCI_SRCFONTSIG:
2588 while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
2589 break;
2590 case TCI_SRCCODEPAGE:
2591 while (PtrToUlong(lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
2592 break;
2593 case TCI_SRCCHARSET:
2594 while (PtrToUlong(lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
2595 break;
2596 default:
2597 return FALSE;
2599 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2600 *lpCs = FONT_tci[index];
2601 return TRUE;
2604 /*************************************************************************
2605 * GetFontLanguageInfo (GDI32.@)
2607 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2609 FONTSIGNATURE fontsig;
2610 static const DWORD GCP_DBCS_MASK=0x003F0000,
2611 GCP_DIACRITIC_MASK=0x00000000,
2612 FLI_GLYPHS_MASK=0x00000000,
2613 GCP_GLYPHSHAPE_MASK=0x00000040,
2614 GCP_KASHIDA_MASK=0x00000000,
2615 GCP_LIGATE_MASK=0x00000000,
2616 GCP_USEKERNING_MASK=0x00000000,
2617 GCP_REORDER_MASK=0x00000060;
2619 DWORD result=0;
2621 GetTextCharsetInfo( hdc, &fontsig, 0 );
2622 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2624 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2625 result|=GCP_DBCS;
2627 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2628 result|=GCP_DIACRITIC;
2630 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2631 result|=FLI_GLYPHS;
2633 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2634 result|=GCP_GLYPHSHAPE;
2636 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2637 result|=GCP_KASHIDA;
2639 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2640 result|=GCP_LIGATE;
2642 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2643 result|=GCP_USEKERNING;
2645 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2646 if( GetTextAlign( hdc) & TA_RTLREADING )
2647 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2648 result|=GCP_REORDER;
2650 return result;
2654 /*************************************************************************
2655 * GetFontData [GDI32.@]
2657 * Retrieve data for TrueType font.
2659 * RETURNS
2661 * success: Number of bytes returned
2662 * failure: GDI_ERROR
2664 * NOTES
2666 * Calls SetLastError()
2669 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2670 LPVOID buffer, DWORD length)
2672 DC *dc = get_dc_ptr(hdc);
2673 DWORD ret = GDI_ERROR;
2675 if(!dc) return GDI_ERROR;
2677 if(dc->gdiFont)
2678 ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2680 release_dc_ptr( dc );
2681 return ret;
2684 /*************************************************************************
2685 * GetGlyphIndicesA [GDI32.@]
2687 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2688 LPWORD pgi, DWORD flags)
2690 DWORD ret;
2691 WCHAR *lpstrW;
2692 INT countW;
2694 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2695 hdc, debugstr_an(lpstr, count), count, pgi, flags);
2697 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2698 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2699 HeapFree(GetProcessHeap(), 0, lpstrW);
2701 return ret;
2704 /*************************************************************************
2705 * GetGlyphIndicesW [GDI32.@]
2707 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2708 LPWORD pgi, DWORD flags)
2710 DC *dc = get_dc_ptr(hdc);
2711 DWORD ret = GDI_ERROR;
2713 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2714 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2716 if(!dc) return GDI_ERROR;
2718 if(dc->gdiFont)
2719 ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2721 release_dc_ptr( dc );
2722 return ret;
2725 /*************************************************************************
2726 * GetCharacterPlacementA [GDI32.@]
2728 * See GetCharacterPlacementW.
2730 * NOTES:
2731 * the web browser control of ie4 calls this with dwFlags=0
2733 DWORD WINAPI
2734 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2735 INT nMaxExtent, GCP_RESULTSA *lpResults,
2736 DWORD dwFlags)
2738 WCHAR *lpStringW;
2739 INT uCountW;
2740 GCP_RESULTSW resultsW;
2741 DWORD ret;
2742 UINT font_cp;
2744 TRACE("%s, %d, %d, 0x%08x\n",
2745 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2747 /* both structs are equal in size */
2748 memcpy(&resultsW, lpResults, sizeof(resultsW));
2750 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2751 if(lpResults->lpOutString)
2752 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2754 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2756 lpResults->nGlyphs = resultsW.nGlyphs;
2757 lpResults->nMaxFit = resultsW.nMaxFit;
2759 if(lpResults->lpOutString) {
2760 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2761 lpResults->lpOutString, uCount, NULL, NULL );
2764 HeapFree(GetProcessHeap(), 0, lpStringW);
2765 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2767 return ret;
2770 /*************************************************************************
2771 * GetCharacterPlacementW [GDI32.@]
2773 * Retrieve information about a string. This includes the width, reordering,
2774 * Glyphing and so on.
2776 * RETURNS
2778 * The width and height of the string if successful, 0 if failed.
2780 * BUGS
2782 * All flags except GCP_REORDER are not yet implemented.
2783 * Reordering is not 100% compliant to the Windows BiDi method.
2784 * Caret positioning is not yet implemented for BiDi.
2785 * Classes are not yet implemented.
2788 DWORD WINAPI
2789 GetCharacterPlacementW(
2790 HDC hdc, /* [in] Device context for which the rendering is to be done */
2791 LPCWSTR lpString, /* [in] The string for which information is to be returned */
2792 INT uCount, /* [in] Number of WORDS in string. */
2793 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
2794 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2795 DWORD dwFlags /* [in] Flags specifying how to process the string */
2798 DWORD ret=0;
2799 SIZE size;
2800 UINT i, nSet;
2802 TRACE("%s, %d, %d, 0x%08x\n",
2803 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2805 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2806 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2807 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2808 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2809 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2811 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08x ignored\n", dwFlags);
2812 if(lpResults->lpClass) FIXME("classes not implemented\n");
2813 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2814 FIXME("Caret positions for complex scripts not implemented\n");
2816 nSet = (UINT)uCount;
2817 if(nSet > lpResults->nGlyphs)
2818 nSet = lpResults->nGlyphs;
2820 /* return number of initialized fields */
2821 lpResults->nGlyphs = nSet;
2823 if((dwFlags&GCP_REORDER)==0 )
2825 /* Treat the case where no special handling was requested in a fastpath way */
2826 /* copy will do if the GCP_REORDER flag is not set */
2827 if(lpResults->lpOutString)
2828 memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
2830 if(lpResults->lpOrder)
2832 for(i = 0; i < nSet; i++)
2833 lpResults->lpOrder[i] = i;
2835 } else
2837 BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
2838 nSet, lpResults->lpOrder );
2841 /* FIXME: Will use the placement chars */
2842 if (lpResults->lpDx)
2844 int c;
2845 for (i = 0; i < nSet; i++)
2847 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
2848 lpResults->lpDx[i]= c;
2852 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
2854 int pos = 0;
2856 lpResults->lpCaretPos[0] = 0;
2857 for (i = 1; i < nSet; i++)
2858 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
2859 lpResults->lpCaretPos[i] = (pos += size.cx);
2862 if(lpResults->lpGlyphs)
2863 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
2865 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
2866 ret = MAKELONG(size.cx, size.cy);
2868 return ret;
2871 /*************************************************************************
2872 * GetCharABCWidthsFloatA [GDI32.@]
2874 * See GetCharABCWidthsFloatW.
2876 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
2878 INT i, wlen, count = (INT)(last - first + 1);
2879 LPSTR str;
2880 LPWSTR wstr;
2881 BOOL ret = TRUE;
2883 if (count <= 0) return FALSE;
2885 str = HeapAlloc(GetProcessHeap(), 0, count);
2887 for(i = 0; i < count; i++)
2888 str[i] = (BYTE)(first + i);
2890 wstr = FONT_mbtowc( hdc, str, count, &wlen, NULL );
2892 for (i = 0; i < wlen; i++)
2894 if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
2896 ret = FALSE;
2897 break;
2899 abcf++;
2902 HeapFree( GetProcessHeap(), 0, str );
2903 HeapFree( GetProcessHeap(), 0, wstr );
2905 return ret;
2908 /*************************************************************************
2909 * GetCharABCWidthsFloatW [GDI32.@]
2911 * Retrieves widths of a range of characters.
2913 * PARAMS
2914 * hdc [I] Handle to device context.
2915 * first [I] First character in range to query.
2916 * last [I] Last character in range to query.
2917 * abcf [O] Array of LPABCFLOAT structures.
2919 * RETURNS
2920 * Success: TRUE
2921 * Failure: FALSE
2923 * BUGS
2924 * Only works with TrueType fonts. It also doesn't return real
2925 * floats but converted integers because it's implemented on
2926 * top of GetCharABCWidthsW.
2928 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
2930 ABC *abc, *abc_base;
2931 unsigned int i, size = sizeof(ABC) * (last - first + 1);
2932 BOOL ret;
2934 TRACE("%p, %d, %d, %p - partial stub\n", hdc, first, last, abcf);
2936 abc = abc_base = HeapAlloc( GetProcessHeap(), 0, size );
2937 if (!abc) return FALSE;
2939 ret = GetCharABCWidthsW( hdc, first, last, abc );
2940 if (ret)
2942 for (i = first; i <= last; i++, abc++, abcf++)
2944 abcf->abcfA = abc->abcA;
2945 abcf->abcfB = abc->abcB;
2946 abcf->abcfC = abc->abcC;
2949 HeapFree( GetProcessHeap(), 0, abc_base );
2950 return ret;
2953 /*************************************************************************
2954 * GetCharWidthFloatA [GDI32.@]
2956 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
2957 UINT iLastChar, PFLOAT pxBuffer)
2959 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
2960 return 0;
2963 /*************************************************************************
2964 * GetCharWidthFloatW [GDI32.@]
2966 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
2967 UINT iLastChar, PFLOAT pxBuffer)
2969 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
2970 return 0;
2974 /***********************************************************************
2976 * Font Resource API *
2978 ***********************************************************************/
2980 /***********************************************************************
2981 * AddFontResourceA (GDI32.@)
2983 INT WINAPI AddFontResourceA( LPCSTR str )
2985 return AddFontResourceExA( str, 0, NULL);
2988 /***********************************************************************
2989 * AddFontResourceW (GDI32.@)
2991 INT WINAPI AddFontResourceW( LPCWSTR str )
2993 return AddFontResourceExW(str, 0, NULL);
2997 /***********************************************************************
2998 * AddFontResourceExA (GDI32.@)
3000 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3002 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3003 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3004 INT ret;
3006 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3007 ret = AddFontResourceExW(strW, fl, pdv);
3008 HeapFree(GetProcessHeap(), 0, strW);
3009 return ret;
3012 static BOOL CALLBACK load_enumed_resource(HMODULE hModule, LPCWSTR type, LPWSTR name, LONG_PTR lParam)
3014 HRSRC rsrc = FindResourceW(hModule, name, type);
3015 HGLOBAL hMem = LoadResource(hModule, rsrc);
3016 LPVOID *pMem = LockResource(hMem);
3017 int *num_total = (int *)lParam;
3018 DWORD num_in_res;
3020 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type));
3021 if (!AddFontMemResourceEx(pMem, SizeofResource(hModule, rsrc), NULL, &num_in_res))
3023 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule, hMem);
3024 return FALSE;
3027 *num_total += num_in_res;
3028 return TRUE;
3031 /***********************************************************************
3032 * AddFontResourceExW (GDI32.@)
3034 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3036 int ret = WineEngAddFontResourceEx(str, fl, pdv);
3037 if (ret == 0)
3039 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3040 HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
3041 if (hModule != NULL)
3043 int num_resources = 0;
3044 LPWSTR rt_font = (LPWSTR)((ULONG_PTR)8); /* we don't want to include winuser.h */
3046 TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3047 wine_dbgstr_w(str));
3048 if (EnumResourceNamesW(hModule, rt_font, load_enumed_resource, (LONG_PTR)&num_resources))
3049 ret = num_resources;
3050 FreeLibrary(hModule);
3053 return ret;
3056 /***********************************************************************
3057 * RemoveFontResourceA (GDI32.@)
3059 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3061 return RemoveFontResourceExA(str, 0, 0);
3064 /***********************************************************************
3065 * RemoveFontResourceW (GDI32.@)
3067 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3069 return RemoveFontResourceExW(str, 0, 0);
3072 /***********************************************************************
3073 * AddFontMemResourceEx (GDI32.@)
3075 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3077 return WineEngAddFontMemResourceEx(pbFont, cbFont, pdv, pcFonts);
3080 /***********************************************************************
3081 * RemoveFontMemResourceEx (GDI32.@)
3083 BOOL WINAPI RemoveFontMemResourceEx( HANDLE fh )
3085 FIXME("(%p) stub\n", fh);
3086 return TRUE;
3089 /***********************************************************************
3090 * RemoveFontResourceExA (GDI32.@)
3092 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3094 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3095 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3096 INT ret;
3098 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3099 ret = RemoveFontResourceExW(strW, fl, pdv);
3100 HeapFree(GetProcessHeap(), 0, strW);
3101 return ret;
3104 /***********************************************************************
3105 * RemoveFontResourceExW (GDI32.@)
3107 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3109 return WineEngRemoveFontResourceEx(str, fl, pdv);
3112 /***********************************************************************
3113 * GetTextCharset (GDI32.@)
3115 UINT WINAPI GetTextCharset(HDC hdc)
3117 /* MSDN docs say this is equivalent */
3118 return GetTextCharsetInfo(hdc, NULL, 0);
3121 /***********************************************************************
3122 * GetTextCharsetInfo (GDI32.@)
3124 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3126 UINT ret = DEFAULT_CHARSET;
3127 DC *dc = get_dc_ptr(hdc);
3129 if (dc)
3131 if (dc->gdiFont)
3132 ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
3134 release_dc_ptr( dc );
3137 if (ret == DEFAULT_CHARSET && fs)
3138 memset(fs, 0, sizeof(FONTSIGNATURE));
3139 return ret;
3142 /***********************************************************************
3143 * GdiGetCharDimensions (GDI32.@)
3145 * Gets the average width of the characters in the English alphabet.
3147 * PARAMS
3148 * hdc [I] Handle to the device context to measure on.
3149 * lptm [O] Pointer to memory to store the text metrics into.
3150 * height [O] On exit, the maximum height of characters in the English alphabet.
3152 * RETURNS
3153 * The average width of characters in the English alphabet.
3155 * NOTES
3156 * This function is used by the dialog manager to get the size of a dialog
3157 * unit. It should also be used by other pieces of code that need to know
3158 * the size of a dialog unit in logical units without having access to the
3159 * window handle of the dialog.
3160 * Windows caches the font metrics from this function, but we don't and
3161 * there doesn't appear to be an immediate advantage to do so.
3163 * SEE ALSO
3164 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3166 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3168 SIZE sz;
3169 static const WCHAR alphabet[] = {
3170 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3171 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3172 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3174 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3176 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3178 if (height) *height = sz.cy;
3179 return (sz.cx / 26 + 1) / 2;
3182 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3184 FIXME("(%d): stub\n", fEnableEUDC);
3185 return FALSE;
3188 /***********************************************************************
3189 * GetCharWidthI (GDI32.@)
3191 * Retrieve widths of characters.
3193 * PARAMS
3194 * hdc [I] Handle to a device context.
3195 * first [I] First glyph in range to query.
3196 * count [I] Number of glyph indices to query.
3197 * glyphs [I] Array of glyphs to query.
3198 * buffer [O] Buffer to receive character widths.
3200 * NOTES
3201 * Only works with TrueType fonts.
3203 * RETURNS
3204 * Success: TRUE
3205 * Failure: FALSE
3207 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3209 ABC *abc;
3210 unsigned int i;
3212 TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3214 if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3215 return FALSE;
3217 if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3219 HeapFree(GetProcessHeap(), 0, abc);
3220 return FALSE;
3223 for (i = 0; i < count; i++)
3224 buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3226 HeapFree(GetProcessHeap(), 0, abc);
3227 return TRUE;
3230 /***********************************************************************
3231 * GetFontUnicodeRanges (GDI32.@)
3233 * Retrieve a list of supported Unicode characters in a font.
3235 * PARAMS
3236 * hdc [I] Handle to a device context.
3237 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3239 * RETURNS
3240 * Success: Number of bytes written to the buffer pointed to by lpgs.
3241 * Failure: 0
3244 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3246 DWORD ret = 0;
3247 DC *dc = get_dc_ptr(hdc);
3249 TRACE("(%p, %p)\n", hdc, lpgs);
3251 if (!dc) return 0;
3253 if (dc->gdiFont) ret = WineEngGetFontUnicodeRanges(dc->gdiFont, lpgs);
3254 release_dc_ptr(dc);
3255 return ret;
3259 /*************************************************************
3260 * FontIsLinked (GDI32.@)
3262 BOOL WINAPI FontIsLinked(HDC hdc)
3264 DC *dc = get_dc_ptr(hdc);
3265 BOOL ret = FALSE;
3267 if (!dc) return FALSE;
3268 if (dc->gdiFont) ret = WineEngFontIsLinked(dc->gdiFont);
3269 release_dc_ptr(dc);
3270 TRACE("returning %d\n", ret);
3271 return ret;
3274 /*************************************************************
3275 * GdiRealizationInfo (GDI32.@)
3277 * Returns a structure that contains some font information.
3279 BOOL WINAPI GdiRealizationInfo(HDC hdc, realization_info_t *info)
3281 DC *dc = get_dc_ptr(hdc);
3282 BOOL ret = FALSE;
3284 if (!dc) return FALSE;
3285 if (dc->gdiFont) ret = WineEngRealizationInfo(dc->gdiFont, info);
3286 release_dc_ptr(dc);
3288 return ret;