setupapi/tests: Add a test for installing a driver service via an INF file.
[wine.git] / dlls / gdi32 / font.c
blobde82e70cd36f77249e513ea6281c9a2906aab216
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 FLOAT floatWidth;
50 /* Perform operation with floating point */
51 floatWidth = (FLOAT)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 FLOAT floatHeight;
63 /* Perform operation with floating point */
64 floatHeight = (FLOAT)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, void *obj, INT count, LPVOID buffer );
91 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
92 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj );
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 = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC, (HGDIOBJ *)&hFont,
349 &font_funcs ))) return 0;
351 fontPtr->logfont = *plf;
353 TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
354 plf->lfHeight, plf->lfWidth,
355 plf->lfEscapement, plf->lfOrientation,
356 plf->lfPitchAndFamily,
357 plf->lfOutPrecision, plf->lfClipPrecision,
358 plf->lfQuality, plf->lfCharSet,
359 debugstr_w(plf->lfFaceName),
360 plf->lfWeight > 400 ? "Bold" : "",
361 plf->lfItalic ? "Italic" : "",
362 plf->lfUnderline ? "Underline" : "", hFont);
364 if (plf->lfEscapement != plf->lfOrientation)
366 /* this should really depend on whether GM_ADVANCED is set */
367 fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
368 WARN("orientation angle %f set to "
369 "escapement angle %f for new font %p\n",
370 plf->lfOrientation/10., plf->lfEscapement/10., hFont);
373 pFaceNameItalicSuffix = strstrW(fontPtr->logfont.lfFaceName, ItalicW);
374 if (pFaceNameItalicSuffix)
376 fontPtr->logfont.lfItalic = TRUE;
377 pFaceNameSuffix = pFaceNameItalicSuffix;
380 pFaceNameBoldSuffix = strstrW(fontPtr->logfont.lfFaceName, BoldW);
381 if (pFaceNameBoldSuffix)
383 if (fontPtr->logfont.lfWeight < FW_BOLD)
384 fontPtr->logfont.lfWeight = FW_BOLD;
385 if (!pFaceNameSuffix || (pFaceNameBoldSuffix < pFaceNameSuffix))
386 pFaceNameSuffix = pFaceNameBoldSuffix;
389 if (pFaceNameSuffix) *pFaceNameSuffix = 0;
391 GDI_ReleaseObj( hFont );
392 return hFont;
395 /*************************************************************************
396 * CreateFontA (GDI32.@)
398 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
399 INT orient, INT weight, DWORD italic,
400 DWORD underline, DWORD strikeout, DWORD charset,
401 DWORD outpres, DWORD clippres, DWORD quality,
402 DWORD pitch, LPCSTR name )
404 LOGFONTA logfont;
406 logfont.lfHeight = height;
407 logfont.lfWidth = width;
408 logfont.lfEscapement = esc;
409 logfont.lfOrientation = orient;
410 logfont.lfWeight = weight;
411 logfont.lfItalic = italic;
412 logfont.lfUnderline = underline;
413 logfont.lfStrikeOut = strikeout;
414 logfont.lfCharSet = charset;
415 logfont.lfOutPrecision = outpres;
416 logfont.lfClipPrecision = clippres;
417 logfont.lfQuality = quality;
418 logfont.lfPitchAndFamily = pitch;
420 if (name)
421 lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
422 else
423 logfont.lfFaceName[0] = '\0';
425 return CreateFontIndirectA( &logfont );
428 /*************************************************************************
429 * CreateFontW (GDI32.@)
431 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
432 INT orient, INT weight, DWORD italic,
433 DWORD underline, DWORD strikeout, DWORD charset,
434 DWORD outpres, DWORD clippres, DWORD quality,
435 DWORD pitch, LPCWSTR name )
437 LOGFONTW logfont;
439 logfont.lfHeight = height;
440 logfont.lfWidth = width;
441 logfont.lfEscapement = esc;
442 logfont.lfOrientation = orient;
443 logfont.lfWeight = weight;
444 logfont.lfItalic = italic;
445 logfont.lfUnderline = underline;
446 logfont.lfStrikeOut = strikeout;
447 logfont.lfCharSet = charset;
448 logfont.lfOutPrecision = outpres;
449 logfont.lfClipPrecision = clippres;
450 logfont.lfQuality = quality;
451 logfont.lfPitchAndFamily = pitch;
453 if (name)
454 lstrcpynW(logfont.lfFaceName, name,
455 sizeof(logfont.lfFaceName) / sizeof(WCHAR));
456 else
457 logfont.lfFaceName[0] = '\0';
459 return CreateFontIndirectW( &logfont );
463 /***********************************************************************
464 * FONT_SelectObject
466 * If the driver supports vector fonts we create a gdi font first and
467 * then call the driver to give it a chance to supply its own device
468 * font. If the driver wants to do this it returns TRUE and we can
469 * delete the gdi font, if the driver wants to use the gdi font it
470 * should return FALSE, to signal an error return GDI_ERROR. For
471 * drivers that don't support vector fonts they must supply their own
472 * font.
474 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc )
476 HGDIOBJ ret = 0;
477 DC *dc = get_dc_ptr( hdc );
479 if (!dc) return 0;
481 if (!GDI_inc_ref_count( handle ))
483 release_dc_ptr( dc );
484 return 0;
487 if (dc->hFont != handle || dc->gdiFont == NULL)
489 if(GetDeviceCaps(dc->hSelf, TEXTCAPS) & TC_VA_ABLE)
491 FONTOBJ *font = GDI_GetObjPtr( handle, FONT_MAGIC ); /* to grab the GDI lock (FIXME) */
492 dc->gdiFont = WineEngCreateFontInstance(dc, handle);
493 if (font) GDI_ReleaseObj( handle );
497 if (dc->funcs->pSelectFont) ret = dc->funcs->pSelectFont( dc->physDev, handle, dc->gdiFont );
499 if (ret && dc->gdiFont) dc->gdiFont = 0;
501 if (ret == HGDI_ERROR)
503 GDI_dec_ref_count( handle );
504 ret = 0; /* SelectObject returns 0 on error */
506 else
508 ret = dc->hFont;
509 dc->hFont = handle;
510 GDI_dec_ref_count( ret );
512 release_dc_ptr( dc );
513 return ret;
517 /***********************************************************************
518 * FONT_GetObjectA
520 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
522 FONTOBJ *font = obj;
523 LOGFONTA lfA;
525 if(!buffer)
526 return sizeof(lfA);
527 FONT_LogFontWToA( &font->logfont, &lfA );
529 if (count > sizeof(lfA)) count = sizeof(lfA);
530 memcpy( buffer, &lfA, count );
531 return count;
534 /***********************************************************************
535 * FONT_GetObjectW
537 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
539 FONTOBJ *font = obj;
540 if(!buffer)
541 return sizeof(LOGFONTW);
542 if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
543 memcpy( buffer, &font->logfont, count );
544 return count;
548 /***********************************************************************
549 * FONT_DeleteObject
551 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj )
553 WineEngDestroyFontInstance( handle );
554 return GDI_FreeObject( handle, obj );
558 /***********************************************************************
559 * FONT_EnumInstance
561 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
562 * We have to use other types because of the FONTENUMPROCW definition.
564 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
565 DWORD fType, LPARAM lp )
567 fontEnum32 *pfe = (fontEnum32*)lp;
568 INT ret = 1;
570 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
571 if ((!pfe->lpLogFontParam ||
572 pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
573 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
574 (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
576 /* convert font metrics */
577 ENUMLOGFONTEXA logfont;
578 NEWTEXTMETRICEXA tmA;
580 pfe->dwFlags |= ENUM_CALLED;
581 if (!(pfe->dwFlags & ENUM_UNICODE))
583 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
584 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
585 plf = (LOGFONTW *)&logfont.elfLogFont;
586 ptm = (TEXTMETRICW *)&tmA;
589 ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
591 return ret;
594 /***********************************************************************
595 * FONT_EnumFontFamiliesEx
597 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf,
598 FONTENUMPROCW efproc,
599 LPARAM lParam, DWORD dwUnicode)
601 INT ret = 1, ret2;
602 DC *dc = get_dc_ptr( hDC );
603 fontEnum32 fe32;
604 BOOL enum_gdi_fonts;
606 if (!dc) return 0;
608 if (plf)
609 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName),
610 plf->lfCharSet);
611 fe32.lpLogFontParam = plf;
612 fe32.lpEnumFunc = efproc;
613 fe32.lpData = lParam;
614 fe32.dwFlags = dwUnicode;
615 fe32.hdc = hDC;
617 enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE;
619 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
621 ret = 0;
622 goto done;
625 if (enum_gdi_fonts)
626 ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
627 fe32.dwFlags &= ~ENUM_CALLED;
628 if (ret && dc->funcs->pEnumDeviceFonts) {
629 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, plf, FONT_EnumInstance, (LPARAM)&fe32 );
630 if(fe32.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
631 ret = ret2;
633 done:
634 release_dc_ptr( dc );
635 return ret;
638 /***********************************************************************
639 * EnumFontFamiliesExW (GDI32.@)
641 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
642 FONTENUMPROCW efproc,
643 LPARAM lParam, DWORD dwFlags )
645 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, ENUM_UNICODE );
648 /***********************************************************************
649 * EnumFontFamiliesExA (GDI32.@)
651 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
652 FONTENUMPROCA efproc,
653 LPARAM lParam, DWORD dwFlags)
655 LOGFONTW lfW, *plfW;
657 if (plf)
659 FONT_LogFontAToW( plf, &lfW );
660 plfW = &lfW;
662 else plfW = NULL;
664 return FONT_EnumFontFamiliesEx( hDC, plfW, (FONTENUMPROCW)efproc, lParam, 0);
667 /***********************************************************************
668 * EnumFontFamiliesA (GDI32.@)
670 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
671 FONTENUMPROCA efproc, LPARAM lpData )
673 LOGFONTA lf, *plf;
675 if (lpFamily)
677 if (!*lpFamily) return 1;
678 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
679 lf.lfCharSet = DEFAULT_CHARSET;
680 lf.lfPitchAndFamily = 0;
681 plf = &lf;
683 else plf = NULL;
685 return EnumFontFamiliesExA( hDC, plf, efproc, lpData, 0 );
688 /***********************************************************************
689 * EnumFontFamiliesW (GDI32.@)
691 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
692 FONTENUMPROCW efproc, LPARAM lpData )
694 LOGFONTW lf, *plf;
696 if (lpFamily)
698 if (!*lpFamily) return 1;
699 lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
700 lf.lfCharSet = DEFAULT_CHARSET;
701 lf.lfPitchAndFamily = 0;
702 plf = &lf;
704 else plf = NULL;
706 return EnumFontFamiliesExW( hDC, plf, efproc, lpData, 0 );
709 /***********************************************************************
710 * EnumFontsA (GDI32.@)
712 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
713 LPARAM lpData )
715 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
718 /***********************************************************************
719 * EnumFontsW (GDI32.@)
721 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
722 LPARAM lpData )
724 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
728 /***********************************************************************
729 * GetTextCharacterExtra (GDI32.@)
731 INT WINAPI GetTextCharacterExtra( HDC hdc )
733 INT ret;
734 DC *dc = get_dc_ptr( hdc );
735 if (!dc) return 0x80000000;
736 ret = dc->charExtra;
737 release_dc_ptr( dc );
738 return ret;
742 /***********************************************************************
743 * SetTextCharacterExtra (GDI32.@)
745 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
747 INT prev;
748 DC * dc = get_dc_ptr( hdc );
749 if (!dc) return 0x80000000;
750 if (dc->funcs->pSetTextCharacterExtra)
751 prev = dc->funcs->pSetTextCharacterExtra( dc->physDev, extra );
752 else
754 prev = dc->charExtra;
755 dc->charExtra = extra;
757 release_dc_ptr( dc );
758 return prev;
762 /***********************************************************************
763 * SetTextJustification (GDI32.@)
765 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
767 BOOL ret = TRUE;
768 DC * dc = get_dc_ptr( hdc );
769 if (!dc) return FALSE;
770 if (dc->funcs->pSetTextJustification)
771 ret = dc->funcs->pSetTextJustification( dc->physDev, extra, breaks );
772 else
774 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
775 if (!extra) breaks = 0;
776 if (breaks)
778 dc->breakExtra = extra / breaks;
779 dc->breakRem = extra - (breaks * dc->breakExtra);
781 else
783 dc->breakExtra = 0;
784 dc->breakRem = 0;
787 release_dc_ptr( dc );
788 return ret;
792 /***********************************************************************
793 * GetTextFaceA (GDI32.@)
795 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
797 INT res = GetTextFaceW(hdc, 0, NULL);
798 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
799 GetTextFaceW( hdc, res, nameW );
801 if (name)
803 if (count && !WideCharToMultiByte( CP_ACP, 0, nameW, -1, name, count, NULL, NULL))
804 name[count-1] = 0;
805 res = strlen(name);
807 else
808 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
809 HeapFree( GetProcessHeap(), 0, nameW );
810 return res;
813 /***********************************************************************
814 * GetTextFaceW (GDI32.@)
816 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
818 FONTOBJ *font;
819 INT ret = 0;
821 DC * dc = get_dc_ptr( hdc );
822 if (!dc) return 0;
824 if(dc->gdiFont)
825 ret = WineEngGetTextFace(dc->gdiFont, count, name);
826 else if ((font = (FONTOBJ *) GDI_GetObjPtr( dc->hFont, FONT_MAGIC )))
828 if (name)
830 lstrcpynW( name, font->logfont.lfFaceName, count );
831 ret = strlenW(name);
833 else ret = strlenW(font->logfont.lfFaceName) + 1;
834 GDI_ReleaseObj( dc->hFont );
836 release_dc_ptr( dc );
837 return ret;
841 /***********************************************************************
842 * GetTextExtentPoint32A (GDI32.@)
844 * See GetTextExtentPoint32W.
846 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
847 LPSIZE size )
849 BOOL ret = FALSE;
850 INT wlen;
851 LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
853 if (p) {
854 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
855 HeapFree( GetProcessHeap(), 0, p );
858 TRACE("(%p %s %d %p): returning %d x %d\n",
859 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
860 return ret;
864 /***********************************************************************
865 * GetTextExtentPoint32W [GDI32.@]
867 * Computes width/height for a string.
869 * Computes width and height of the specified string.
871 * RETURNS
872 * Success: TRUE
873 * Failure: FALSE
875 BOOL WINAPI GetTextExtentPoint32W(
876 HDC hdc, /* [in] Handle of device context */
877 LPCWSTR str, /* [in] Address of text string */
878 INT count, /* [in] Number of characters in string */
879 LPSIZE size) /* [out] Address of structure for string size */
881 return GetTextExtentExPointW(hdc, str, count, 0, NULL, NULL, size);
884 /***********************************************************************
885 * GetTextExtentExPointI [GDI32.@]
887 * Computes width and height of the array of glyph indices.
889 * PARAMS
890 * hdc [I] Handle of device context.
891 * indices [I] Glyph index array.
892 * count [I] Number of glyphs in array.
893 * max_ext [I] Maximum width in glyphs.
894 * nfit [O] Maximum number of characters.
895 * dxs [O] Partial string widths.
896 * size [O] Returned string size.
898 * RETURNS
899 * Success: TRUE
900 * Failure: FALSE
902 BOOL WINAPI GetTextExtentExPointI( HDC hdc, const WORD *indices, INT count, INT max_ext,
903 LPINT nfit, LPINT dxs, LPSIZE size )
905 BOOL ret = FALSE;
906 DC * dc = get_dc_ptr( hdc );
907 if (!dc) return FALSE;
909 if(dc->gdiFont) {
910 ret = WineEngGetTextExtentExPointI(dc->gdiFont, indices, count, max_ext, nfit, dxs, size);
911 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
912 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
913 size->cx += count * dc->charExtra;
915 else if(dc->funcs->pGetTextExtentExPoint) {
916 FIXME("calling GetTextExtentExPoint\n");
917 ret = dc->funcs->pGetTextExtentExPoint( dc->physDev, (LPCWSTR)indices,
918 count, max_ext, nfit, dxs, size );
921 release_dc_ptr( dc );
923 TRACE("(%p %p %d %p): returning %d x %d\n",
924 hdc, indices, count, size, size->cx, size->cy );
925 return ret;
928 /***********************************************************************
929 * GetTextExtentPointI [GDI32.@]
931 * Computes width and height of the array of glyph indices.
933 * PARAMS
934 * hdc [I] Handle of device context.
935 * indices [I] Glyph index array.
936 * count [I] Number of glyphs in array.
937 * size [O] Returned string size.
939 * RETURNS
940 * Success: TRUE
941 * Failure: FALSE
943 BOOL WINAPI GetTextExtentPointI( HDC hdc, const WORD *indices, INT count, LPSIZE size )
945 return GetTextExtentExPointI( hdc, indices, count, 0, NULL, NULL, size );
949 /***********************************************************************
950 * GetTextExtentPointA (GDI32.@)
952 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
953 LPSIZE size )
955 TRACE("not bug compatible.\n");
956 return GetTextExtentPoint32A( hdc, str, count, size );
959 /***********************************************************************
960 * GetTextExtentPointW (GDI32.@)
962 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
963 LPSIZE size )
965 TRACE("not bug compatible.\n");
966 return GetTextExtentPoint32W( hdc, str, count, size );
970 /***********************************************************************
971 * GetTextExtentExPointA (GDI32.@)
973 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
974 INT maxExt, LPINT lpnFit,
975 LPINT alpDx, LPSIZE size )
977 BOOL ret;
978 INT wlen;
979 INT *walpDx = NULL;
980 LPWSTR p = NULL;
982 if (alpDx &&
983 NULL == (walpDx = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT))))
984 return FALSE;
986 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
987 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
988 if (walpDx)
990 INT n = lpnFit ? *lpnFit : wlen;
991 INT i, j;
992 for(i = 0, j = 0; i < n; i++, j++)
994 alpDx[j] = walpDx[i];
995 if (IsDBCSLeadByte(str[j])) alpDx[++j] = walpDx[i];
998 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
999 HeapFree( GetProcessHeap(), 0, p );
1000 HeapFree( GetProcessHeap(), 0, walpDx );
1001 return ret;
1005 /***********************************************************************
1006 * GetTextExtentExPointW (GDI32.@)
1008 * Return the size of the string as it would be if it was output properly by
1009 * e.g. TextOut.
1011 * This should include
1012 * - Intercharacter spacing
1013 * - justification spacing (not yet done)
1014 * - kerning? see below
1016 * Kerning. Since kerning would be carried out by the rendering code it should
1017 * be done by the driver. However they don't support it yet. Also I am not
1018 * yet persuaded that (certainly under Win95) any kerning is actually done.
1020 * str: According to MSDN this should be null-terminated. That is not true; a
1021 * null will not terminate it early.
1022 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1023 * than count. I have seen it be either the size of the full string or
1024 * 1 less than the size of the full string. I have not seen it bear any
1025 * resemblance to the portion that would fit.
1026 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1027 * trailing intercharacter spacing and any trailing justification.
1029 * FIXME
1030 * Currently we do this by measuring each character etc. We should do it by
1031 * passing the request to the driver, perhaps by extending the
1032 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1033 * thinking about kerning issues and rounding issues in the justification.
1036 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1037 INT maxExt, LPINT lpnFit,
1038 LPINT alpDx, LPSIZE size )
1040 INT nFit = 0;
1041 LPINT dxs = NULL;
1042 DC *dc;
1043 BOOL ret = FALSE;
1044 TEXTMETRICW tm;
1046 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1048 dc = get_dc_ptr(hdc);
1049 if (! dc)
1050 return FALSE;
1052 GetTextMetricsW(hdc, &tm);
1054 /* If we need to calculate nFit, then we need the partial extents even if
1055 the user hasn't provided us with an array. */
1056 if (lpnFit)
1058 dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]);
1059 if (! dxs)
1061 release_dc_ptr(dc);
1062 SetLastError(ERROR_OUTOFMEMORY);
1063 return FALSE;
1066 else
1067 dxs = alpDx;
1069 if (dc->gdiFont)
1070 ret = WineEngGetTextExtentExPoint(dc->gdiFont, str, count,
1071 0, NULL, dxs, size);
1072 else if (dc->funcs->pGetTextExtentExPoint)
1073 ret = dc->funcs->pGetTextExtentExPoint(dc->physDev, str, count,
1074 0, NULL, dxs, size);
1076 /* Perform device size to world size transformations. */
1077 if (ret)
1079 INT extra = dc->charExtra,
1080 breakExtra = dc->breakExtra,
1081 breakRem = dc->breakRem,
1084 if (dxs)
1086 for (i = 0; i < count; ++i)
1088 dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
1089 dxs[i] += (i+1) * extra;
1090 if (count > 1 && (breakExtra || breakRem) && str[i] == tm.tmBreakChar)
1092 dxs[i] += breakExtra;
1093 if (breakRem > 0)
1095 breakRem--;
1096 dxs[i]++;
1099 if (dxs[i] <= maxExt)
1100 ++nFit;
1102 breakRem = dc->breakRem;
1104 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1105 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1107 if (!dxs && count > 1 && (breakExtra || breakRem))
1109 for (i = 0; i < count; i++)
1111 if (str[i] == tm.tmBreakChar)
1113 size->cx += breakExtra;
1114 if (breakRem > 0)
1116 breakRem--;
1117 (size->cx)++;
1124 if (lpnFit)
1125 *lpnFit = nFit;
1127 if (! alpDx)
1128 HeapFree(GetProcessHeap(), 0, dxs);
1130 release_dc_ptr( dc );
1132 TRACE("returning %d %d x %d\n",nFit,size->cx,size->cy);
1133 return ret;
1136 /***********************************************************************
1137 * GetTextMetricsA (GDI32.@)
1139 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1141 TEXTMETRICW tm32;
1143 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1144 FONT_TextMetricWToA( &tm32, metrics );
1145 return TRUE;
1148 /***********************************************************************
1149 * GetTextMetricsW (GDI32.@)
1151 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1153 BOOL ret = FALSE;
1154 DC * dc = get_dc_ptr( hdc );
1155 if (!dc) return FALSE;
1157 if (dc->gdiFont)
1158 ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1159 else if (dc->funcs->pGetTextMetrics)
1160 ret = dc->funcs->pGetTextMetrics( dc->physDev, metrics );
1162 if (ret)
1164 /* device layer returns values in device units
1165 * therefore we have to convert them to logical */
1167 metrics->tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1168 metrics->tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1170 #define WDPTOLP(x) ((x<0)? \
1171 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1172 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1173 #define HDPTOLP(y) ((y<0)? \
1174 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1175 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1177 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1178 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1179 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1180 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1181 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1182 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1183 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1184 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1185 ret = TRUE;
1186 #undef WDPTOLP
1187 #undef HDPTOLP
1188 TRACE("text metrics:\n"
1189 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1190 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1191 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1192 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1193 " PitchAndFamily = %02x\n"
1194 " --------------------\n"
1195 " InternalLeading = %i\n"
1196 " Ascent = %i\n"
1197 " Descent = %i\n"
1198 " Height = %i\n",
1199 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1200 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1201 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1202 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1203 metrics->tmPitchAndFamily,
1204 metrics->tmInternalLeading,
1205 metrics->tmAscent,
1206 metrics->tmDescent,
1207 metrics->tmHeight );
1209 release_dc_ptr( dc );
1210 return ret;
1214 /***********************************************************************
1215 * GetOutlineTextMetricsA (GDI32.@)
1216 * Gets metrics for TrueType fonts.
1218 * NOTES
1219 * If the supplied buffer isn't big enough Windows partially fills it up to
1220 * its given length and returns that length.
1222 * RETURNS
1223 * Success: Non-zero or size of required buffer
1224 * Failure: 0
1226 UINT WINAPI GetOutlineTextMetricsA(
1227 HDC hdc, /* [in] Handle of device context */
1228 UINT cbData, /* [in] Size of metric data array */
1229 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1231 char buf[512], *ptr;
1232 UINT ret, needed;
1233 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1234 OUTLINETEXTMETRICA *output = lpOTM;
1235 INT left, len;
1237 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1238 return 0;
1239 if(ret > sizeof(buf))
1240 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1241 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1243 needed = sizeof(OUTLINETEXTMETRICA);
1244 if(lpOTMW->otmpFamilyName)
1245 needed += WideCharToMultiByte(CP_ACP, 0,
1246 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1247 NULL, 0, NULL, NULL);
1248 if(lpOTMW->otmpFaceName)
1249 needed += WideCharToMultiByte(CP_ACP, 0,
1250 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1251 NULL, 0, NULL, NULL);
1252 if(lpOTMW->otmpStyleName)
1253 needed += WideCharToMultiByte(CP_ACP, 0,
1254 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1255 NULL, 0, NULL, NULL);
1256 if(lpOTMW->otmpFullName)
1257 needed += WideCharToMultiByte(CP_ACP, 0,
1258 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1259 NULL, 0, NULL, NULL);
1261 if(!lpOTM) {
1262 ret = needed;
1263 goto end;
1266 TRACE("needed = %d\n", needed);
1267 if(needed > cbData)
1268 /* Since the supplied buffer isn't big enough, we'll alloc one
1269 that is and memcpy the first cbData bytes into the lpOTM at
1270 the end. */
1271 output = HeapAlloc(GetProcessHeap(), 0, needed);
1273 ret = output->otmSize = min(needed, cbData);
1274 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1275 output->otmFiller = 0;
1276 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1277 output->otmfsSelection = lpOTMW->otmfsSelection;
1278 output->otmfsType = lpOTMW->otmfsType;
1279 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1280 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1281 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1282 output->otmEMSquare = lpOTMW->otmEMSquare;
1283 output->otmAscent = lpOTMW->otmAscent;
1284 output->otmDescent = lpOTMW->otmDescent;
1285 output->otmLineGap = lpOTMW->otmLineGap;
1286 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1287 output->otmsXHeight = lpOTMW->otmsXHeight;
1288 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1289 output->otmMacAscent = lpOTMW->otmMacAscent;
1290 output->otmMacDescent = lpOTMW->otmMacDescent;
1291 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1292 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1293 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1294 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1295 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1296 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1297 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1298 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1299 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1300 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1303 ptr = (char*)(output + 1);
1304 left = needed - sizeof(*output);
1306 if(lpOTMW->otmpFamilyName) {
1307 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1308 len = WideCharToMultiByte(CP_ACP, 0,
1309 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1310 ptr, left, NULL, NULL);
1311 left -= len;
1312 ptr += len;
1313 } else
1314 output->otmpFamilyName = 0;
1316 if(lpOTMW->otmpFaceName) {
1317 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1318 len = WideCharToMultiByte(CP_ACP, 0,
1319 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1320 ptr, left, NULL, NULL);
1321 left -= len;
1322 ptr += len;
1323 } else
1324 output->otmpFaceName = 0;
1326 if(lpOTMW->otmpStyleName) {
1327 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1328 len = WideCharToMultiByte(CP_ACP, 0,
1329 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1330 ptr, left, NULL, NULL);
1331 left -= len;
1332 ptr += len;
1333 } else
1334 output->otmpStyleName = 0;
1336 if(lpOTMW->otmpFullName) {
1337 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1338 len = WideCharToMultiByte(CP_ACP, 0,
1339 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1340 ptr, left, NULL, NULL);
1341 left -= len;
1342 } else
1343 output->otmpFullName = 0;
1345 assert(left == 0);
1347 if(output != lpOTM) {
1348 memcpy(lpOTM, output, cbData);
1349 HeapFree(GetProcessHeap(), 0, output);
1351 /* check if the string offsets really fit into the provided size */
1352 /* FIXME: should we check string length as well? */
1353 /* make sure that we don't read/write beyond the provided buffer */
1354 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(LPSTR))
1356 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1357 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1360 /* make sure that we don't read/write beyond the provided buffer */
1361 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(LPSTR))
1363 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1364 lpOTM->otmpFaceName = 0; /* doesn't fit */
1367 /* make sure that we don't read/write beyond the provided buffer */
1368 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(LPSTR))
1370 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1371 lpOTM->otmpStyleName = 0; /* doesn't fit */
1374 /* make sure that we don't read/write beyond the provided buffer */
1375 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(LPSTR))
1377 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1378 lpOTM->otmpFullName = 0; /* doesn't fit */
1382 end:
1383 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1384 HeapFree(GetProcessHeap(), 0, lpOTMW);
1386 return ret;
1390 /***********************************************************************
1391 * GetOutlineTextMetricsW [GDI32.@]
1393 UINT WINAPI GetOutlineTextMetricsW(
1394 HDC hdc, /* [in] Handle of device context */
1395 UINT cbData, /* [in] Size of metric data array */
1396 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1398 DC *dc = get_dc_ptr( hdc );
1399 OUTLINETEXTMETRICW *output = lpOTM;
1400 UINT ret;
1402 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1403 if(!dc) return 0;
1405 if(dc->gdiFont) {
1406 ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, output);
1407 if(lpOTM && ret) {
1408 if(ret > cbData) {
1409 output = HeapAlloc(GetProcessHeap(), 0, ret);
1410 WineEngGetOutlineTextMetrics(dc->gdiFont, ret, output);
1413 #define WDPTOLP(x) ((x<0)? \
1414 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1415 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1416 #define HDPTOLP(y) ((y<0)? \
1417 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1418 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1420 output->otmTextMetrics.tmHeight = HDPTOLP(output->otmTextMetrics.tmHeight);
1421 output->otmTextMetrics.tmAscent = HDPTOLP(output->otmTextMetrics.tmAscent);
1422 output->otmTextMetrics.tmDescent = HDPTOLP(output->otmTextMetrics.tmDescent);
1423 output->otmTextMetrics.tmInternalLeading = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1424 output->otmTextMetrics.tmExternalLeading = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1425 output->otmTextMetrics.tmAveCharWidth = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1426 output->otmTextMetrics.tmMaxCharWidth = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1427 output->otmTextMetrics.tmOverhang = WDPTOLP(output->otmTextMetrics.tmOverhang);
1428 output->otmAscent = HDPTOLP(output->otmAscent);
1429 output->otmDescent = HDPTOLP(output->otmDescent);
1430 output->otmLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmLineGap));
1431 output->otmsCapEmHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsCapEmHeight));
1432 output->otmsXHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsXHeight));
1433 output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1434 output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1435 output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1436 output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1437 output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1438 output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1439 output->otmMacLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmMacLineGap));
1440 output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1441 output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1442 output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1443 output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1444 output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1445 output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1446 output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1447 output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1448 output->otmsStrikeoutSize = abs(INTERNAL_YDSTOWS(dc,output->otmsStrikeoutSize));
1449 output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1450 output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1451 output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1452 #undef WDPTOLP
1453 #undef HDPTOLP
1454 if(output != lpOTM) {
1455 memcpy(lpOTM, output, cbData);
1456 HeapFree(GetProcessHeap(), 0, output);
1457 ret = cbData;
1462 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1463 but really this should just be a return 0. */
1465 ret = sizeof(*lpOTM);
1466 if (lpOTM) {
1467 if(cbData < ret)
1468 ret = 0;
1469 else {
1470 memset(lpOTM, 0, ret);
1471 lpOTM->otmSize = sizeof(*lpOTM);
1472 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1474 Further fill of the structure not implemented,
1475 Needs real values for the structure members
1480 release_dc_ptr(dc);
1481 return ret;
1485 /***********************************************************************
1486 * GetCharWidthW (GDI32.@)
1487 * GetCharWidth32W (GDI32.@)
1489 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1490 LPINT buffer )
1492 UINT i;
1493 BOOL ret = FALSE;
1494 DC * dc = get_dc_ptr( hdc );
1495 if (!dc) return FALSE;
1497 if (dc->gdiFont)
1498 ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1499 else if (dc->funcs->pGetCharWidth)
1500 ret = dc->funcs->pGetCharWidth( dc->physDev, firstChar, lastChar, buffer);
1502 if (ret)
1504 /* convert device units to logical */
1505 for( i = firstChar; i <= lastChar; i++, buffer++ )
1506 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1507 ret = TRUE;
1509 release_dc_ptr( dc );
1510 return ret;
1514 /***********************************************************************
1515 * GetCharWidthA (GDI32.@)
1516 * GetCharWidth32A (GDI32.@)
1518 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1519 LPINT buffer )
1521 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1522 LPSTR str;
1523 LPWSTR wstr;
1524 BOOL ret = TRUE;
1526 if(count <= 0) return FALSE;
1528 str = HeapAlloc(GetProcessHeap(), 0, count);
1529 for(i = 0; i < count; i++)
1530 str[i] = (BYTE)(firstChar + i);
1532 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1534 for(i = 0; i < wlen; i++)
1536 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1538 ret = FALSE;
1539 break;
1541 buffer++;
1544 HeapFree(GetProcessHeap(), 0, str);
1545 HeapFree(GetProcessHeap(), 0, wstr);
1547 return ret;
1551 /***********************************************************************
1552 * ExtTextOutA (GDI32.@)
1554 * See ExtTextOutW.
1556 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1557 const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1559 INT wlen;
1560 UINT codepage;
1561 LPWSTR p;
1562 BOOL ret;
1563 LPINT lpDxW = NULL;
1565 if (flags & ETO_GLYPH_INDEX)
1566 return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
1568 p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
1570 if (lpDx) {
1571 unsigned int i = 0, j = 0;
1573 lpDxW = HeapAlloc( GetProcessHeap(), 0, wlen*sizeof(INT));
1574 while(i < count) {
1575 if(IsDBCSLeadByteEx(codepage, str[i])) {
1576 lpDxW[j++] = lpDx[i] + lpDx[i+1];
1577 i = i + 2;
1578 } else {
1579 lpDxW[j++] = lpDx[i];
1580 i = i + 1;
1585 ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1587 HeapFree( GetProcessHeap(), 0, p );
1588 HeapFree( GetProcessHeap(), 0, lpDxW );
1589 return ret;
1593 /***********************************************************************
1594 * ExtTextOutW (GDI32.@)
1596 * Draws text using the currently selected font, background color, and text color.
1599 * PARAMS
1600 * x,y [I] coordinates of string
1601 * flags [I]
1602 * ETO_GRAYED - undocumented on MSDN
1603 * ETO_OPAQUE - use background color for fill the rectangle
1604 * ETO_CLIPPED - clipping text to the rectangle
1605 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1606 * than encoded characters. Implies ETO_IGNORELANGUAGE
1607 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1608 * Affects BiDi ordering
1609 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1610 * ETO_PDY - unimplemented
1611 * ETO_NUMERICSLATIN - unimplemented always assumed -
1612 * do not translate numbers into locale representations
1613 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1614 * lprect [I] dimensions for clipping or/and opaquing
1615 * str [I] text string
1616 * count [I] number of symbols in string
1617 * lpDx [I] optional parameter with distance between drawing characters
1619 * RETURNS
1620 * Success: TRUE
1621 * Failure: FALSE
1623 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1624 const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1626 BOOL ret = FALSE;
1627 LPWSTR reordered_str = (LPWSTR)str;
1628 WORD *glyphs = NULL;
1629 UINT align = GetTextAlign( hdc );
1630 POINT pt;
1631 TEXTMETRICW tm;
1632 LOGFONTW lf;
1633 double cosEsc, sinEsc;
1634 INT *deltas = NULL, char_extra;
1635 SIZE sz;
1636 RECT rc;
1637 BOOL done_extents = FALSE;
1638 INT width = 0, xwidth = 0, ywidth = 0;
1639 DWORD type;
1640 DC * dc = get_dc_ptr( hdc );
1641 INT breakRem;
1643 if (!dc) return FALSE;
1645 breakRem = dc->breakRem;
1647 if (flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY))
1648 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY unimplemented\n");
1650 if (!dc->funcs->pExtTextOut && !PATH_IsPathOpen(dc->path))
1652 release_dc_ptr( dc );
1653 return ret;
1656 update_dc( dc );
1657 type = GetObjectType(hdc);
1658 if(type == OBJ_METADC || type == OBJ_ENHMETADC)
1660 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, flags, lprect, str, count, lpDx);
1661 release_dc_ptr( dc );
1662 return ret;
1665 if (!lprect)
1666 flags &= ~ETO_CLIPPED;
1668 if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && count > 0 )
1670 reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1672 BIDI_Reorder( str, count, GCP_REORDER,
1673 ((flags&ETO_RTLREADING)!=0 || (GetTextAlign(hdc)&TA_RTLREADING)!=0)?
1674 WINE_GCPW_FORCE_RTL:WINE_GCPW_FORCE_LTR,
1675 reordered_str, count, NULL );
1677 flags |= ETO_IGNORELANGUAGE;
1680 TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc, x, y, flags,
1681 lprect, debugstr_wn(str, count), count, lpDx);
1683 if(flags & ETO_GLYPH_INDEX)
1684 glyphs = reordered_str;
1686 if(lprect)
1687 TRACE("rect: %d,%d - %d,%d\n", lprect->left, lprect->top, lprect->right,
1688 lprect->bottom);
1689 TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
1691 if(align & TA_UPDATECP)
1693 GetCurrentPositionEx( hdc, &pt );
1694 x = pt.x;
1695 y = pt.y;
1698 GetTextMetricsW(hdc, &tm);
1699 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1701 if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
1702 lf.lfEscapement = 0;
1704 if(lf.lfEscapement != 0)
1706 cosEsc = cos(lf.lfEscapement * M_PI / 1800);
1707 sinEsc = sin(lf.lfEscapement * M_PI / 1800);
1709 else
1711 cosEsc = 1;
1712 sinEsc = 0;
1715 if(flags & (ETO_CLIPPED | ETO_OPAQUE))
1717 if(!lprect)
1719 if(flags & ETO_GLYPH_INDEX)
1720 GetTextExtentPointI(hdc, glyphs, count, &sz);
1721 else
1722 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1724 done_extents = TRUE;
1725 rc.left = x;
1726 rc.top = y;
1727 rc.right = x + sz.cx;
1728 rc.bottom = y + sz.cy;
1730 else
1732 rc = *lprect;
1735 LPtoDP(hdc, (POINT*)&rc, 2);
1737 if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
1738 if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
1741 if ((flags & ETO_OPAQUE) && !PATH_IsPathOpen(dc->path))
1742 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1744 if(count == 0)
1746 ret = TRUE;
1747 goto done;
1750 pt.x = x;
1751 pt.y = y;
1752 LPtoDP(hdc, &pt, 1);
1753 x = pt.x;
1754 y = pt.y;
1756 char_extra = GetTextCharacterExtra(hdc);
1757 if(char_extra || dc->breakExtra || breakRem || lpDx || lf.lfEscapement != 0)
1759 UINT i;
1760 SIZE tmpsz;
1761 deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT));
1762 for(i = 0; i < count; i++)
1764 if(lpDx && (flags & ETO_PDY))
1765 deltas[i] = lpDx[i*2] + char_extra;
1766 else if(lpDx)
1767 deltas[i] = lpDx[i] + char_extra;
1768 else
1770 if(flags & ETO_GLYPH_INDEX)
1771 GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
1772 else
1773 GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
1775 deltas[i] = tmpsz.cx;
1778 if (!(flags & ETO_GLYPH_INDEX) && (dc->breakExtra || breakRem) && reordered_str[i] == tm.tmBreakChar)
1780 deltas[i] = deltas[i] + dc->breakExtra;
1781 if (breakRem > 0)
1783 breakRem--;
1784 deltas[i]++;
1787 deltas[i] = INTERNAL_XWSTODS(dc, deltas[i]);
1788 width += deltas[i];
1791 else
1793 if(!done_extents)
1795 if(flags & ETO_GLYPH_INDEX)
1796 GetTextExtentPointI(hdc, glyphs, count, &sz);
1797 else
1798 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1799 done_extents = TRUE;
1801 width = INTERNAL_XWSTODS(dc, sz.cx);
1803 xwidth = width * cosEsc;
1804 ywidth = width * sinEsc;
1806 tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
1807 tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
1808 switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
1810 case TA_LEFT:
1811 if (align & TA_UPDATECP)
1813 pt.x = x + xwidth;
1814 pt.y = y - ywidth;
1815 DPtoLP(hdc, &pt, 1);
1816 MoveToEx(hdc, pt.x, pt.y, NULL);
1818 break;
1820 case TA_CENTER:
1821 x -= xwidth / 2;
1822 y += ywidth / 2;
1823 break;
1825 case TA_RIGHT:
1826 x -= xwidth;
1827 y += ywidth;
1828 if (align & TA_UPDATECP)
1830 pt.x = x;
1831 pt.y = y;
1832 DPtoLP(hdc, &pt, 1);
1833 MoveToEx(hdc, pt.x, pt.y, NULL);
1835 break;
1838 switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
1840 case TA_TOP:
1841 y += tm.tmAscent * cosEsc;
1842 x += tm.tmAscent * sinEsc;
1843 break;
1845 case TA_BOTTOM:
1846 y -= tm.tmDescent * cosEsc;
1847 x -= tm.tmDescent * sinEsc;
1848 break;
1850 case TA_BASELINE:
1851 break;
1854 if (GetBkMode(hdc) != TRANSPARENT && !PATH_IsPathOpen(dc->path))
1856 if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
1858 if(!(flags & ETO_OPAQUE) || x < rc.left || x + width >= rc.right ||
1859 y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
1861 RECT rc;
1862 rc.left = x;
1863 rc.right = x + width;
1864 rc.top = y - tm.tmAscent;
1865 rc.bottom = y + tm.tmDescent;
1866 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1871 if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
1873 HFONT orig_font = dc->hFont, cur_font;
1874 UINT glyph;
1875 INT span = 0, *offsets = NULL;
1876 unsigned int i;
1878 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
1879 for(i = 0; i < count; i++)
1881 WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
1882 if(cur_font != dc->hFont)
1884 if(!offsets)
1886 unsigned int j;
1887 offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
1888 offsets[0] = 0;
1889 if(!deltas)
1891 SIZE tmpsz;
1892 for(j = 1; j < count; j++)
1894 GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
1895 offsets[j] = offsets[j-1] + INTERNAL_XWSTODS(dc, tmpsz.cx);
1898 else
1900 for(j = 1; j < count; j++)
1901 offsets[j] = offsets[j-1] + deltas[j];
1904 if(span)
1906 if (PATH_IsPathOpen(dc->path))
1907 ret = PATH_ExtTextOut(dc, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
1908 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
1909 glyphs, span, deltas ? deltas + i - span : NULL);
1910 else
1911 dc->funcs->pExtTextOut(dc->physDev, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
1912 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
1913 glyphs, span, deltas ? deltas + i - span : NULL);
1914 span = 0;
1916 SelectObject(hdc, cur_font);
1918 glyphs[span++] = glyph;
1920 if(i == count - 1)
1922 if (PATH_IsPathOpen(dc->path))
1923 ret = PATH_ExtTextOut(dc, x + (offsets ? offsets[count - span] * cosEsc : 0),
1924 y - (offsets ? offsets[count - span] * sinEsc : 0),
1925 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
1926 glyphs, span, deltas ? deltas + count - span : NULL);
1927 else
1928 ret = dc->funcs->pExtTextOut(dc->physDev, x + (offsets ? offsets[count - span] * cosEsc : 0),
1929 y - (offsets ? offsets[count - span] * sinEsc : 0),
1930 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
1931 glyphs, span, deltas ? deltas + count - span : NULL);
1932 SelectObject(hdc, orig_font);
1933 HeapFree(GetProcessHeap(), 0, offsets);
1937 else
1939 if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
1941 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
1942 GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
1943 flags |= ETO_GLYPH_INDEX;
1946 if (PATH_IsPathOpen(dc->path))
1947 ret = PATH_ExtTextOut(dc, x, y, (flags & ~ETO_OPAQUE), &rc,
1948 glyphs ? glyphs : reordered_str, count, deltas);
1949 else
1950 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, (flags & ~ETO_OPAQUE), &rc,
1951 glyphs ? glyphs : reordered_str, count, deltas);
1954 done:
1955 HeapFree(GetProcessHeap(), 0, deltas);
1956 if(glyphs != reordered_str)
1957 HeapFree(GetProcessHeap(), 0, glyphs);
1958 if(reordered_str != str)
1959 HeapFree(GetProcessHeap(), 0, reordered_str);
1961 release_dc_ptr( dc );
1963 if (ret && (lf.lfUnderline || lf.lfStrikeOut))
1965 int underlinePos, strikeoutPos;
1966 int underlineWidth, strikeoutWidth;
1967 UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
1968 OUTLINETEXTMETRICW* otm = NULL;
1970 if(!size)
1972 underlinePos = 0;
1973 underlineWidth = tm.tmAscent / 20 + 1;
1974 strikeoutPos = tm.tmAscent / 2;
1975 strikeoutWidth = underlineWidth;
1977 else
1979 otm = HeapAlloc(GetProcessHeap(), 0, size);
1980 GetOutlineTextMetricsW(hdc, size, otm);
1981 underlinePos = otm->otmsUnderscorePosition;
1982 underlineWidth = otm->otmsUnderscoreSize;
1983 strikeoutPos = otm->otmsStrikeoutPosition;
1984 strikeoutWidth = otm->otmsStrikeoutSize;
1985 HeapFree(GetProcessHeap(), 0, otm);
1988 if (PATH_IsPathOpen(dc->path))
1990 POINT pts[5];
1991 HPEN hpen;
1992 HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
1994 hbrush = SelectObject(hdc, hbrush);
1995 hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
1997 if (lf.lfUnderline)
1999 pts[0].x = x - underlinePos * sinEsc;
2000 pts[0].y = y - underlinePos * cosEsc;
2001 pts[1].x = x + xwidth - underlinePos * sinEsc;
2002 pts[1].y = y - ywidth - underlinePos * cosEsc;
2003 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2004 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2005 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2006 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2007 pts[4].x = pts[0].x;
2008 pts[4].y = pts[0].y;
2009 DPtoLP(hdc, pts, 5);
2010 Polygon(hdc, pts, 5);
2013 if (lf.lfStrikeOut)
2015 pts[0].x = x - strikeoutPos * sinEsc;
2016 pts[0].y = y - strikeoutPos * cosEsc;
2017 pts[1].x = x + xwidth - strikeoutPos * sinEsc;
2018 pts[1].y = y - ywidth - strikeoutPos * cosEsc;
2019 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2020 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2021 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2022 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2023 pts[4].x = pts[0].x;
2024 pts[4].y = pts[0].y;
2025 DPtoLP(hdc, pts, 5);
2026 Polygon(hdc, pts, 5);
2029 SelectObject(hdc, hpen);
2030 hbrush = SelectObject(hdc, hbrush);
2031 DeleteObject(hbrush);
2033 else
2035 POINT pts[2], oldpt;
2036 HPEN hpen;
2038 if (lf.lfUnderline)
2040 hpen = CreatePen(PS_SOLID, underlineWidth, GetTextColor(hdc));
2041 hpen = SelectObject(hdc, hpen);
2042 pts[0].x = x;
2043 pts[0].y = y;
2044 pts[1].x = x + xwidth;
2045 pts[1].y = y - ywidth;
2046 DPtoLP(hdc, pts, 2);
2047 MoveToEx(hdc, pts[0].x - underlinePos * sinEsc, pts[0].y - underlinePos * cosEsc, &oldpt);
2048 LineTo(hdc, pts[1].x - underlinePos * sinEsc, pts[1].y - underlinePos * cosEsc);
2049 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2050 DeleteObject(SelectObject(hdc, hpen));
2053 if (lf.lfStrikeOut)
2055 hpen = CreatePen(PS_SOLID, strikeoutWidth, GetTextColor(hdc));
2056 hpen = SelectObject(hdc, hpen);
2057 pts[0].x = x;
2058 pts[0].y = y;
2059 pts[1].x = x + xwidth;
2060 pts[1].y = y - ywidth;
2061 DPtoLP(hdc, pts, 2);
2062 MoveToEx(hdc, pts[0].x - strikeoutPos * sinEsc, pts[0].y - strikeoutPos * cosEsc, &oldpt);
2063 LineTo(hdc, pts[1].x - strikeoutPos * sinEsc, pts[1].y - strikeoutPos * cosEsc);
2064 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2065 DeleteObject(SelectObject(hdc, hpen));
2070 return ret;
2074 /***********************************************************************
2075 * TextOutA (GDI32.@)
2077 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2079 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2083 /***********************************************************************
2084 * TextOutW (GDI32.@)
2086 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2088 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2092 /***********************************************************************
2093 * PolyTextOutA (GDI32.@)
2095 * See PolyTextOutW.
2097 BOOL WINAPI PolyTextOutA( HDC hdc, const POLYTEXTA *pptxt, INT cStrings )
2099 for (; cStrings>0; cStrings--, pptxt++)
2100 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2101 return FALSE;
2102 return TRUE;
2107 /***********************************************************************
2108 * PolyTextOutW (GDI32.@)
2110 * Draw several Strings
2112 * RETURNS
2113 * TRUE: Success.
2114 * FALSE: Failure.
2116 BOOL WINAPI PolyTextOutW( HDC hdc, const POLYTEXTW *pptxt, INT cStrings )
2118 for (; cStrings>0; cStrings--, pptxt++)
2119 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2120 return FALSE;
2121 return TRUE;
2125 /* FIXME: all following APIs ******************************************/
2128 /***********************************************************************
2129 * SetMapperFlags (GDI32.@)
2131 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
2133 DC *dc = get_dc_ptr( hDC );
2134 DWORD ret = 0;
2135 if(!dc) return 0;
2136 if(dc->funcs->pSetMapperFlags)
2138 ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
2139 /* FIXME: ret is just a success flag, we should return a proper value */
2141 else
2142 FIXME("(%p, 0x%08x): stub - harmless\n", hDC, dwFlag);
2143 release_dc_ptr( dc );
2144 return ret;
2147 /***********************************************************************
2148 * GetAspectRatioFilterEx (GDI32.@)
2150 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2152 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2153 return FALSE;
2157 /***********************************************************************
2158 * GetCharABCWidthsA (GDI32.@)
2160 * See GetCharABCWidthsW.
2162 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2163 LPABC abc )
2165 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
2166 LPSTR str;
2167 LPWSTR wstr;
2168 BOOL ret = TRUE;
2170 if(count <= 0) return FALSE;
2172 str = HeapAlloc(GetProcessHeap(), 0, count);
2173 for(i = 0; i < count; i++)
2174 str[i] = (BYTE)(firstChar + i);
2176 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
2178 for(i = 0; i < wlen; i++)
2180 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2182 ret = FALSE;
2183 break;
2185 abc++;
2188 HeapFree(GetProcessHeap(), 0, str);
2189 HeapFree(GetProcessHeap(), 0, wstr);
2191 return ret;
2195 /******************************************************************************
2196 * GetCharABCWidthsW [GDI32.@]
2198 * Retrieves widths of characters in range.
2200 * PARAMS
2201 * hdc [I] Handle of device context
2202 * firstChar [I] First character in range to query
2203 * lastChar [I] Last character in range to query
2204 * abc [O] Address of character-width structure
2206 * NOTES
2207 * Only works with TrueType fonts
2209 * RETURNS
2210 * Success: TRUE
2211 * Failure: FALSE
2213 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2214 LPABC abc )
2216 DC *dc = get_dc_ptr(hdc);
2217 unsigned int i;
2218 BOOL ret = FALSE;
2220 if (!dc) return FALSE;
2222 if (!abc)
2224 release_dc_ptr( dc );
2225 return FALSE;
2228 if(dc->gdiFont)
2229 ret = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
2230 else
2231 FIXME(": stub\n");
2233 if (ret)
2235 /* convert device units to logical */
2236 for( i = firstChar; i <= lastChar; i++, abc++ ) {
2237 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2238 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2239 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2241 ret = TRUE;
2244 release_dc_ptr( dc );
2245 return ret;
2249 /******************************************************************************
2250 * GetCharABCWidthsI [GDI32.@]
2252 * Retrieves widths of characters in range.
2254 * PARAMS
2255 * hdc [I] Handle of device context
2256 * firstChar [I] First glyphs in range to query
2257 * count [I] Last glyphs in range to query
2258 * pgi [i] Array of glyphs to query
2259 * abc [O] Address of character-width structure
2261 * NOTES
2262 * Only works with TrueType fonts
2264 * RETURNS
2265 * Success: TRUE
2266 * Failure: FALSE
2268 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2269 LPWORD pgi, LPABC abc)
2271 DC *dc = get_dc_ptr(hdc);
2272 unsigned int i;
2273 BOOL ret = FALSE;
2275 if (!dc) return FALSE;
2277 if (!abc)
2279 release_dc_ptr( dc );
2280 return FALSE;
2283 if(dc->gdiFont)
2284 ret = WineEngGetCharABCWidthsI( dc->gdiFont, firstChar, count, pgi, abc );
2285 else
2286 FIXME(": stub\n");
2288 if (ret)
2290 /* convert device units to logical */
2291 for( i = 0; i < count; i++, abc++ ) {
2292 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2293 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2294 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2296 ret = TRUE;
2299 release_dc_ptr( dc );
2300 return ret;
2304 /***********************************************************************
2305 * GetGlyphOutlineA (GDI32.@)
2307 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2308 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2309 LPVOID lpBuffer, const MAT2 *lpmat2 )
2311 LPWSTR p = NULL;
2312 DWORD ret;
2313 UINT c;
2315 if(!(fuFormat & GGO_GLYPH_INDEX)) {
2316 int len;
2317 char mbchs[2];
2318 if(uChar > 0xff) { /* but, 2 bytes character only */
2319 len = 2;
2320 mbchs[0] = (uChar & 0xff00) >> 8;
2321 mbchs[1] = (uChar & 0xff);
2322 } else {
2323 len = 1;
2324 mbchs[0] = (uChar & 0xff);
2326 p = FONT_mbtowc(hdc, mbchs, len, NULL, NULL);
2327 c = p[0];
2328 } else
2329 c = uChar;
2330 ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
2331 lpmat2);
2332 HeapFree(GetProcessHeap(), 0, p);
2333 return ret;
2336 /***********************************************************************
2337 * GetGlyphOutlineW (GDI32.@)
2339 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2340 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2341 LPVOID lpBuffer, const MAT2 *lpmat2 )
2343 DC *dc = get_dc_ptr(hdc);
2344 DWORD ret;
2346 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2347 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2349 if(!dc) return GDI_ERROR;
2351 if(dc->gdiFont)
2352 ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
2353 cbBuffer, lpBuffer, lpmat2);
2354 else
2355 ret = GDI_ERROR;
2357 release_dc_ptr( dc );
2358 return ret;
2362 /***********************************************************************
2363 * CreateScalableFontResourceA (GDI32.@)
2365 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2366 LPCSTR lpszResourceFile,
2367 LPCSTR lpszFontFile,
2368 LPCSTR lpszCurrentPath )
2370 LPWSTR lpszResourceFileW = NULL;
2371 LPWSTR lpszFontFileW = NULL;
2372 LPWSTR lpszCurrentPathW = NULL;
2373 int len;
2374 BOOL ret;
2376 if (lpszResourceFile)
2378 len = MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, NULL, 0);
2379 lpszResourceFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2380 MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, lpszResourceFileW, len);
2383 if (lpszFontFile)
2385 len = MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, NULL, 0);
2386 lpszFontFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2387 MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, lpszFontFileW, len);
2390 if (lpszCurrentPath)
2392 len = MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, NULL, 0);
2393 lpszCurrentPathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2394 MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, lpszCurrentPathW, len);
2397 ret = CreateScalableFontResourceW(fHidden, lpszResourceFileW,
2398 lpszFontFileW, lpszCurrentPathW);
2400 HeapFree(GetProcessHeap(), 0, lpszResourceFileW);
2401 HeapFree(GetProcessHeap(), 0, lpszFontFileW);
2402 HeapFree(GetProcessHeap(), 0, lpszCurrentPathW);
2404 return ret;
2407 /***********************************************************************
2408 * CreateScalableFontResourceW (GDI32.@)
2410 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2411 LPCWSTR lpszResourceFile,
2412 LPCWSTR lpszFontFile,
2413 LPCWSTR lpszCurrentPath )
2415 HANDLE f;
2416 FIXME("(%d,%s,%s,%s): stub\n",
2417 fHidden, debugstr_w(lpszResourceFile), debugstr_w(lpszFontFile),
2418 debugstr_w(lpszCurrentPath) );
2420 /* fHidden=1 - only visible for the calling app, read-only, not
2421 * enumbered with EnumFonts/EnumFontFamilies
2422 * lpszCurrentPath can be NULL
2425 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2426 if ((f = CreateFileW(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2427 CloseHandle(f);
2428 SetLastError(ERROR_FILE_EXISTS);
2429 return FALSE;
2431 return FALSE; /* create failed */
2434 /*************************************************************************
2435 * GetKerningPairsA (GDI32.@)
2437 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2438 LPKERNINGPAIR kern_pairA )
2440 INT charset;
2441 CHARSETINFO csi;
2442 CPINFO cpi;
2443 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2444 KERNINGPAIR *kern_pairW;
2446 if (!cPairs && kern_pairA)
2448 SetLastError(ERROR_INVALID_PARAMETER);
2449 return 0;
2452 charset = GetTextCharset(hDC);
2453 if (!TranslateCharsetInfo(ULongToPtr(charset), &csi, TCI_SRCCHARSET))
2455 FIXME("Can't find codepage for charset %d\n", charset);
2456 return 0;
2458 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2459 * to fail on an invalid character for CP_SYMBOL.
2461 cpi.DefaultChar[0] = 0;
2462 if (csi.ciACP != CP_SYMBOL && !GetCPInfo(csi.ciACP, &cpi))
2464 FIXME("Can't find codepage %u info\n", csi.ciACP);
2465 return 0;
2467 TRACE("charset %d => codepage %u\n", charset, csi.ciACP);
2469 total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2470 if (!total_kern_pairs) return 0;
2472 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2473 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2475 for (i = 0; i < total_kern_pairs; i++)
2477 char first, second;
2479 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2480 continue;
2482 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2483 continue;
2485 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2486 continue;
2488 if (kern_pairA)
2490 if (kern_pairs_copied >= cPairs) break;
2492 kern_pairA->wFirst = (BYTE)first;
2493 kern_pairA->wSecond = (BYTE)second;
2494 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2495 kern_pairA++;
2497 kern_pairs_copied++;
2500 HeapFree(GetProcessHeap(), 0, kern_pairW);
2502 return kern_pairs_copied;
2505 /*************************************************************************
2506 * GetKerningPairsW (GDI32.@)
2508 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2509 LPKERNINGPAIR lpKerningPairs )
2511 DC *dc;
2512 DWORD ret = 0;
2514 TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2516 if (!cPairs && lpKerningPairs)
2518 SetLastError(ERROR_INVALID_PARAMETER);
2519 return 0;
2522 dc = get_dc_ptr(hDC);
2523 if (!dc) return 0;
2525 if (dc->gdiFont)
2526 ret = WineEngGetKerningPairs(dc->gdiFont, cPairs, lpKerningPairs);
2528 release_dc_ptr( dc );
2529 return ret;
2532 /*************************************************************************
2533 * TranslateCharsetInfo [GDI32.@]
2535 * Fills a CHARSETINFO structure for a character set, code page, or
2536 * font. This allows making the correspondence between different labels
2537 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2538 * of the same encoding.
2540 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2541 * only one codepage should be set in *lpSrc.
2543 * RETURNS
2544 * TRUE on success, FALSE on failure.
2547 BOOL WINAPI TranslateCharsetInfo(
2548 LPDWORD lpSrc, /* [in]
2549 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2550 if flags == TCI_SRCCHARSET: a character set value
2551 if flags == TCI_SRCCODEPAGE: a code page value
2553 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2554 DWORD flags /* [in] determines interpretation of lpSrc */)
2556 int index = 0;
2557 switch (flags) {
2558 case TCI_SRCFONTSIG:
2559 while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
2560 break;
2561 case TCI_SRCCODEPAGE:
2562 while (PtrToUlong(lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
2563 break;
2564 case TCI_SRCCHARSET:
2565 while (PtrToUlong(lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
2566 break;
2567 default:
2568 return FALSE;
2570 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2571 *lpCs = FONT_tci[index];
2572 return TRUE;
2575 /*************************************************************************
2576 * GetFontLanguageInfo (GDI32.@)
2578 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2580 FONTSIGNATURE fontsig;
2581 static const DWORD GCP_DBCS_MASK=0x003F0000,
2582 GCP_DIACRITIC_MASK=0x00000000,
2583 FLI_GLYPHS_MASK=0x00000000,
2584 GCP_GLYPHSHAPE_MASK=0x00000040,
2585 GCP_KASHIDA_MASK=0x00000000,
2586 GCP_LIGATE_MASK=0x00000000,
2587 GCP_USEKERNING_MASK=0x00000000,
2588 GCP_REORDER_MASK=0x00000060;
2590 DWORD result=0;
2592 GetTextCharsetInfo( hdc, &fontsig, 0 );
2593 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2595 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2596 result|=GCP_DBCS;
2598 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2599 result|=GCP_DIACRITIC;
2601 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2602 result|=FLI_GLYPHS;
2604 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2605 result|=GCP_GLYPHSHAPE;
2607 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2608 result|=GCP_KASHIDA;
2610 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2611 result|=GCP_LIGATE;
2613 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2614 result|=GCP_USEKERNING;
2616 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2617 if( GetTextAlign( hdc) & TA_RTLREADING )
2618 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2619 result|=GCP_REORDER;
2621 return result;
2625 /*************************************************************************
2626 * GetFontData [GDI32.@]
2628 * Retrieve data for TrueType font.
2630 * RETURNS
2632 * success: Number of bytes returned
2633 * failure: GDI_ERROR
2635 * NOTES
2637 * Calls SetLastError()
2640 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2641 LPVOID buffer, DWORD length)
2643 DC *dc = get_dc_ptr(hdc);
2644 DWORD ret = GDI_ERROR;
2646 if(!dc) return GDI_ERROR;
2648 if(dc->gdiFont)
2649 ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2651 release_dc_ptr( dc );
2652 return ret;
2655 /*************************************************************************
2656 * GetGlyphIndicesA [GDI32.@]
2658 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2659 LPWORD pgi, DWORD flags)
2661 DWORD ret;
2662 WCHAR *lpstrW;
2663 INT countW;
2665 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2666 hdc, debugstr_an(lpstr, count), count, pgi, flags);
2668 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2669 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2670 HeapFree(GetProcessHeap(), 0, lpstrW);
2672 return ret;
2675 /*************************************************************************
2676 * GetGlyphIndicesW [GDI32.@]
2678 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2679 LPWORD pgi, DWORD flags)
2681 DC *dc = get_dc_ptr(hdc);
2682 DWORD ret = GDI_ERROR;
2684 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2685 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2687 if(!dc) return GDI_ERROR;
2689 if(dc->gdiFont)
2690 ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2692 release_dc_ptr( dc );
2693 return ret;
2696 /*************************************************************************
2697 * GetCharacterPlacementA [GDI32.@]
2699 * See GetCharacterPlacementW.
2701 * NOTES:
2702 * the web browser control of ie4 calls this with dwFlags=0
2704 DWORD WINAPI
2705 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2706 INT nMaxExtent, GCP_RESULTSA *lpResults,
2707 DWORD dwFlags)
2709 WCHAR *lpStringW;
2710 INT uCountW;
2711 GCP_RESULTSW resultsW;
2712 DWORD ret;
2713 UINT font_cp;
2715 TRACE("%s, %d, %d, 0x%08x\n",
2716 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2718 /* both structs are equal in size */
2719 memcpy(&resultsW, lpResults, sizeof(resultsW));
2721 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2722 if(lpResults->lpOutString)
2723 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2725 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2727 lpResults->nGlyphs = resultsW.nGlyphs;
2728 lpResults->nMaxFit = resultsW.nMaxFit;
2730 if(lpResults->lpOutString) {
2731 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2732 lpResults->lpOutString, uCount, NULL, NULL );
2735 HeapFree(GetProcessHeap(), 0, lpStringW);
2736 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2738 return ret;
2741 /*************************************************************************
2742 * GetCharacterPlacementW [GDI32.@]
2744 * Retrieve information about a string. This includes the width, reordering,
2745 * Glyphing and so on.
2747 * RETURNS
2749 * The width and height of the string if successful, 0 if failed.
2751 * BUGS
2753 * All flags except GCP_REORDER are not yet implemented.
2754 * Reordering is not 100% complient to the Windows BiDi method.
2755 * Caret positioning is not yet implemented for BiDi.
2756 * Classes are not yet implemented.
2759 DWORD WINAPI
2760 GetCharacterPlacementW(
2761 HDC hdc, /* [in] Device context for which the rendering is to be done */
2762 LPCWSTR lpString, /* [in] The string for which information is to be returned */
2763 INT uCount, /* [in] Number of WORDS in string. */
2764 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
2765 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2766 DWORD dwFlags /* [in] Flags specifying how to process the string */
2769 DWORD ret=0;
2770 SIZE size;
2771 UINT i, nSet;
2773 TRACE("%s, %d, %d, 0x%08x\n",
2774 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2776 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2777 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2778 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2779 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2780 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2782 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08x ignored\n", dwFlags);
2783 if(lpResults->lpClass) FIXME("classes not implemented\n");
2784 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2785 FIXME("Caret positions for complex scripts not implemented\n");
2787 nSet = (UINT)uCount;
2788 if(nSet > lpResults->nGlyphs)
2789 nSet = lpResults->nGlyphs;
2791 /* return number of initialized fields */
2792 lpResults->nGlyphs = nSet;
2794 if((dwFlags&GCP_REORDER)==0 )
2796 /* Treat the case where no special handling was requested in a fastpath way */
2797 /* copy will do if the GCP_REORDER flag is not set */
2798 if(lpResults->lpOutString)
2799 memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
2801 if(lpResults->lpOrder)
2803 for(i = 0; i < nSet; i++)
2804 lpResults->lpOrder[i] = i;
2806 } else
2808 BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
2809 nSet, lpResults->lpOrder );
2812 /* FIXME: Will use the placement chars */
2813 if (lpResults->lpDx)
2815 int c;
2816 for (i = 0; i < nSet; i++)
2818 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
2819 lpResults->lpDx[i]= c;
2823 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
2825 int pos = 0;
2827 lpResults->lpCaretPos[0] = 0;
2828 for (i = 1; i < nSet; i++)
2829 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
2830 lpResults->lpCaretPos[i] = (pos += size.cx);
2833 if(lpResults->lpGlyphs)
2834 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
2836 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
2837 ret = MAKELONG(size.cx, size.cy);
2839 return ret;
2842 /*************************************************************************
2843 * GetCharABCWidthsFloatA [GDI32.@]
2845 * See GetCharABCWidthsFloatW.
2847 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
2849 INT i, wlen, count = (INT)(last - first + 1);
2850 LPSTR str;
2851 LPWSTR wstr;
2852 BOOL ret = TRUE;
2854 if (count <= 0) return FALSE;
2856 str = HeapAlloc(GetProcessHeap(), 0, count);
2858 for(i = 0; i < count; i++)
2859 str[i] = (BYTE)(first + i);
2861 wstr = FONT_mbtowc( hdc, str, count, &wlen, NULL );
2863 for (i = 0; i < wlen; i++)
2865 if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
2867 ret = FALSE;
2868 break;
2870 abcf++;
2873 HeapFree( GetProcessHeap(), 0, str );
2874 HeapFree( GetProcessHeap(), 0, wstr );
2876 return ret;
2879 /*************************************************************************
2880 * GetCharABCWidthsFloatW [GDI32.@]
2882 * Retrieves widths of a range of characters.
2884 * PARAMS
2885 * hdc [I] Handle to device context.
2886 * first [I] First character in range to query.
2887 * last [I] Last character in range to query.
2888 * abcf [O] Array of LPABCFLOAT structures.
2890 * RETURNS
2891 * Success: TRUE
2892 * Failure: FALSE
2894 * BUGS
2895 * Only works with TrueType fonts. It also doesn't return real
2896 * floats but converted integers because it's implemented on
2897 * top of GetCharABCWidthsW.
2899 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
2901 ABC *abc;
2902 unsigned int i, size = sizeof(ABC) * (last - first + 1);
2903 BOOL ret;
2905 TRACE("%p, %d, %d, %p - partial stub\n", hdc, first, last, abcf);
2907 abc = HeapAlloc( GetProcessHeap(), 0, size );
2908 if (!abc) return FALSE;
2910 ret = GetCharABCWidthsW( hdc, first, last, abc );
2911 if (ret)
2913 for (i = first; i <= last; i++, abc++, abcf++)
2915 abcf->abcfA = abc->abcA;
2916 abcf->abcfB = abc->abcB;
2917 abcf->abcfC = abc->abcC;
2920 HeapFree( GetProcessHeap(), 0, abc );
2921 return ret;
2924 /*************************************************************************
2925 * GetCharWidthFloatA [GDI32.@]
2927 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
2928 UINT iLastChar, PFLOAT pxBuffer)
2930 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
2931 return 0;
2934 /*************************************************************************
2935 * GetCharWidthFloatW [GDI32.@]
2937 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
2938 UINT iLastChar, PFLOAT pxBuffer)
2940 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
2941 return 0;
2945 /***********************************************************************
2947 * Font Resource API *
2949 ***********************************************************************/
2951 /***********************************************************************
2952 * AddFontResourceA (GDI32.@)
2954 INT WINAPI AddFontResourceA( LPCSTR str )
2956 return AddFontResourceExA( str, 0, NULL);
2959 /***********************************************************************
2960 * AddFontResourceW (GDI32.@)
2962 INT WINAPI AddFontResourceW( LPCWSTR str )
2964 return AddFontResourceExW(str, 0, NULL);
2968 /***********************************************************************
2969 * AddFontResourceExA (GDI32.@)
2971 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
2973 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
2974 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2975 INT ret;
2977 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
2978 ret = AddFontResourceExW(strW, fl, pdv);
2979 HeapFree(GetProcessHeap(), 0, strW);
2980 return ret;
2983 static BOOL CALLBACK load_enumed_resource(HMODULE hModule, LPCWSTR type, LPWSTR name, LONG_PTR lParam)
2985 HRSRC rsrc = FindResourceW(hModule, name, type);
2986 HGLOBAL hMem = LoadResource(hModule, rsrc);
2987 LPVOID *pMem = LockResource(hMem);
2988 int *num_total = (int *)lParam;
2989 DWORD num_in_res;
2991 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type));
2992 if (!AddFontMemResourceEx(pMem, SizeofResource(hModule, rsrc), NULL, &num_in_res))
2994 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule, hMem);
2995 return FALSE;
2998 *num_total += num_in_res;
2999 return TRUE;
3002 /***********************************************************************
3003 * AddFontResourceExW (GDI32.@)
3005 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3007 int ret = WineEngAddFontResourceEx(str, fl, pdv);
3008 if (ret == 0)
3010 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3011 HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
3012 if (hModule != NULL)
3014 int num_resources = 0;
3015 LPWSTR rt_font = (LPWSTR)((ULONG_PTR)8); /* we don't want to include winuser.h */
3017 TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3018 wine_dbgstr_w(str));
3019 if (EnumResourceNamesW(hModule, rt_font, load_enumed_resource, (LONG_PTR)&num_resources))
3020 ret = num_resources;
3021 FreeLibrary(hModule);
3024 return ret;
3027 /***********************************************************************
3028 * RemoveFontResourceA (GDI32.@)
3030 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3032 return RemoveFontResourceExA(str, 0, 0);
3035 /***********************************************************************
3036 * RemoveFontResourceW (GDI32.@)
3038 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3040 return RemoveFontResourceExW(str, 0, 0);
3043 /***********************************************************************
3044 * AddFontMemResourceEx (GDI32.@)
3046 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3048 return WineEngAddFontMemResourceEx(pbFont, cbFont, pdv, pcFonts);
3051 /***********************************************************************
3052 * RemoveFontMemResourceEx (GDI32.@)
3054 BOOL WINAPI RemoveFontMemResourceEx( HANDLE fh )
3056 FIXME("(%p) stub\n", fh);
3057 return TRUE;
3060 /***********************************************************************
3061 * RemoveFontResourceExA (GDI32.@)
3063 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3065 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3066 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3067 INT ret;
3069 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3070 ret = RemoveFontResourceExW(strW, fl, pdv);
3071 HeapFree(GetProcessHeap(), 0, strW);
3072 return ret;
3075 /***********************************************************************
3076 * RemoveFontResourceExW (GDI32.@)
3078 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3080 return WineEngRemoveFontResourceEx(str, fl, pdv);
3083 /***********************************************************************
3084 * GetTextCharset (GDI32.@)
3086 UINT WINAPI GetTextCharset(HDC hdc)
3088 /* MSDN docs say this is equivalent */
3089 return GetTextCharsetInfo(hdc, NULL, 0);
3092 /***********************************************************************
3093 * GetTextCharsetInfo (GDI32.@)
3095 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3097 UINT ret = DEFAULT_CHARSET;
3098 DC *dc = get_dc_ptr(hdc);
3100 if (dc)
3102 if (dc->gdiFont)
3103 ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
3105 release_dc_ptr( dc );
3108 if (ret == DEFAULT_CHARSET && fs)
3109 memset(fs, 0, sizeof(FONTSIGNATURE));
3110 return ret;
3113 /***********************************************************************
3114 * GdiGetCharDimensions (GDI32.@)
3116 * Gets the average width of the characters in the English alphabet.
3118 * PARAMS
3119 * hdc [I] Handle to the device context to measure on.
3120 * lptm [O] Pointer to memory to store the text metrics into.
3121 * height [O] On exit, the maximum height of characters in the English alphabet.
3123 * RETURNS
3124 * The average width of characters in the English alphabet.
3126 * NOTES
3127 * This function is used by the dialog manager to get the size of a dialog
3128 * unit. It should also be used by other pieces of code that need to know
3129 * the size of a dialog unit in logical units without having access to the
3130 * window handle of the dialog.
3131 * Windows caches the font metrics from this function, but we don't and
3132 * there doesn't appear to be an immediate advantage to do so.
3134 * SEE ALSO
3135 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3137 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3139 SIZE sz;
3140 static const WCHAR alphabet[] = {
3141 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3142 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3143 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3145 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3147 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3149 if (height) *height = sz.cy;
3150 return (sz.cx / 26 + 1) / 2;
3153 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3155 FIXME("(%d): stub\n", fEnableEUDC);
3156 return FALSE;
3159 /***********************************************************************
3160 * GetCharWidthI (GDI32.@)
3162 * Retrieve widths of characters.
3164 * PARAMS
3165 * hdc [I] Handle to a device context.
3166 * first [I] First glyph in range to query.
3167 * count [I] Number of glyph indices to query.
3168 * glyphs [I] Array of glyphs to query.
3169 * buffer [O] Buffer to receive character widths.
3171 * NOTES
3172 * Only works with TrueType fonts.
3174 * RETURNS
3175 * Success: TRUE
3176 * Failure: FALSE
3178 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3180 ABC *abc;
3181 unsigned int i;
3183 TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3185 if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3186 return FALSE;
3188 if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3190 HeapFree(GetProcessHeap(), 0, abc);
3191 return FALSE;
3194 for (i = 0; i < count; i++)
3195 buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3197 HeapFree(GetProcessHeap(), 0, abc);
3198 return TRUE;
3201 /***********************************************************************
3202 * GetFontUnicodeRanges (GDI32.@)
3204 * Retrieve a list of supported Unicode characters in a font.
3206 * PARAMS
3207 * hdc [I] Handle to a device context.
3208 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3210 * RETURNS
3211 * Success: Number of bytes written to the buffer pointed to by lpgs.
3212 * Failure: 0
3215 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3217 DWORD ret = 0;
3218 DC *dc = get_dc_ptr(hdc);
3220 TRACE("(%p, %p)\n", hdc, lpgs);
3222 if (!dc) return 0;
3224 if (dc->gdiFont) ret = WineEngGetFontUnicodeRanges(dc->gdiFont, lpgs);
3225 release_dc_ptr(dc);
3226 return ret;
3230 /*************************************************************
3231 * FontIsLinked (GDI32.@)
3233 BOOL WINAPI FontIsLinked(HDC hdc)
3235 DC *dc = get_dc_ptr(hdc);
3236 BOOL ret = FALSE;
3238 if (!dc) return FALSE;
3239 if (dc->gdiFont) ret = WineEngFontIsLinked(dc->gdiFont);
3240 release_dc_ptr(dc);
3241 TRACE("returning %d\n", ret);
3242 return ret;
3245 /*************************************************************
3246 * GdiRealizationInfo (GDI32.@)
3248 * Returns a structure that contains some font information.
3250 typedef struct
3252 DWORD flags; /* 1 for bitmap fonts, 3 for scalable fonts */
3253 DWORD unknown1; /* keeps incrementing - num of fonts that have been created or selected into a dc ?? */
3254 DWORD unknown2; /* fixed for a given font - looks like it could be the order of the face in the font list or the order
3255 in which the face was first rendered. */
3256 } realization_info_t;
3258 BOOL WINAPI GdiRealizationInfo(HDC hdc, realization_info_t *info)
3260 UINT otm_size;
3261 FIXME("(%p, %p): stub!\n", hdc, info);
3263 info->flags = 1;
3264 otm_size = GetOutlineTextMetricsW(hdc, 0, NULL);
3265 if(otm_size) info->flags |= 2; /* scalable */
3267 info->unknown1 = -1;
3268 info->unknown2 = -1;
3269 return TRUE;