msi/tests: Move test coverage for standard actions to a separate module.
[wine.git] / dlls / gdi32 / font.c
blobb247722b91368d6f6ac6d6103692e5594ee9cc92
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/exception.h"
37 #include "wine/unicode.h"
38 #include "wine/debug.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(font);
42 /* Device -> World size conversion */
44 /* Performs a device to world transformation on the specified width (which
45 * is in integer format).
47 static inline INT INTERNAL_XDSTOWS(DC *dc, INT width)
49 double floatWidth;
51 /* Perform operation with floating point */
52 floatWidth = (double)width * dc->xformVport2World.eM11;
53 /* Round to integers */
54 return GDI_ROUND(floatWidth);
57 /* Performs a device to world transformation on the specified size (which
58 * is in integer format).
60 static inline INT INTERNAL_YDSTOWS(DC *dc, INT height)
62 double floatHeight;
64 /* Perform operation with floating point */
65 floatHeight = (double)height * dc->xformVport2World.eM22;
66 /* Round to integers */
67 return GDI_ROUND(floatHeight);
70 static inline INT INTERNAL_XWSTODS(DC *dc, INT width)
72 POINT pt[2];
73 pt[0].x = pt[0].y = 0;
74 pt[1].x = width;
75 pt[1].y = 0;
76 LPtoDP(dc->hSelf, pt, 2);
77 return pt[1].x - pt[0].x;
80 static inline INT INTERNAL_YWSTODS(DC *dc, INT height)
82 POINT pt[2];
83 pt[0].x = pt[0].y = 0;
84 pt[1].x = 0;
85 pt[1].y = height;
86 LPtoDP(dc->hSelf, pt, 2);
87 return pt[1].y - pt[0].y;
90 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc );
91 static INT FONT_GetObjectA( HGDIOBJ handle, INT count, LPVOID buffer );
92 static INT FONT_GetObjectW( HGDIOBJ handle, INT count, LPVOID buffer );
93 static BOOL FONT_DeleteObject( HGDIOBJ handle );
95 static const struct gdi_obj_funcs font_funcs =
97 FONT_SelectObject, /* pSelectObject */
98 FONT_GetObjectA, /* pGetObjectA */
99 FONT_GetObjectW, /* pGetObjectW */
100 NULL, /* pUnrealizeObject */
101 FONT_DeleteObject /* pDeleteObject */
104 #define ENUM_UNICODE 0x00000001
105 #define ENUM_CALLED 0x00000002
107 typedef struct
109 GDIOBJHDR header;
110 LOGFONTW logfont;
111 } FONTOBJ;
113 typedef struct
115 LPLOGFONTW lpLogFontParam;
116 FONTENUMPROCW lpEnumFunc;
117 LPARAM lpData;
118 DWORD dwFlags;
119 HDC hdc;
120 } fontEnum32;
123 * For TranslateCharsetInfo
125 #define MAXTCIINDEX 32
126 static const CHARSETINFO FONT_tci[MAXTCIINDEX] = {
127 /* ANSI */
128 { ANSI_CHARSET, 1252, {{0,0,0,0},{FS_LATIN1,0}} },
129 { EASTEUROPE_CHARSET, 1250, {{0,0,0,0},{FS_LATIN2,0}} },
130 { RUSSIAN_CHARSET, 1251, {{0,0,0,0},{FS_CYRILLIC,0}} },
131 { GREEK_CHARSET, 1253, {{0,0,0,0},{FS_GREEK,0}} },
132 { TURKISH_CHARSET, 1254, {{0,0,0,0},{FS_TURKISH,0}} },
133 { HEBREW_CHARSET, 1255, {{0,0,0,0},{FS_HEBREW,0}} },
134 { ARABIC_CHARSET, 1256, {{0,0,0,0},{FS_ARABIC,0}} },
135 { BALTIC_CHARSET, 1257, {{0,0,0,0},{FS_BALTIC,0}} },
136 { VIETNAMESE_CHARSET, 1258, {{0,0,0,0},{FS_VIETNAMESE,0}} },
137 /* reserved by ANSI */
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 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
145 /* ANSI and OEM */
146 { THAI_CHARSET, 874, {{0,0,0,0},{FS_THAI,0}} },
147 { SHIFTJIS_CHARSET, 932, {{0,0,0,0},{FS_JISJAPAN,0}} },
148 { GB2312_CHARSET, 936, {{0,0,0,0},{FS_CHINESESIMP,0}} },
149 { HANGEUL_CHARSET, 949, {{0,0,0,0},{FS_WANSUNG,0}} },
150 { CHINESEBIG5_CHARSET, 950, {{0,0,0,0},{FS_CHINESETRAD,0}} },
151 { JOHAB_CHARSET, 1361, {{0,0,0,0},{FS_JOHAB,0}} },
152 /* reserved for alternate ANSI and OEM */
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 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
161 /* reserved for system */
162 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
163 { SYMBOL_CHARSET, CP_SYMBOL, {{0,0,0,0},{FS_SYMBOL,0}} }
166 static void FONT_LogFontAToW( const LOGFONTA *fontA, LPLOGFONTW fontW )
168 memcpy(fontW, fontA, sizeof(LOGFONTA) - LF_FACESIZE);
169 MultiByteToWideChar(CP_ACP, 0, fontA->lfFaceName, -1, fontW->lfFaceName,
170 LF_FACESIZE);
171 fontW->lfFaceName[LF_FACESIZE-1] = 0;
174 static void FONT_LogFontWToA( const LOGFONTW *fontW, LPLOGFONTA fontA )
176 memcpy(fontA, fontW, sizeof(LOGFONTA) - LF_FACESIZE);
177 WideCharToMultiByte(CP_ACP, 0, fontW->lfFaceName, -1, fontA->lfFaceName,
178 LF_FACESIZE, NULL, NULL);
179 fontA->lfFaceName[LF_FACESIZE-1] = 0;
182 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEXA fontA )
184 FONT_LogFontWToA( &fontW->elfLogFont, &fontA->elfLogFont );
186 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
187 (LPSTR) fontA->elfFullName, LF_FULLFACESIZE, NULL, NULL );
188 fontA->elfFullName[LF_FULLFACESIZE-1] = '\0';
189 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
190 (LPSTR) fontA->elfStyle, LF_FACESIZE, NULL, NULL );
191 fontA->elfStyle[LF_FACESIZE-1] = '\0';
192 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
193 (LPSTR) fontA->elfScript, LF_FACESIZE, NULL, NULL );
194 fontA->elfScript[LF_FACESIZE-1] = '\0';
197 static void FONT_EnumLogFontExAToW( const ENUMLOGFONTEXA *fontA, LPENUMLOGFONTEXW fontW )
199 FONT_LogFontAToW( &fontA->elfLogFont, &fontW->elfLogFont );
201 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfFullName, -1,
202 fontW->elfFullName, LF_FULLFACESIZE );
203 fontW->elfFullName[LF_FULLFACESIZE-1] = '\0';
204 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfStyle, -1,
205 fontW->elfStyle, LF_FACESIZE );
206 fontW->elfStyle[LF_FACESIZE-1] = '\0';
207 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfScript, -1,
208 fontW->elfScript, LF_FACESIZE );
209 fontW->elfScript[LF_FACESIZE-1] = '\0';
212 /***********************************************************************
213 * TEXTMETRIC conversion functions.
215 static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
217 ptmA->tmHeight = ptmW->tmHeight;
218 ptmA->tmAscent = ptmW->tmAscent;
219 ptmA->tmDescent = ptmW->tmDescent;
220 ptmA->tmInternalLeading = ptmW->tmInternalLeading;
221 ptmA->tmExternalLeading = ptmW->tmExternalLeading;
222 ptmA->tmAveCharWidth = ptmW->tmAveCharWidth;
223 ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth;
224 ptmA->tmWeight = ptmW->tmWeight;
225 ptmA->tmOverhang = ptmW->tmOverhang;
226 ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX;
227 ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
228 ptmA->tmFirstChar = min(ptmW->tmFirstChar, 255);
229 if (ptmW->tmCharSet == SYMBOL_CHARSET)
231 ptmA->tmFirstChar = 0x1e;
232 ptmA->tmLastChar = 0xff; /* win9x behaviour - we need the OS2 table data to calculate correctly */
234 else
236 ptmA->tmFirstChar = ptmW->tmDefaultChar - 1;
237 ptmA->tmLastChar = min(ptmW->tmLastChar, 0xff);
239 ptmA->tmDefaultChar = ptmW->tmDefaultChar;
240 ptmA->tmBreakChar = ptmW->tmBreakChar;
241 ptmA->tmItalic = ptmW->tmItalic;
242 ptmA->tmUnderlined = ptmW->tmUnderlined;
243 ptmA->tmStruckOut = ptmW->tmStruckOut;
244 ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
245 ptmA->tmCharSet = ptmW->tmCharSet;
249 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW *ptmW, NEWTEXTMETRICEXA *ptmA )
251 FONT_TextMetricWToA((const TEXTMETRICW *)ptmW, (LPTEXTMETRICA)ptmA);
252 ptmA->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
253 ptmA->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
254 ptmA->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
255 ptmA->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
256 memcpy(&ptmA->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
260 /***********************************************************************
261 * GdiGetCodePage (GDI32.@)
263 DWORD WINAPI GdiGetCodePage( HDC hdc )
265 UINT cp = CP_ACP;
266 DC *dc = get_dc_ptr( hdc );
268 if (dc)
270 cp = dc->font_code_page;
271 release_dc_ptr( dc );
273 return cp;
276 /***********************************************************************
277 * FONT_mbtowc
279 * Returns a Unicode translation of str using the charset of the
280 * currently selected font in hdc. If count is -1 then str is assumed
281 * to be '\0' terminated, otherwise it contains the number of bytes to
282 * convert. If plenW is non-NULL, on return it will point to the
283 * number of WCHARs that have been written. If pCP is non-NULL, on
284 * return it will point to the codepage used in the conversion. The
285 * caller should free the returned LPWSTR from the process heap
286 * itself.
288 static LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
290 UINT cp;
291 INT lenW;
292 LPWSTR strW;
294 cp = GdiGetCodePage( hdc );
296 if(count == -1) count = strlen(str);
297 lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
298 strW = HeapAlloc(GetProcessHeap(), 0, lenW*sizeof(WCHAR));
299 MultiByteToWideChar(cp, 0, str, count, strW, lenW);
300 TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW));
301 if(plenW) *plenW = lenW;
302 if(pCP) *pCP = cp;
303 return strW;
306 /***********************************************************************
307 * CreateFontIndirectExA (GDI32.@)
309 HFONT WINAPI CreateFontIndirectExA( const ENUMLOGFONTEXDVA *penumexA )
311 ENUMLOGFONTEXDVW enumexW;
313 if (!penumexA) return 0;
315 FONT_EnumLogFontExAToW( &penumexA->elfEnumLogfontEx, &enumexW.elfEnumLogfontEx );
316 enumexW.elfDesignVector = penumexA->elfDesignVector;
317 return CreateFontIndirectExW( &enumexW );
320 /***********************************************************************
321 * CreateFontIndirectExW (GDI32.@)
323 HFONT WINAPI CreateFontIndirectExW( const ENUMLOGFONTEXDVW *penumex )
325 HFONT hFont;
326 FONTOBJ *fontPtr;
327 const LOGFONTW *plf;
329 if (!penumex) return 0;
331 if (penumex->elfEnumLogfontEx.elfFullName[0] ||
332 penumex->elfEnumLogfontEx.elfStyle[0] ||
333 penumex->elfEnumLogfontEx.elfScript[0])
335 FIXME("some fields ignored. fullname=%s, style=%s, script=%s\n",
336 debugstr_w(penumex->elfEnumLogfontEx.elfFullName),
337 debugstr_w(penumex->elfEnumLogfontEx.elfStyle),
338 debugstr_w(penumex->elfEnumLogfontEx.elfScript));
341 plf = &penumex->elfEnumLogfontEx.elfLogFont;
342 if (!(fontPtr = HeapAlloc( GetProcessHeap(), 0, sizeof(*fontPtr) ))) return 0;
344 fontPtr->logfont = *plf;
346 if (plf->lfEscapement != plf->lfOrientation)
348 /* this should really depend on whether GM_ADVANCED is set */
349 fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
350 WARN("orientation angle %f set to "
351 "escapement angle %f for new font %p\n",
352 plf->lfOrientation/10., plf->lfEscapement/10., fontPtr);
355 if (!(hFont = alloc_gdi_handle( &fontPtr->header, OBJ_FONT, &font_funcs )))
357 HeapFree( GetProcessHeap(), 0, fontPtr );
358 return 0;
361 TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
362 plf->lfHeight, plf->lfWidth,
363 plf->lfEscapement, plf->lfOrientation,
364 plf->lfPitchAndFamily,
365 plf->lfOutPrecision, plf->lfClipPrecision,
366 plf->lfQuality, plf->lfCharSet,
367 debugstr_w(plf->lfFaceName),
368 plf->lfWeight > 400 ? "Bold" : "",
369 plf->lfItalic ? "Italic" : "",
370 plf->lfUnderline ? "Underline" : "", hFont);
372 return hFont;
375 /***********************************************************************
376 * CreateFontIndirectA (GDI32.@)
378 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *plfA )
380 LOGFONTW lfW;
382 if (!plfA) return 0;
384 FONT_LogFontAToW( plfA, &lfW );
385 return CreateFontIndirectW( &lfW );
388 /***********************************************************************
389 * CreateFontIndirectW (GDI32.@)
391 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
393 ENUMLOGFONTEXDVW exdv;
395 if (!plf) return 0;
397 exdv.elfEnumLogfontEx.elfLogFont = *plf;
398 exdv.elfEnumLogfontEx.elfFullName[0] = 0;
399 exdv.elfEnumLogfontEx.elfStyle[0] = 0;
400 exdv.elfEnumLogfontEx.elfScript[0] = 0;
401 return CreateFontIndirectExW( &exdv );
404 /*************************************************************************
405 * CreateFontA (GDI32.@)
407 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
408 INT orient, INT weight, DWORD italic,
409 DWORD underline, DWORD strikeout, DWORD charset,
410 DWORD outpres, DWORD clippres, DWORD quality,
411 DWORD pitch, LPCSTR name )
413 LOGFONTA logfont;
415 logfont.lfHeight = height;
416 logfont.lfWidth = width;
417 logfont.lfEscapement = esc;
418 logfont.lfOrientation = orient;
419 logfont.lfWeight = weight;
420 logfont.lfItalic = italic;
421 logfont.lfUnderline = underline;
422 logfont.lfStrikeOut = strikeout;
423 logfont.lfCharSet = charset;
424 logfont.lfOutPrecision = outpres;
425 logfont.lfClipPrecision = clippres;
426 logfont.lfQuality = quality;
427 logfont.lfPitchAndFamily = pitch;
429 if (name)
430 lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
431 else
432 logfont.lfFaceName[0] = '\0';
434 return CreateFontIndirectA( &logfont );
437 /*************************************************************************
438 * CreateFontW (GDI32.@)
440 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
441 INT orient, INT weight, DWORD italic,
442 DWORD underline, DWORD strikeout, DWORD charset,
443 DWORD outpres, DWORD clippres, DWORD quality,
444 DWORD pitch, LPCWSTR name )
446 LOGFONTW logfont;
448 logfont.lfHeight = height;
449 logfont.lfWidth = width;
450 logfont.lfEscapement = esc;
451 logfont.lfOrientation = orient;
452 logfont.lfWeight = weight;
453 logfont.lfItalic = italic;
454 logfont.lfUnderline = underline;
455 logfont.lfStrikeOut = strikeout;
456 logfont.lfCharSet = charset;
457 logfont.lfOutPrecision = outpres;
458 logfont.lfClipPrecision = clippres;
459 logfont.lfQuality = quality;
460 logfont.lfPitchAndFamily = pitch;
462 if (name)
463 lstrcpynW(logfont.lfFaceName, name,
464 sizeof(logfont.lfFaceName) / sizeof(WCHAR));
465 else
466 logfont.lfFaceName[0] = '\0';
468 return CreateFontIndirectW( &logfont );
471 static void update_font_code_page( DC *dc )
473 CHARSETINFO csi;
474 int charset = DEFAULT_CHARSET;
476 if (dc->gdiFont)
477 charset = WineEngGetTextCharsetInfo( dc->gdiFont, NULL, 0 );
479 /* Hmm, nicely designed api this one! */
480 if (TranslateCharsetInfo( ULongToPtr(charset), &csi, TCI_SRCCHARSET) )
481 dc->font_code_page = csi.ciACP;
482 else {
483 switch(charset) {
484 case OEM_CHARSET:
485 dc->font_code_page = GetOEMCP();
486 break;
487 case DEFAULT_CHARSET:
488 dc->font_code_page = GetACP();
489 break;
491 case VISCII_CHARSET:
492 case TCVN_CHARSET:
493 case KOI8_CHARSET:
494 case ISO3_CHARSET:
495 case ISO4_CHARSET:
496 case ISO10_CHARSET:
497 case CELTIC_CHARSET:
498 /* FIXME: These have no place here, but because x11drv
499 enumerates fonts with these (made up) charsets some apps
500 might use them and then the FIXME below would become
501 annoying. Now we could pick the intended codepage for
502 each of these, but since it's broken anyway we'll just
503 use CP_ACP and hope it'll go away...
505 dc->font_code_page = CP_ACP;
506 break;
508 default:
509 FIXME("Can't find codepage for charset %d\n", charset);
510 dc->font_code_page = CP_ACP;
511 break;
515 TRACE("charset %d => cp %d\n", charset, dc->font_code_page);
518 /***********************************************************************
519 * FONT_SelectObject
521 * If the driver supports vector fonts we create a gdi font first and
522 * then call the driver to give it a chance to supply its own device
523 * font. If the driver wants to do this it returns TRUE and we can
524 * delete the gdi font, if the driver wants to use the gdi font it
525 * should return FALSE, to signal an error return GDI_ERROR. For
526 * drivers that don't support vector fonts they must supply their own
527 * font.
529 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc )
531 HGDIOBJ ret = 0;
532 DC *dc = get_dc_ptr( hdc );
534 if (!dc) return 0;
536 if (!GDI_inc_ref_count( handle ))
538 release_dc_ptr( dc );
539 return 0;
542 if (GetDeviceCaps( dc->hSelf, TEXTCAPS ) & TC_VA_ABLE)
543 dc->gdiFont = WineEngCreateFontInstance( dc, handle );
545 if (dc->funcs->pSelectFont) ret = dc->funcs->pSelectFont( dc->physDev, handle, dc->gdiFont );
547 if (ret && dc->gdiFont) dc->gdiFont = 0;
549 if (ret == HGDI_ERROR)
551 GDI_dec_ref_count( handle );
552 ret = 0; /* SelectObject returns 0 on error */
554 else
556 ret = dc->hFont;
557 dc->hFont = handle;
558 update_font_code_page( dc );
559 GDI_dec_ref_count( ret );
561 release_dc_ptr( dc );
562 return ret;
566 /***********************************************************************
567 * FONT_GetObjectA
569 static INT FONT_GetObjectA( HGDIOBJ handle, INT count, LPVOID buffer )
571 FONTOBJ *font = GDI_GetObjPtr( handle, OBJ_FONT );
572 LOGFONTA lfA;
574 if (!font) return 0;
575 if (buffer)
577 FONT_LogFontWToA( &font->logfont, &lfA );
578 if (count > sizeof(lfA)) count = sizeof(lfA);
579 memcpy( buffer, &lfA, count );
581 else count = sizeof(lfA);
582 GDI_ReleaseObj( handle );
583 return count;
586 /***********************************************************************
587 * FONT_GetObjectW
589 static INT FONT_GetObjectW( HGDIOBJ handle, INT count, LPVOID buffer )
591 FONTOBJ *font = GDI_GetObjPtr( handle, OBJ_FONT );
593 if (!font) return 0;
594 if (buffer)
596 if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
597 memcpy( buffer, &font->logfont, count );
599 else count = sizeof(LOGFONTW);
600 GDI_ReleaseObj( handle );
601 return count;
605 /***********************************************************************
606 * FONT_DeleteObject
608 static BOOL FONT_DeleteObject( HGDIOBJ handle )
610 FONTOBJ *obj;
612 WineEngDestroyFontInstance( handle );
614 if (!(obj = free_gdi_handle( handle ))) return FALSE;
615 return HeapFree( GetProcessHeap(), 0, obj );
619 /***********************************************************************
620 * FONT_EnumInstance
622 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
623 * We have to use other types because of the FONTENUMPROCW definition.
625 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
626 DWORD fType, LPARAM lp )
628 fontEnum32 *pfe = (fontEnum32*)lp;
629 INT ret = 1;
631 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
632 if ((!pfe->lpLogFontParam ||
633 pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
634 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
635 (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
637 /* convert font metrics */
638 ENUMLOGFONTEXA logfont;
639 NEWTEXTMETRICEXA tmA;
641 pfe->dwFlags |= ENUM_CALLED;
642 if (!(pfe->dwFlags & ENUM_UNICODE))
644 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
645 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
646 plf = (LOGFONTW *)&logfont.elfLogFont;
647 ptm = (TEXTMETRICW *)&tmA;
650 ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
652 return ret;
655 /***********************************************************************
656 * FONT_EnumFontFamiliesEx
658 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf,
659 FONTENUMPROCW efproc,
660 LPARAM lParam, DWORD dwUnicode)
662 INT ret = 1, ret2;
663 DC *dc = get_dc_ptr( hDC );
664 fontEnum32 fe32;
665 BOOL enum_gdi_fonts;
667 if (!dc) return 0;
669 if (plf)
670 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName),
671 plf->lfCharSet);
672 fe32.lpLogFontParam = plf;
673 fe32.lpEnumFunc = efproc;
674 fe32.lpData = lParam;
675 fe32.dwFlags = dwUnicode;
676 fe32.hdc = hDC;
678 enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE;
680 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
682 ret = 0;
683 goto done;
686 if (enum_gdi_fonts)
687 ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
688 fe32.dwFlags &= ~ENUM_CALLED;
689 if (ret && dc->funcs->pEnumDeviceFonts) {
690 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, plf, FONT_EnumInstance, (LPARAM)&fe32 );
691 if(fe32.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
692 ret = ret2;
694 done:
695 release_dc_ptr( dc );
696 return ret;
699 /***********************************************************************
700 * EnumFontFamiliesExW (GDI32.@)
702 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
703 FONTENUMPROCW efproc,
704 LPARAM lParam, DWORD dwFlags )
706 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, ENUM_UNICODE );
709 /***********************************************************************
710 * EnumFontFamiliesExA (GDI32.@)
712 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
713 FONTENUMPROCA efproc,
714 LPARAM lParam, DWORD dwFlags)
716 LOGFONTW lfW, *plfW;
718 if (plf)
720 FONT_LogFontAToW( plf, &lfW );
721 plfW = &lfW;
723 else plfW = NULL;
725 return FONT_EnumFontFamiliesEx( hDC, plfW, (FONTENUMPROCW)efproc, lParam, 0);
728 /***********************************************************************
729 * EnumFontFamiliesA (GDI32.@)
731 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
732 FONTENUMPROCA efproc, LPARAM lpData )
734 LOGFONTA lf, *plf;
736 if (lpFamily)
738 if (!*lpFamily) return 1;
739 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
740 lf.lfCharSet = DEFAULT_CHARSET;
741 lf.lfPitchAndFamily = 0;
742 plf = &lf;
744 else plf = NULL;
746 return EnumFontFamiliesExA( hDC, plf, efproc, lpData, 0 );
749 /***********************************************************************
750 * EnumFontFamiliesW (GDI32.@)
752 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
753 FONTENUMPROCW efproc, LPARAM lpData )
755 LOGFONTW lf, *plf;
757 if (lpFamily)
759 if (!*lpFamily) return 1;
760 lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
761 lf.lfCharSet = DEFAULT_CHARSET;
762 lf.lfPitchAndFamily = 0;
763 plf = &lf;
765 else plf = NULL;
767 return EnumFontFamiliesExW( hDC, plf, efproc, lpData, 0 );
770 /***********************************************************************
771 * EnumFontsA (GDI32.@)
773 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
774 LPARAM lpData )
776 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
779 /***********************************************************************
780 * EnumFontsW (GDI32.@)
782 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
783 LPARAM lpData )
785 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
789 /***********************************************************************
790 * GetTextCharacterExtra (GDI32.@)
792 INT WINAPI GetTextCharacterExtra( HDC hdc )
794 INT ret;
795 DC *dc = get_dc_ptr( hdc );
796 if (!dc) return 0x80000000;
797 ret = dc->charExtra;
798 release_dc_ptr( dc );
799 return ret;
803 /***********************************************************************
804 * SetTextCharacterExtra (GDI32.@)
806 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
808 INT prev;
809 DC * dc = get_dc_ptr( hdc );
810 if (!dc) return 0x80000000;
811 if (dc->funcs->pSetTextCharacterExtra)
812 prev = dc->funcs->pSetTextCharacterExtra( dc->physDev, extra );
813 else
815 prev = dc->charExtra;
816 dc->charExtra = extra;
818 release_dc_ptr( dc );
819 return prev;
823 /***********************************************************************
824 * SetTextJustification (GDI32.@)
826 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
828 BOOL ret = TRUE;
829 DC * dc = get_dc_ptr( hdc );
830 if (!dc) return FALSE;
831 if (dc->funcs->pSetTextJustification)
832 ret = dc->funcs->pSetTextJustification( dc->physDev, extra, breaks );
833 else
835 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
836 if (!extra) breaks = 0;
837 if (breaks)
839 dc->breakExtra = extra / breaks;
840 dc->breakRem = extra - (breaks * dc->breakExtra);
842 else
844 dc->breakExtra = 0;
845 dc->breakRem = 0;
848 release_dc_ptr( dc );
849 return ret;
853 /***********************************************************************
854 * GetTextFaceA (GDI32.@)
856 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
858 INT res = GetTextFaceW(hdc, 0, NULL);
859 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
860 GetTextFaceW( hdc, res, nameW );
862 if (name)
864 if (count)
866 res = WideCharToMultiByte(CP_ACP, 0, nameW, -1, name, count, NULL, NULL);
867 if (res == 0)
868 res = count;
869 name[count-1] = 0;
870 /* GetTextFaceA does NOT include the nul byte in the return count. */
871 res--;
873 else
874 res = 0;
876 else
877 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
878 HeapFree( GetProcessHeap(), 0, nameW );
879 return res;
882 /***********************************************************************
883 * GetTextFaceW (GDI32.@)
885 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
887 FONTOBJ *font;
888 INT ret = 0;
890 DC * dc = get_dc_ptr( hdc );
891 if (!dc) return 0;
893 if(dc->gdiFont)
894 ret = WineEngGetTextFace(dc->gdiFont, count, name);
895 else if ((font = GDI_GetObjPtr( dc->hFont, OBJ_FONT )))
897 INT n = strlenW(font->logfont.lfFaceName) + 1;
898 if (name)
900 lstrcpynW( name, font->logfont.lfFaceName, count );
901 ret = min(count, n);
903 else ret = n;
904 GDI_ReleaseObj( dc->hFont );
906 release_dc_ptr( dc );
907 return ret;
911 /***********************************************************************
912 * GetTextExtentPoint32A (GDI32.@)
914 * See GetTextExtentPoint32W.
916 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
917 LPSIZE size )
919 BOOL ret = FALSE;
920 INT wlen;
921 LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
923 if (p) {
924 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
925 HeapFree( GetProcessHeap(), 0, p );
928 TRACE("(%p %s %d %p): returning %d x %d\n",
929 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
930 return ret;
934 /***********************************************************************
935 * GetTextExtentPoint32W [GDI32.@]
937 * Computes width/height for a string.
939 * Computes width and height of the specified string.
941 * RETURNS
942 * Success: TRUE
943 * Failure: FALSE
945 BOOL WINAPI GetTextExtentPoint32W(
946 HDC hdc, /* [in] Handle of device context */
947 LPCWSTR str, /* [in] Address of text string */
948 INT count, /* [in] Number of characters in string */
949 LPSIZE size) /* [out] Address of structure for string size */
951 return GetTextExtentExPointW(hdc, str, count, 0, NULL, NULL, size);
954 /***********************************************************************
955 * GetTextExtentExPointI [GDI32.@]
957 * Computes width and height of the array of glyph indices.
959 * PARAMS
960 * hdc [I] Handle of device context.
961 * indices [I] Glyph index array.
962 * count [I] Number of glyphs in array.
963 * max_ext [I] Maximum width in glyphs.
964 * nfit [O] Maximum number of characters.
965 * dxs [O] Partial string widths.
966 * size [O] Returned string size.
968 * RETURNS
969 * Success: TRUE
970 * Failure: FALSE
972 BOOL WINAPI GetTextExtentExPointI( HDC hdc, const WORD *indices, INT count, INT max_ext,
973 LPINT nfit, LPINT dxs, LPSIZE size )
975 BOOL ret = FALSE;
976 DC * dc = get_dc_ptr( hdc );
977 if (!dc) return FALSE;
979 if(dc->gdiFont) {
980 ret = WineEngGetTextExtentExPointI(dc->gdiFont, indices, count, max_ext, nfit, dxs, size);
981 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
982 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
983 size->cx += count * dc->charExtra;
985 else if(dc->funcs->pGetTextExtentExPoint) {
986 FIXME("calling GetTextExtentExPoint\n");
987 ret = dc->funcs->pGetTextExtentExPoint( dc->physDev, indices, count,
988 max_ext, nfit, dxs, size );
991 release_dc_ptr( dc );
993 TRACE("(%p %p %d %p): returning %d x %d\n",
994 hdc, indices, count, size, size->cx, size->cy );
995 return ret;
998 /***********************************************************************
999 * GetTextExtentPointI [GDI32.@]
1001 * Computes width and height of the array of glyph indices.
1003 * PARAMS
1004 * hdc [I] Handle of device context.
1005 * indices [I] Glyph index array.
1006 * count [I] Number of glyphs in array.
1007 * size [O] Returned string size.
1009 * RETURNS
1010 * Success: TRUE
1011 * Failure: FALSE
1013 BOOL WINAPI GetTextExtentPointI( HDC hdc, const WORD *indices, INT count, LPSIZE size )
1015 return GetTextExtentExPointI( hdc, indices, count, 0, NULL, NULL, size );
1019 /***********************************************************************
1020 * GetTextExtentPointA (GDI32.@)
1022 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
1023 LPSIZE size )
1025 TRACE("not bug compatible.\n");
1026 return GetTextExtentPoint32A( hdc, str, count, size );
1029 /***********************************************************************
1030 * GetTextExtentPointW (GDI32.@)
1032 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1033 LPSIZE size )
1035 TRACE("not bug compatible.\n");
1036 return GetTextExtentPoint32W( hdc, str, count, size );
1040 /***********************************************************************
1041 * GetTextExtentExPointA (GDI32.@)
1043 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1044 INT maxExt, LPINT lpnFit,
1045 LPINT alpDx, LPSIZE size )
1047 BOOL ret;
1048 INT wlen;
1049 INT *walpDx = NULL;
1050 LPWSTR p = NULL;
1052 if (alpDx &&
1053 NULL == (walpDx = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT))))
1054 return FALSE;
1056 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1057 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
1058 if (walpDx)
1060 INT n = lpnFit ? *lpnFit : wlen;
1061 INT i, j;
1062 for(i = 0, j = 0; i < n; i++, j++)
1064 alpDx[j] = walpDx[i];
1065 if (IsDBCSLeadByte(str[j])) alpDx[++j] = walpDx[i];
1068 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1069 HeapFree( GetProcessHeap(), 0, p );
1070 HeapFree( GetProcessHeap(), 0, walpDx );
1071 return ret;
1075 /***********************************************************************
1076 * GetTextExtentExPointW (GDI32.@)
1078 * Return the size of the string as it would be if it was output properly by
1079 * e.g. TextOut.
1081 * This should include
1082 * - Intercharacter spacing
1083 * - justification spacing (not yet done)
1084 * - kerning? see below
1086 * Kerning. Since kerning would be carried out by the rendering code it should
1087 * be done by the driver. However they don't support it yet. Also I am not
1088 * yet persuaded that (certainly under Win95) any kerning is actually done.
1090 * str: According to MSDN this should be null-terminated. That is not true; a
1091 * null will not terminate it early.
1092 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1093 * than count. I have seen it be either the size of the full string or
1094 * 1 less than the size of the full string. I have not seen it bear any
1095 * resemblance to the portion that would fit.
1096 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1097 * trailing intercharacter spacing and any trailing justification.
1099 * FIXME
1100 * Currently we do this by measuring each character etc. We should do it by
1101 * passing the request to the driver, perhaps by extending the
1102 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1103 * thinking about kerning issues and rounding issues in the justification.
1106 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1107 INT maxExt, LPINT lpnFit,
1108 LPINT alpDx, LPSIZE size )
1110 INT nFit = 0;
1111 LPINT dxs = NULL;
1112 DC *dc;
1113 BOOL ret = FALSE;
1114 TEXTMETRICW tm;
1116 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1118 dc = get_dc_ptr(hdc);
1119 if (! dc)
1120 return FALSE;
1122 GetTextMetricsW(hdc, &tm);
1124 /* If we need to calculate nFit, then we need the partial extents even if
1125 the user hasn't provided us with an array. */
1126 if (lpnFit)
1128 dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]);
1129 if (! dxs)
1131 release_dc_ptr(dc);
1132 SetLastError(ERROR_OUTOFMEMORY);
1133 return FALSE;
1136 else
1137 dxs = alpDx;
1139 if (dc->gdiFont)
1140 ret = WineEngGetTextExtentExPoint(dc->gdiFont, str, count,
1141 0, NULL, dxs, size);
1142 else if (dc->funcs->pGetTextExtentExPoint)
1143 ret = dc->funcs->pGetTextExtentExPoint(dc->physDev, str, count,
1144 0, NULL, dxs, size);
1146 /* Perform device size to world size transformations. */
1147 if (ret)
1149 INT extra = dc->charExtra,
1150 breakExtra = dc->breakExtra,
1151 breakRem = dc->breakRem,
1154 if (dxs)
1156 for (i = 0; i < count; ++i)
1158 dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
1159 dxs[i] += (i+1) * extra;
1160 if (count > 1 && (breakExtra || breakRem) && str[i] == tm.tmBreakChar)
1162 dxs[i] += breakExtra;
1163 if (breakRem > 0)
1165 breakRem--;
1166 dxs[i]++;
1169 if (dxs[i] <= maxExt)
1170 ++nFit;
1172 breakRem = dc->breakRem;
1174 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1175 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1177 if (!dxs && count > 1 && (breakExtra || breakRem))
1179 for (i = 0; i < count; i++)
1181 if (str[i] == tm.tmBreakChar)
1183 size->cx += breakExtra;
1184 if (breakRem > 0)
1186 breakRem--;
1187 (size->cx)++;
1194 if (lpnFit)
1195 *lpnFit = nFit;
1197 if (! alpDx)
1198 HeapFree(GetProcessHeap(), 0, dxs);
1200 release_dc_ptr( dc );
1202 TRACE("returning %d %d x %d\n",nFit,size->cx,size->cy);
1203 return ret;
1206 /***********************************************************************
1207 * GetTextMetricsA (GDI32.@)
1209 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1211 TEXTMETRICW tm32;
1213 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1214 FONT_TextMetricWToA( &tm32, metrics );
1215 return TRUE;
1218 /***********************************************************************
1219 * GetTextMetricsW (GDI32.@)
1221 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1223 BOOL ret = FALSE;
1224 DC * dc = get_dc_ptr( hdc );
1225 if (!dc) return FALSE;
1227 if (dc->gdiFont)
1228 ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1229 else if (dc->funcs->pGetTextMetrics)
1230 ret = dc->funcs->pGetTextMetrics( dc->physDev, metrics );
1232 if (ret)
1234 /* device layer returns values in device units
1235 * therefore we have to convert them to logical */
1237 metrics->tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1238 metrics->tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1240 #define WDPTOLP(x) ((x<0)? \
1241 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1242 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1243 #define HDPTOLP(y) ((y<0)? \
1244 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1245 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1247 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1248 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1249 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1250 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1251 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1252 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1253 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1254 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1255 ret = TRUE;
1256 #undef WDPTOLP
1257 #undef HDPTOLP
1258 TRACE("text metrics:\n"
1259 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1260 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1261 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1262 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1263 " PitchAndFamily = %02x\n"
1264 " --------------------\n"
1265 " InternalLeading = %i\n"
1266 " Ascent = %i\n"
1267 " Descent = %i\n"
1268 " Height = %i\n",
1269 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1270 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1271 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1272 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1273 metrics->tmPitchAndFamily,
1274 metrics->tmInternalLeading,
1275 metrics->tmAscent,
1276 metrics->tmDescent,
1277 metrics->tmHeight );
1279 release_dc_ptr( dc );
1280 return ret;
1284 /***********************************************************************
1285 * GetOutlineTextMetricsA (GDI32.@)
1286 * Gets metrics for TrueType fonts.
1288 * NOTES
1289 * If the supplied buffer isn't big enough Windows partially fills it up to
1290 * its given length and returns that length.
1292 * RETURNS
1293 * Success: Non-zero or size of required buffer
1294 * Failure: 0
1296 UINT WINAPI GetOutlineTextMetricsA(
1297 HDC hdc, /* [in] Handle of device context */
1298 UINT cbData, /* [in] Size of metric data array */
1299 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1301 char buf[512], *ptr;
1302 UINT ret, needed;
1303 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1304 OUTLINETEXTMETRICA *output = lpOTM;
1305 INT left, len;
1307 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1308 return 0;
1309 if(ret > sizeof(buf))
1310 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1311 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1313 needed = sizeof(OUTLINETEXTMETRICA);
1314 if(lpOTMW->otmpFamilyName)
1315 needed += WideCharToMultiByte(CP_ACP, 0,
1316 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1317 NULL, 0, NULL, NULL);
1318 if(lpOTMW->otmpFaceName)
1319 needed += WideCharToMultiByte(CP_ACP, 0,
1320 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1321 NULL, 0, NULL, NULL);
1322 if(lpOTMW->otmpStyleName)
1323 needed += WideCharToMultiByte(CP_ACP, 0,
1324 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1325 NULL, 0, NULL, NULL);
1326 if(lpOTMW->otmpFullName)
1327 needed += WideCharToMultiByte(CP_ACP, 0,
1328 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1329 NULL, 0, NULL, NULL);
1331 if(!lpOTM) {
1332 ret = needed;
1333 goto end;
1336 TRACE("needed = %d\n", needed);
1337 if(needed > cbData)
1338 /* Since the supplied buffer isn't big enough, we'll alloc one
1339 that is and memcpy the first cbData bytes into the lpOTM at
1340 the end. */
1341 output = HeapAlloc(GetProcessHeap(), 0, needed);
1343 ret = output->otmSize = min(needed, cbData);
1344 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1345 output->otmFiller = 0;
1346 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1347 output->otmfsSelection = lpOTMW->otmfsSelection;
1348 output->otmfsType = lpOTMW->otmfsType;
1349 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1350 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1351 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1352 output->otmEMSquare = lpOTMW->otmEMSquare;
1353 output->otmAscent = lpOTMW->otmAscent;
1354 output->otmDescent = lpOTMW->otmDescent;
1355 output->otmLineGap = lpOTMW->otmLineGap;
1356 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1357 output->otmsXHeight = lpOTMW->otmsXHeight;
1358 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1359 output->otmMacAscent = lpOTMW->otmMacAscent;
1360 output->otmMacDescent = lpOTMW->otmMacDescent;
1361 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1362 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1363 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1364 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1365 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1366 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1367 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1368 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1369 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1370 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1373 ptr = (char*)(output + 1);
1374 left = needed - sizeof(*output);
1376 if(lpOTMW->otmpFamilyName) {
1377 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1378 len = WideCharToMultiByte(CP_ACP, 0,
1379 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1380 ptr, left, NULL, NULL);
1381 left -= len;
1382 ptr += len;
1383 } else
1384 output->otmpFamilyName = 0;
1386 if(lpOTMW->otmpFaceName) {
1387 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1388 len = WideCharToMultiByte(CP_ACP, 0,
1389 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1390 ptr, left, NULL, NULL);
1391 left -= len;
1392 ptr += len;
1393 } else
1394 output->otmpFaceName = 0;
1396 if(lpOTMW->otmpStyleName) {
1397 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1398 len = WideCharToMultiByte(CP_ACP, 0,
1399 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1400 ptr, left, NULL, NULL);
1401 left -= len;
1402 ptr += len;
1403 } else
1404 output->otmpStyleName = 0;
1406 if(lpOTMW->otmpFullName) {
1407 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1408 len = WideCharToMultiByte(CP_ACP, 0,
1409 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1410 ptr, left, NULL, NULL);
1411 left -= len;
1412 } else
1413 output->otmpFullName = 0;
1415 assert(left == 0);
1417 if(output != lpOTM) {
1418 memcpy(lpOTM, output, cbData);
1419 HeapFree(GetProcessHeap(), 0, output);
1421 /* check if the string offsets really fit into the provided size */
1422 /* FIXME: should we check string length as well? */
1423 /* make sure that we don't read/write beyond the provided buffer */
1424 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(LPSTR))
1426 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1427 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1430 /* make sure that we don't read/write beyond the provided buffer */
1431 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(LPSTR))
1433 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1434 lpOTM->otmpFaceName = 0; /* doesn't fit */
1437 /* make sure that we don't read/write beyond the provided buffer */
1438 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(LPSTR))
1440 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1441 lpOTM->otmpStyleName = 0; /* doesn't fit */
1444 /* make sure that we don't read/write beyond the provided buffer */
1445 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(LPSTR))
1447 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1448 lpOTM->otmpFullName = 0; /* doesn't fit */
1452 end:
1453 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1454 HeapFree(GetProcessHeap(), 0, lpOTMW);
1456 return ret;
1460 /***********************************************************************
1461 * GetOutlineTextMetricsW [GDI32.@]
1463 UINT WINAPI GetOutlineTextMetricsW(
1464 HDC hdc, /* [in] Handle of device context */
1465 UINT cbData, /* [in] Size of metric data array */
1466 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1468 DC *dc = get_dc_ptr( hdc );
1469 OUTLINETEXTMETRICW *output = lpOTM;
1470 UINT ret;
1472 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1473 if(!dc) return 0;
1475 if(dc->gdiFont) {
1476 ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, output);
1477 if(lpOTM && ret) {
1478 if(ret > cbData) {
1479 output = HeapAlloc(GetProcessHeap(), 0, ret);
1480 WineEngGetOutlineTextMetrics(dc->gdiFont, ret, output);
1483 output->otmTextMetrics.tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1484 output->otmTextMetrics.tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1486 #define WDPTOLP(x) ((x<0)? \
1487 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1488 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1489 #define HDPTOLP(y) ((y<0)? \
1490 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1491 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1493 output->otmTextMetrics.tmHeight = HDPTOLP(output->otmTextMetrics.tmHeight);
1494 output->otmTextMetrics.tmAscent = HDPTOLP(output->otmTextMetrics.tmAscent);
1495 output->otmTextMetrics.tmDescent = HDPTOLP(output->otmTextMetrics.tmDescent);
1496 output->otmTextMetrics.tmInternalLeading = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1497 output->otmTextMetrics.tmExternalLeading = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1498 output->otmTextMetrics.tmAveCharWidth = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1499 output->otmTextMetrics.tmMaxCharWidth = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1500 output->otmTextMetrics.tmOverhang = WDPTOLP(output->otmTextMetrics.tmOverhang);
1501 output->otmAscent = HDPTOLP(output->otmAscent);
1502 output->otmDescent = HDPTOLP(output->otmDescent);
1503 output->otmLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmLineGap));
1504 output->otmsCapEmHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsCapEmHeight));
1505 output->otmsXHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsXHeight));
1506 output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1507 output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1508 output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1509 output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1510 output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1511 output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1512 output->otmMacLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmMacLineGap));
1513 output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1514 output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1515 output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1516 output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1517 output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1518 output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1519 output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1520 output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1521 output->otmsStrikeoutSize = abs(INTERNAL_YDSTOWS(dc,output->otmsStrikeoutSize));
1522 output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1523 output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1524 output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1525 #undef WDPTOLP
1526 #undef HDPTOLP
1527 if(output != lpOTM) {
1528 memcpy(lpOTM, output, cbData);
1529 HeapFree(GetProcessHeap(), 0, output);
1530 ret = cbData;
1535 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1536 but really this should just be a return 0. */
1538 ret = sizeof(*lpOTM);
1539 if (lpOTM) {
1540 if(cbData < ret)
1541 ret = 0;
1542 else {
1543 memset(lpOTM, 0, ret);
1544 lpOTM->otmSize = sizeof(*lpOTM);
1545 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1547 Further fill of the structure not implemented,
1548 Needs real values for the structure members
1553 release_dc_ptr(dc);
1554 return ret;
1558 /***********************************************************************
1559 * GetCharWidthW (GDI32.@)
1560 * GetCharWidth32W (GDI32.@)
1562 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1563 LPINT buffer )
1565 UINT i;
1566 BOOL ret = FALSE;
1567 DC * dc = get_dc_ptr( hdc );
1568 if (!dc) return FALSE;
1570 if (dc->gdiFont)
1571 ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1572 else if (dc->funcs->pGetCharWidth)
1573 ret = dc->funcs->pGetCharWidth( dc->physDev, firstChar, lastChar, buffer);
1575 if (ret)
1577 /* convert device units to logical */
1578 for( i = firstChar; i <= lastChar; i++, buffer++ )
1579 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1580 ret = TRUE;
1582 release_dc_ptr( dc );
1583 return ret;
1587 /***********************************************************************
1588 * GetCharWidthA (GDI32.@)
1589 * GetCharWidth32A (GDI32.@)
1591 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1592 LPINT buffer )
1594 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1595 LPSTR str;
1596 LPWSTR wstr;
1597 BOOL ret = TRUE;
1599 if(count <= 0) return FALSE;
1601 str = HeapAlloc(GetProcessHeap(), 0, count);
1602 for(i = 0; i < count; i++)
1603 str[i] = (BYTE)(firstChar + i);
1605 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1607 for(i = 0; i < wlen; i++)
1609 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1611 ret = FALSE;
1612 break;
1614 buffer++;
1617 HeapFree(GetProcessHeap(), 0, str);
1618 HeapFree(GetProcessHeap(), 0, wstr);
1620 return ret;
1624 /***********************************************************************
1625 * ExtTextOutA (GDI32.@)
1627 * See ExtTextOutW.
1629 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1630 const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1632 INT wlen;
1633 UINT codepage;
1634 LPWSTR p;
1635 BOOL ret;
1636 LPINT lpDxW = NULL;
1638 if (flags & ETO_GLYPH_INDEX)
1639 return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
1641 p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
1643 if (lpDx) {
1644 unsigned int i = 0, j = 0;
1646 /* allocate enough for a ETO_PDY */
1647 lpDxW = HeapAlloc( GetProcessHeap(), 0, 2*wlen*sizeof(INT));
1648 while(i < count) {
1649 if(IsDBCSLeadByteEx(codepage, str[i]))
1651 if(flags & ETO_PDY)
1653 lpDxW[j++] = lpDx[i * 2] + lpDx[(i + 1) * 2];
1654 lpDxW[j++] = lpDx[i * 2 + 1] + lpDx[(i + 1) * 2 + 1];
1656 else
1657 lpDxW[j++] = lpDx[i] + lpDx[i + 1];
1658 i = i + 2;
1660 else
1662 if(flags & ETO_PDY)
1664 lpDxW[j++] = lpDx[i * 2];
1665 lpDxW[j++] = lpDx[i * 2 + 1];
1667 else
1668 lpDxW[j++] = lpDx[i];
1669 i = i + 1;
1674 ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1676 HeapFree( GetProcessHeap(), 0, p );
1677 HeapFree( GetProcessHeap(), 0, lpDxW );
1678 return ret;
1682 /***********************************************************************
1683 * ExtTextOutW (GDI32.@)
1685 * Draws text using the currently selected font, background color, and text color.
1688 * PARAMS
1689 * x,y [I] coordinates of string
1690 * flags [I]
1691 * ETO_GRAYED - undocumented on MSDN
1692 * ETO_OPAQUE - use background color for fill the rectangle
1693 * ETO_CLIPPED - clipping text to the rectangle
1694 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1695 * than encoded characters. Implies ETO_IGNORELANGUAGE
1696 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1697 * Affects BiDi ordering
1698 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1699 * ETO_PDY - unimplemented
1700 * ETO_NUMERICSLATIN - unimplemented always assumed -
1701 * do not translate numbers into locale representations
1702 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1703 * lprect [I] dimensions for clipping or/and opaquing
1704 * str [I] text string
1705 * count [I] number of symbols in string
1706 * lpDx [I] optional parameter with distance between drawing characters
1708 * RETURNS
1709 * Success: TRUE
1710 * Failure: FALSE
1712 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1713 const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1715 BOOL ret = FALSE;
1716 LPWSTR reordered_str = (LPWSTR)str;
1717 WORD *glyphs = NULL;
1718 UINT align = GetTextAlign( hdc );
1719 DWORD layout = GetLayout( hdc );
1720 POINT pt;
1721 TEXTMETRICW tm;
1722 LOGFONTW lf;
1723 double cosEsc, sinEsc;
1724 INT char_extra;
1725 SIZE sz;
1726 RECT rc;
1727 BOOL done_extents = FALSE;
1728 POINT *deltas = NULL, width = {0, 0};
1729 DWORD type;
1730 DC * dc = get_dc_ptr( hdc );
1731 INT breakRem;
1732 static int quietfixme = 0;
1734 if (!dc) return FALSE;
1736 breakRem = dc->breakRem;
1738 if (quietfixme == 0 && flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN))
1740 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN unimplemented\n");
1741 quietfixme = 1;
1743 if (!dc->funcs->pExtTextOut && !PATH_IsPathOpen(dc->path))
1745 release_dc_ptr( dc );
1746 return ret;
1749 update_dc( dc );
1750 type = GetObjectType(hdc);
1751 if(type == OBJ_METADC || type == OBJ_ENHMETADC)
1753 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, flags, lprect, str, count, lpDx);
1754 release_dc_ptr( dc );
1755 return ret;
1758 if (!lprect)
1759 flags &= ~ETO_CLIPPED;
1761 if (flags & ETO_RTLREADING) align |= TA_RTLREADING;
1762 if (layout & LAYOUT_RTL)
1764 if ((align & TA_CENTER) != TA_CENTER) align ^= TA_RIGHT;
1765 align ^= TA_RTLREADING;
1768 if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && count > 0 )
1770 INT cGlyphs;
1771 reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1773 BIDI_Reorder( hdc, str, count, GCP_REORDER,
1774 (align & TA_RTLREADING) ? WINE_GCPW_FORCE_RTL : WINE_GCPW_FORCE_LTR,
1775 reordered_str, count, NULL, &glyphs, &cGlyphs);
1777 flags |= ETO_IGNORELANGUAGE;
1778 if (glyphs)
1780 flags |= ETO_GLYPH_INDEX;
1781 if (cGlyphs != count)
1782 count = cGlyphs;
1785 else if(flags & ETO_GLYPH_INDEX)
1786 glyphs = reordered_str;
1788 TRACE("%p, %d, %d, %08x, %s, %s, %d, %p)\n", hdc, x, y, flags,
1789 wine_dbgstr_rect(lprect), debugstr_wn(str, count), count, lpDx);
1790 TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
1792 if(align & TA_UPDATECP)
1794 GetCurrentPositionEx( hdc, &pt );
1795 x = pt.x;
1796 y = pt.y;
1799 GetTextMetricsW(hdc, &tm);
1800 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1802 if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
1803 lf.lfEscapement = 0;
1805 if(lf.lfEscapement != 0)
1807 cosEsc = cos(lf.lfEscapement * M_PI / 1800);
1808 sinEsc = sin(lf.lfEscapement * M_PI / 1800);
1810 else
1812 cosEsc = 1;
1813 sinEsc = 0;
1816 if(flags & (ETO_CLIPPED | ETO_OPAQUE))
1818 if(!lprect)
1820 if(flags & ETO_GLYPH_INDEX)
1821 GetTextExtentPointI(hdc, glyphs, count, &sz);
1822 else
1823 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1825 done_extents = TRUE;
1826 rc.left = x;
1827 rc.top = y;
1828 rc.right = x + sz.cx;
1829 rc.bottom = y + sz.cy;
1831 else
1833 rc = *lprect;
1836 LPtoDP(hdc, (POINT*)&rc, 2);
1838 if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
1839 if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
1842 if ((flags & ETO_OPAQUE) && !PATH_IsPathOpen(dc->path))
1843 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1845 if(count == 0)
1847 ret = TRUE;
1848 goto done;
1851 pt.x = x;
1852 pt.y = y;
1853 LPtoDP(hdc, &pt, 1);
1854 x = pt.x;
1855 y = pt.y;
1857 char_extra = GetTextCharacterExtra(hdc);
1858 if(char_extra || dc->breakExtra || breakRem || lpDx || lf.lfEscapement != 0)
1860 UINT i;
1861 SIZE tmpsz;
1862 POINT total = {0, 0}, desired[2];
1864 deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
1865 for(i = 0; i < count; i++)
1867 if(lpDx)
1869 if(flags & ETO_PDY)
1871 deltas[i].x = lpDx[i * 2] + char_extra;
1872 deltas[i].y = -lpDx[i * 2 + 1];
1874 else
1876 deltas[i].x = lpDx[i] + char_extra;
1877 deltas[i].y = 0;
1881 else
1883 if(flags & ETO_GLYPH_INDEX)
1884 GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
1885 else
1886 GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
1888 deltas[i].x = tmpsz.cx;
1889 deltas[i].y = 0;
1892 if (!(flags & ETO_GLYPH_INDEX) && (dc->breakExtra || breakRem) && reordered_str[i] == tm.tmBreakChar)
1894 deltas[i].x = deltas[i].x + dc->breakExtra;
1895 if (breakRem > 0)
1897 breakRem--;
1898 deltas[i].x++;
1901 total.x += deltas[i].x;
1902 total.y += deltas[i].y;
1904 desired[0].x = desired[0].y = 0;
1906 desired[1].x = cosEsc * total.x + sinEsc * total.y;
1907 desired[1].y = -sinEsc * total.x + cosEsc * total.y;
1909 LPtoDP(hdc, desired, 2);
1910 desired[1].x -= desired[0].x;
1911 desired[1].y -= desired[0].y;
1912 if (layout & LAYOUT_RTL) desired[1].x = -desired[1].x;
1914 deltas[i].x = desired[1].x - width.x;
1915 deltas[i].y = desired[1].y - width.y;
1917 width = desired[1];
1919 flags |= ETO_PDY;
1921 else
1923 if(!done_extents)
1925 if(flags & ETO_GLYPH_INDEX)
1926 GetTextExtentPointI(hdc, glyphs, count, &sz);
1927 else
1928 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1929 done_extents = TRUE;
1931 width.x = abs(INTERNAL_XWSTODS(dc, sz.cx));
1932 width.y = 0;
1935 tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
1936 tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
1937 switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
1939 case TA_LEFT:
1940 if (align & TA_UPDATECP)
1942 pt.x = x + width.x;
1943 pt.y = y + width.y;
1944 DPtoLP(hdc, &pt, 1);
1945 MoveToEx(hdc, pt.x, pt.y, NULL);
1947 break;
1949 case TA_CENTER:
1950 x -= width.x / 2;
1951 y -= width.y / 2;
1952 break;
1954 case TA_RIGHT:
1955 x -= width.x;
1956 y -= width.y;
1957 if (align & TA_UPDATECP)
1959 pt.x = x;
1960 pt.y = y;
1961 DPtoLP(hdc, &pt, 1);
1962 MoveToEx(hdc, pt.x, pt.y, NULL);
1964 break;
1967 switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
1969 case TA_TOP:
1970 y += tm.tmAscent * cosEsc;
1971 x += tm.tmAscent * sinEsc;
1972 break;
1974 case TA_BOTTOM:
1975 y -= tm.tmDescent * cosEsc;
1976 x -= tm.tmDescent * sinEsc;
1977 break;
1979 case TA_BASELINE:
1980 break;
1983 if (GetBkMode(hdc) != TRANSPARENT && !PATH_IsPathOpen(dc->path))
1985 if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
1987 if(!(flags & ETO_OPAQUE) || x < rc.left || x + width.x >= rc.right ||
1988 y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
1990 RECT rc;
1991 rc.left = x;
1992 rc.right = x + width.x;
1993 rc.top = y - tm.tmAscent;
1994 rc.bottom = y + tm.tmDescent;
1995 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
2000 if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
2002 HFONT orig_font = dc->hFont, cur_font;
2003 UINT glyph;
2004 INT span = 0;
2005 POINT *offsets = NULL;
2006 unsigned int i;
2008 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2009 for(i = 0; i < count; i++)
2011 WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
2012 if(cur_font != dc->hFont)
2014 if(!offsets)
2016 unsigned int j;
2017 offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
2018 offsets[0].x = offsets[0].y = 0;
2020 if(!deltas)
2022 SIZE tmpsz;
2023 for(j = 1; j < count; j++)
2025 GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
2026 offsets[j].x = offsets[j - 1].x + abs(INTERNAL_XWSTODS(dc, tmpsz.cx));
2027 offsets[j].y = 0;
2030 else
2032 for(j = 1; j < count; j++)
2034 offsets[j].x = offsets[j - 1].x + deltas[j].x;
2035 offsets[j].y = offsets[j - 1].y + deltas[j].y;
2039 if(span)
2041 if (PATH_IsPathOpen(dc->path))
2042 ret = PATH_ExtTextOut(dc, x + offsets[i - span].x, y + offsets[i - span].y,
2043 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2044 glyphs, span, deltas ? (INT*)(deltas + (i - span)) : NULL);
2045 else
2046 dc->funcs->pExtTextOut(dc->physDev, x + offsets[i - span].x, y + offsets[i - span].y,
2047 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2048 glyphs, span, deltas ? (INT*)(deltas + (i - span)) : NULL);
2049 span = 0;
2051 SelectObject(hdc, cur_font);
2053 glyphs[span++] = glyph;
2055 if(i == count - 1)
2057 if (PATH_IsPathOpen(dc->path))
2058 ret = PATH_ExtTextOut(dc, x + (offsets ? offsets[count - span].x : 0),
2059 y + (offsets ? offsets[count - span].y : 0),
2060 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2061 glyphs, span, deltas ? (INT*)(deltas + (count - span)) : NULL);
2062 else
2063 ret = dc->funcs->pExtTextOut(dc->physDev, x + (offsets ? offsets[count - span].x : 0),
2064 y + (offsets ? offsets[count - span].y : 0),
2065 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2066 glyphs, span, deltas ? (INT*)(deltas + (count - span)) : NULL);
2067 SelectObject(hdc, orig_font);
2068 HeapFree(GetProcessHeap(), 0, offsets);
2072 else
2074 if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
2076 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2077 GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
2078 flags |= ETO_GLYPH_INDEX;
2081 if (PATH_IsPathOpen(dc->path))
2082 ret = PATH_ExtTextOut(dc, x, y, (flags & ~ETO_OPAQUE), &rc,
2083 glyphs ? glyphs : reordered_str, count, (INT*)deltas);
2084 else
2085 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, (flags & ~ETO_OPAQUE), &rc,
2086 glyphs ? glyphs : reordered_str, count, (INT*)deltas);
2089 done:
2090 HeapFree(GetProcessHeap(), 0, deltas);
2091 if(glyphs != reordered_str)
2092 HeapFree(GetProcessHeap(), 0, glyphs);
2093 if(reordered_str != str)
2094 HeapFree(GetProcessHeap(), 0, reordered_str);
2096 release_dc_ptr( dc );
2098 if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2100 int underlinePos, strikeoutPos;
2101 int underlineWidth, strikeoutWidth;
2102 UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2103 OUTLINETEXTMETRICW* otm = NULL;
2105 if(!size)
2107 underlinePos = 0;
2108 underlineWidth = tm.tmAscent / 20 + 1;
2109 strikeoutPos = tm.tmAscent / 2;
2110 strikeoutWidth = underlineWidth;
2112 else
2114 otm = HeapAlloc(GetProcessHeap(), 0, size);
2115 GetOutlineTextMetricsW(hdc, size, otm);
2116 underlinePos = otm->otmsUnderscorePosition;
2117 underlineWidth = otm->otmsUnderscoreSize;
2118 strikeoutPos = otm->otmsStrikeoutPosition;
2119 strikeoutWidth = otm->otmsStrikeoutSize;
2120 HeapFree(GetProcessHeap(), 0, otm);
2123 if (PATH_IsPathOpen(dc->path))
2125 POINT pts[5];
2126 HPEN hpen;
2127 HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2129 hbrush = SelectObject(hdc, hbrush);
2130 hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2132 if (lf.lfUnderline)
2134 pts[0].x = x - underlinePos * sinEsc;
2135 pts[0].y = y - underlinePos * cosEsc;
2136 pts[1].x = x + width.x - underlinePos * sinEsc;
2137 pts[1].y = y + width.y - underlinePos * cosEsc;
2138 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2139 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2140 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2141 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2142 pts[4].x = pts[0].x;
2143 pts[4].y = pts[0].y;
2144 DPtoLP(hdc, pts, 5);
2145 Polygon(hdc, pts, 5);
2148 if (lf.lfStrikeOut)
2150 pts[0].x = x - strikeoutPos * sinEsc;
2151 pts[0].y = y - strikeoutPos * cosEsc;
2152 pts[1].x = x + width.x - strikeoutPos * sinEsc;
2153 pts[1].y = y + width.y - strikeoutPos * cosEsc;
2154 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2155 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2156 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2157 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2158 pts[4].x = pts[0].x;
2159 pts[4].y = pts[0].y;
2160 DPtoLP(hdc, pts, 5);
2161 Polygon(hdc, pts, 5);
2164 SelectObject(hdc, hpen);
2165 hbrush = SelectObject(hdc, hbrush);
2166 DeleteObject(hbrush);
2168 else
2170 POINT pts[2], oldpt;
2171 HPEN hpen;
2173 if (lf.lfUnderline)
2175 hpen = CreatePen(PS_SOLID, underlineWidth, GetTextColor(hdc));
2176 hpen = SelectObject(hdc, hpen);
2177 pts[0].x = x;
2178 pts[0].y = y;
2179 pts[1].x = x + width.x;
2180 pts[1].y = y + width.y;
2181 DPtoLP(hdc, pts, 2);
2182 MoveToEx(hdc, pts[0].x - underlinePos * sinEsc, pts[0].y - underlinePos * cosEsc, &oldpt);
2183 LineTo(hdc, pts[1].x - underlinePos * sinEsc, pts[1].y - underlinePos * cosEsc);
2184 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2185 DeleteObject(SelectObject(hdc, hpen));
2188 if (lf.lfStrikeOut)
2190 hpen = CreatePen(PS_SOLID, strikeoutWidth, GetTextColor(hdc));
2191 hpen = SelectObject(hdc, hpen);
2192 pts[0].x = x;
2193 pts[0].y = y;
2194 pts[1].x = x + width.x;
2195 pts[1].y = y + width.y;
2196 DPtoLP(hdc, pts, 2);
2197 MoveToEx(hdc, pts[0].x - strikeoutPos * sinEsc, pts[0].y - strikeoutPos * cosEsc, &oldpt);
2198 LineTo(hdc, pts[1].x - strikeoutPos * sinEsc, pts[1].y - strikeoutPos * cosEsc);
2199 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2200 DeleteObject(SelectObject(hdc, hpen));
2205 return ret;
2209 /***********************************************************************
2210 * TextOutA (GDI32.@)
2212 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2214 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2218 /***********************************************************************
2219 * TextOutW (GDI32.@)
2221 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2223 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2227 /***********************************************************************
2228 * PolyTextOutA (GDI32.@)
2230 * See PolyTextOutW.
2232 BOOL WINAPI PolyTextOutA( HDC hdc, const POLYTEXTA *pptxt, INT cStrings )
2234 for (; cStrings>0; cStrings--, pptxt++)
2235 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2236 return FALSE;
2237 return TRUE;
2242 /***********************************************************************
2243 * PolyTextOutW (GDI32.@)
2245 * Draw several Strings
2247 * RETURNS
2248 * TRUE: Success.
2249 * FALSE: Failure.
2251 BOOL WINAPI PolyTextOutW( HDC hdc, const POLYTEXTW *pptxt, INT cStrings )
2253 for (; cStrings>0; cStrings--, pptxt++)
2254 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2255 return FALSE;
2256 return TRUE;
2260 /* FIXME: all following APIs ******************************************/
2263 /***********************************************************************
2264 * SetMapperFlags (GDI32.@)
2266 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
2268 DC *dc = get_dc_ptr( hDC );
2269 DWORD ret = 0;
2270 if(!dc) return 0;
2271 if(dc->funcs->pSetMapperFlags)
2273 ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
2274 /* FIXME: ret is just a success flag, we should return a proper value */
2276 else
2277 FIXME("(%p, 0x%08x): stub - harmless\n", hDC, dwFlag);
2278 release_dc_ptr( dc );
2279 return ret;
2282 /***********************************************************************
2283 * GetAspectRatioFilterEx (GDI32.@)
2285 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2287 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2288 return FALSE;
2292 /***********************************************************************
2293 * GetCharABCWidthsA (GDI32.@)
2295 * See GetCharABCWidthsW.
2297 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2298 LPABC abc )
2300 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
2301 LPSTR str;
2302 LPWSTR wstr;
2303 BOOL ret = TRUE;
2305 if(count <= 0) return FALSE;
2307 str = HeapAlloc(GetProcessHeap(), 0, count);
2308 for(i = 0; i < count; i++)
2309 str[i] = (BYTE)(firstChar + i);
2311 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
2313 for(i = 0; i < wlen; i++)
2315 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2317 ret = FALSE;
2318 break;
2320 abc++;
2323 HeapFree(GetProcessHeap(), 0, str);
2324 HeapFree(GetProcessHeap(), 0, wstr);
2326 return ret;
2330 /******************************************************************************
2331 * GetCharABCWidthsW [GDI32.@]
2333 * Retrieves widths of characters in range.
2335 * PARAMS
2336 * hdc [I] Handle of device context
2337 * firstChar [I] First character in range to query
2338 * lastChar [I] Last character in range to query
2339 * abc [O] Address of character-width structure
2341 * NOTES
2342 * Only works with TrueType fonts
2344 * RETURNS
2345 * Success: TRUE
2346 * Failure: FALSE
2348 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2349 LPABC abc )
2351 DC *dc = get_dc_ptr(hdc);
2352 unsigned int i;
2353 BOOL ret = FALSE;
2355 if (!dc) return FALSE;
2357 if (!abc)
2359 release_dc_ptr( dc );
2360 return FALSE;
2363 if(dc->gdiFont)
2364 ret = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
2365 else
2366 FIXME(": stub\n");
2368 if (ret)
2370 /* convert device units to logical */
2371 for( i = firstChar; i <= lastChar; i++, abc++ ) {
2372 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2373 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2374 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2376 ret = TRUE;
2379 release_dc_ptr( dc );
2380 return ret;
2384 /******************************************************************************
2385 * GetCharABCWidthsI [GDI32.@]
2387 * Retrieves widths of characters in range.
2389 * PARAMS
2390 * hdc [I] Handle of device context
2391 * firstChar [I] First glyphs in range to query
2392 * count [I] Last glyphs in range to query
2393 * pgi [i] Array of glyphs to query
2394 * abc [O] Address of character-width structure
2396 * NOTES
2397 * Only works with TrueType fonts
2399 * RETURNS
2400 * Success: TRUE
2401 * Failure: FALSE
2403 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2404 LPWORD pgi, LPABC abc)
2406 DC *dc = get_dc_ptr(hdc);
2407 unsigned int i;
2408 BOOL ret = FALSE;
2410 if (!dc) return FALSE;
2412 if (!abc)
2414 release_dc_ptr( dc );
2415 return FALSE;
2418 if(dc->gdiFont)
2419 ret = WineEngGetCharABCWidthsI( dc->gdiFont, firstChar, count, pgi, abc );
2420 else
2421 FIXME(": stub\n");
2423 if (ret)
2425 /* convert device units to logical */
2426 for( i = 0; i < count; i++, abc++ ) {
2427 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2428 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2429 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2431 ret = TRUE;
2434 release_dc_ptr( dc );
2435 return ret;
2439 /***********************************************************************
2440 * GetGlyphOutlineA (GDI32.@)
2442 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2443 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2444 LPVOID lpBuffer, const MAT2 *lpmat2 )
2446 LPWSTR p = NULL;
2447 DWORD ret;
2448 UINT c;
2450 if (!lpmat2) return GDI_ERROR;
2452 if(!(fuFormat & GGO_GLYPH_INDEX)) {
2453 int len;
2454 char mbchs[2];
2455 if(uChar > 0xff) { /* but, 2 bytes character only */
2456 len = 2;
2457 mbchs[0] = (uChar & 0xff00) >> 8;
2458 mbchs[1] = (uChar & 0xff);
2459 } else {
2460 len = 1;
2461 mbchs[0] = (uChar & 0xff);
2463 p = FONT_mbtowc(hdc, mbchs, len, NULL, NULL);
2464 c = p[0];
2465 } else
2466 c = uChar;
2467 ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
2468 lpmat2);
2469 HeapFree(GetProcessHeap(), 0, p);
2470 return ret;
2473 /***********************************************************************
2474 * GetGlyphOutlineW (GDI32.@)
2476 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2477 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2478 LPVOID lpBuffer, const MAT2 *lpmat2 )
2480 DC *dc;
2481 DWORD ret;
2483 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2484 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2486 if (!lpmat2) return GDI_ERROR;
2488 dc = get_dc_ptr(hdc);
2489 if(!dc) return GDI_ERROR;
2491 if(dc->gdiFont)
2492 ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
2493 cbBuffer, lpBuffer, lpmat2);
2494 else
2495 ret = GDI_ERROR;
2497 release_dc_ptr( dc );
2498 return ret;
2502 /***********************************************************************
2503 * CreateScalableFontResourceA (GDI32.@)
2505 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2506 LPCSTR lpszResourceFile,
2507 LPCSTR lpszFontFile,
2508 LPCSTR lpszCurrentPath )
2510 LPWSTR lpszResourceFileW = NULL;
2511 LPWSTR lpszFontFileW = NULL;
2512 LPWSTR lpszCurrentPathW = NULL;
2513 int len;
2514 BOOL ret;
2516 if (lpszResourceFile)
2518 len = MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, NULL, 0);
2519 lpszResourceFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2520 MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, lpszResourceFileW, len);
2523 if (lpszFontFile)
2525 len = MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, NULL, 0);
2526 lpszFontFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2527 MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, lpszFontFileW, len);
2530 if (lpszCurrentPath)
2532 len = MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, NULL, 0);
2533 lpszCurrentPathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2534 MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, lpszCurrentPathW, len);
2537 ret = CreateScalableFontResourceW(fHidden, lpszResourceFileW,
2538 lpszFontFileW, lpszCurrentPathW);
2540 HeapFree(GetProcessHeap(), 0, lpszResourceFileW);
2541 HeapFree(GetProcessHeap(), 0, lpszFontFileW);
2542 HeapFree(GetProcessHeap(), 0, lpszCurrentPathW);
2544 return ret;
2547 /***********************************************************************
2548 * CreateScalableFontResourceW (GDI32.@)
2550 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2551 LPCWSTR lpszResourceFile,
2552 LPCWSTR lpszFontFile,
2553 LPCWSTR lpszCurrentPath )
2555 HANDLE f;
2556 FIXME("(%d,%s,%s,%s): stub\n",
2557 fHidden, debugstr_w(lpszResourceFile), debugstr_w(lpszFontFile),
2558 debugstr_w(lpszCurrentPath) );
2560 /* fHidden=1 - only visible for the calling app, read-only, not
2561 * enumerated with EnumFonts/EnumFontFamilies
2562 * lpszCurrentPath can be NULL
2565 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2566 if ((f = CreateFileW(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2567 CloseHandle(f);
2568 SetLastError(ERROR_FILE_EXISTS);
2569 return FALSE;
2571 return FALSE; /* create failed */
2574 /*************************************************************************
2575 * GetKerningPairsA (GDI32.@)
2577 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2578 LPKERNINGPAIR kern_pairA )
2580 UINT cp;
2581 CPINFO cpi;
2582 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2583 KERNINGPAIR *kern_pairW;
2585 if (!cPairs && kern_pairA)
2587 SetLastError(ERROR_INVALID_PARAMETER);
2588 return 0;
2591 cp = GdiGetCodePage(hDC);
2593 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2594 * to fail on an invalid character for CP_SYMBOL.
2596 cpi.DefaultChar[0] = 0;
2597 if (cp != CP_SYMBOL && !GetCPInfo(cp, &cpi))
2599 FIXME("Can't find codepage %u info\n", cp);
2600 return 0;
2603 total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2604 if (!total_kern_pairs) return 0;
2606 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2607 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2609 for (i = 0; i < total_kern_pairs; i++)
2611 char first, second;
2613 if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2614 continue;
2616 if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2617 continue;
2619 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2620 continue;
2622 if (kern_pairA)
2624 if (kern_pairs_copied >= cPairs) break;
2626 kern_pairA->wFirst = (BYTE)first;
2627 kern_pairA->wSecond = (BYTE)second;
2628 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2629 kern_pairA++;
2631 kern_pairs_copied++;
2634 HeapFree(GetProcessHeap(), 0, kern_pairW);
2636 return kern_pairs_copied;
2639 /*************************************************************************
2640 * GetKerningPairsW (GDI32.@)
2642 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2643 LPKERNINGPAIR lpKerningPairs )
2645 DC *dc;
2646 DWORD ret = 0;
2648 TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2650 if (!cPairs && lpKerningPairs)
2652 SetLastError(ERROR_INVALID_PARAMETER);
2653 return 0;
2656 dc = get_dc_ptr(hDC);
2657 if (!dc) return 0;
2659 if (dc->gdiFont)
2660 ret = WineEngGetKerningPairs(dc->gdiFont, cPairs, lpKerningPairs);
2662 release_dc_ptr( dc );
2663 return ret;
2666 /*************************************************************************
2667 * TranslateCharsetInfo [GDI32.@]
2669 * Fills a CHARSETINFO structure for a character set, code page, or
2670 * font. This allows making the correspondence between different labels
2671 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2672 * of the same encoding.
2674 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2675 * only one codepage should be set in *lpSrc.
2677 * RETURNS
2678 * TRUE on success, FALSE on failure.
2681 BOOL WINAPI TranslateCharsetInfo(
2682 LPDWORD lpSrc, /* [in]
2683 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2684 if flags == TCI_SRCCHARSET: a character set value
2685 if flags == TCI_SRCCODEPAGE: a code page value
2687 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2688 DWORD flags /* [in] determines interpretation of lpSrc */)
2690 int index = 0;
2691 switch (flags) {
2692 case TCI_SRCFONTSIG:
2693 while (index < MAXTCIINDEX && !(*lpSrc>>index & 0x0001)) index++;
2694 break;
2695 case TCI_SRCCODEPAGE:
2696 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciACP) index++;
2697 break;
2698 case TCI_SRCCHARSET:
2699 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciCharset) index++;
2700 break;
2701 default:
2702 return FALSE;
2704 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2705 *lpCs = FONT_tci[index];
2706 return TRUE;
2709 /*************************************************************************
2710 * GetFontLanguageInfo (GDI32.@)
2712 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2714 FONTSIGNATURE fontsig;
2715 static const DWORD GCP_DBCS_MASK=0x003F0000,
2716 GCP_DIACRITIC_MASK=0x00000000,
2717 FLI_GLYPHS_MASK=0x00000000,
2718 GCP_GLYPHSHAPE_MASK=0x00000040,
2719 GCP_KASHIDA_MASK=0x00000000,
2720 GCP_LIGATE_MASK=0x00000000,
2721 GCP_USEKERNING_MASK=0x00000000,
2722 GCP_REORDER_MASK=0x00000060;
2724 DWORD result=0;
2726 GetTextCharsetInfo( hdc, &fontsig, 0 );
2727 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2729 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2730 result|=GCP_DBCS;
2732 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2733 result|=GCP_DIACRITIC;
2735 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2736 result|=FLI_GLYPHS;
2738 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2739 result|=GCP_GLYPHSHAPE;
2741 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2742 result|=GCP_KASHIDA;
2744 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2745 result|=GCP_LIGATE;
2747 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2748 result|=GCP_USEKERNING;
2750 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2751 if( GetTextAlign( hdc) & TA_RTLREADING )
2752 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2753 result|=GCP_REORDER;
2755 return result;
2759 /*************************************************************************
2760 * GetFontData [GDI32.@]
2762 * Retrieve data for TrueType font.
2764 * RETURNS
2766 * success: Number of bytes returned
2767 * failure: GDI_ERROR
2769 * NOTES
2771 * Calls SetLastError()
2774 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2775 LPVOID buffer, DWORD length)
2777 DC *dc = get_dc_ptr(hdc);
2778 DWORD ret = GDI_ERROR;
2780 if(!dc) return GDI_ERROR;
2782 if(dc->gdiFont)
2783 ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2785 release_dc_ptr( dc );
2786 return ret;
2789 /*************************************************************************
2790 * GetGlyphIndicesA [GDI32.@]
2792 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2793 LPWORD pgi, DWORD flags)
2795 DWORD ret;
2796 WCHAR *lpstrW;
2797 INT countW;
2799 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2800 hdc, debugstr_an(lpstr, count), count, pgi, flags);
2802 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2803 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2804 HeapFree(GetProcessHeap(), 0, lpstrW);
2806 return ret;
2809 /*************************************************************************
2810 * GetGlyphIndicesW [GDI32.@]
2812 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2813 LPWORD pgi, DWORD flags)
2815 DC *dc = get_dc_ptr(hdc);
2816 DWORD ret = GDI_ERROR;
2818 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2819 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2821 if(!dc) return GDI_ERROR;
2823 if(dc->gdiFont)
2824 ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2826 release_dc_ptr( dc );
2827 return ret;
2830 /*************************************************************************
2831 * GetCharacterPlacementA [GDI32.@]
2833 * See GetCharacterPlacementW.
2835 * NOTES:
2836 * the web browser control of ie4 calls this with dwFlags=0
2838 DWORD WINAPI
2839 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2840 INT nMaxExtent, GCP_RESULTSA *lpResults,
2841 DWORD dwFlags)
2843 WCHAR *lpStringW;
2844 INT uCountW;
2845 GCP_RESULTSW resultsW;
2846 DWORD ret;
2847 UINT font_cp;
2849 TRACE("%s, %d, %d, 0x%08x\n",
2850 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2852 /* both structs are equal in size */
2853 memcpy(&resultsW, lpResults, sizeof(resultsW));
2855 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2856 if(lpResults->lpOutString)
2857 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2859 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2861 lpResults->nGlyphs = resultsW.nGlyphs;
2862 lpResults->nMaxFit = resultsW.nMaxFit;
2864 if(lpResults->lpOutString) {
2865 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2866 lpResults->lpOutString, uCount, NULL, NULL );
2869 HeapFree(GetProcessHeap(), 0, lpStringW);
2870 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2872 return ret;
2875 /*************************************************************************
2876 * GetCharacterPlacementW [GDI32.@]
2878 * Retrieve information about a string. This includes the width, reordering,
2879 * Glyphing and so on.
2881 * RETURNS
2883 * The width and height of the string if successful, 0 if failed.
2885 * BUGS
2887 * All flags except GCP_REORDER are not yet implemented.
2888 * Reordering is not 100% compliant to the Windows BiDi method.
2889 * Caret positioning is not yet implemented for BiDi.
2890 * Classes are not yet implemented.
2893 DWORD WINAPI
2894 GetCharacterPlacementW(
2895 HDC hdc, /* [in] Device context for which the rendering is to be done */
2896 LPCWSTR lpString, /* [in] The string for which information is to be returned */
2897 INT uCount, /* [in] Number of WORDS in string. */
2898 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
2899 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2900 DWORD dwFlags /* [in] Flags specifying how to process the string */
2903 DWORD ret=0;
2904 SIZE size;
2905 UINT i, nSet;
2907 TRACE("%s, %d, %d, 0x%08x\n",
2908 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2910 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2911 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2912 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2913 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2914 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2916 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08x ignored\n", dwFlags);
2917 if(lpResults->lpClass) FIXME("classes not implemented\n");
2918 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2919 FIXME("Caret positions for complex scripts not implemented\n");
2921 nSet = (UINT)uCount;
2922 if(nSet > lpResults->nGlyphs)
2923 nSet = lpResults->nGlyphs;
2925 /* return number of initialized fields */
2926 lpResults->nGlyphs = nSet;
2928 if((dwFlags&GCP_REORDER)==0 )
2930 /* Treat the case where no special handling was requested in a fastpath way */
2931 /* copy will do if the GCP_REORDER flag is not set */
2932 if(lpResults->lpOutString)
2933 memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
2935 if(lpResults->lpOrder)
2937 for(i = 0; i < nSet; i++)
2938 lpResults->lpOrder[i] = i;
2940 } else
2942 BIDI_Reorder(NULL, lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
2943 nSet, lpResults->lpOrder, NULL, NULL );
2946 /* FIXME: Will use the placement chars */
2947 if (lpResults->lpDx)
2949 int c;
2950 for (i = 0; i < nSet; i++)
2952 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
2953 lpResults->lpDx[i]= c;
2957 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
2959 int pos = 0;
2961 lpResults->lpCaretPos[0] = 0;
2962 for (i = 1; i < nSet; i++)
2963 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
2964 lpResults->lpCaretPos[i] = (pos += size.cx);
2967 if(lpResults->lpGlyphs)
2968 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
2970 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
2971 ret = MAKELONG(size.cx, size.cy);
2973 return ret;
2976 /*************************************************************************
2977 * GetCharABCWidthsFloatA [GDI32.@]
2979 * See GetCharABCWidthsFloatW.
2981 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
2983 INT i, wlen, count = (INT)(last - first + 1);
2984 LPSTR str;
2985 LPWSTR wstr;
2986 BOOL ret = TRUE;
2988 if (count <= 0) return FALSE;
2990 str = HeapAlloc(GetProcessHeap(), 0, count);
2992 for(i = 0; i < count; i++)
2993 str[i] = (BYTE)(first + i);
2995 wstr = FONT_mbtowc( hdc, str, count, &wlen, NULL );
2997 for (i = 0; i < wlen; i++)
2999 if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
3001 ret = FALSE;
3002 break;
3004 abcf++;
3007 HeapFree( GetProcessHeap(), 0, str );
3008 HeapFree( GetProcessHeap(), 0, wstr );
3010 return ret;
3013 /*************************************************************************
3014 * GetCharABCWidthsFloatW [GDI32.@]
3016 * Retrieves widths of a range of characters.
3018 * PARAMS
3019 * hdc [I] Handle to device context.
3020 * first [I] First character in range to query.
3021 * last [I] Last character in range to query.
3022 * abcf [O] Array of LPABCFLOAT structures.
3024 * RETURNS
3025 * Success: TRUE
3026 * Failure: FALSE
3028 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3030 UINT i;
3031 BOOL ret = FALSE;
3032 DC *dc = get_dc_ptr( hdc );
3034 TRACE("%p, %d, %d, %p\n", hdc, first, last, abcf);
3036 if (!dc) return FALSE;
3038 if (!abcf)
3040 release_dc_ptr( dc );
3041 return FALSE;
3044 if (dc->gdiFont)
3045 ret = WineEngGetCharABCWidthsFloat( dc->gdiFont, first, last, abcf );
3046 else
3047 FIXME("stub\n");
3049 if (ret)
3051 /* convert device units to logical */
3052 for (i = first; i <= last; i++, abcf++)
3054 abcf->abcfA = abcf->abcfA * dc->xformVport2World.eM11;
3055 abcf->abcfB = abcf->abcfB * dc->xformVport2World.eM11;
3056 abcf->abcfC = abcf->abcfC * dc->xformVport2World.eM11;
3060 release_dc_ptr( dc );
3061 return ret;
3064 /*************************************************************************
3065 * GetCharWidthFloatA [GDI32.@]
3067 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
3068 UINT iLastChar, PFLOAT pxBuffer)
3070 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3071 return 0;
3074 /*************************************************************************
3075 * GetCharWidthFloatW [GDI32.@]
3077 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
3078 UINT iLastChar, PFLOAT pxBuffer)
3080 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3081 return 0;
3085 /***********************************************************************
3087 * Font Resource API *
3089 ***********************************************************************/
3091 /***********************************************************************
3092 * AddFontResourceA (GDI32.@)
3094 INT WINAPI AddFontResourceA( LPCSTR str )
3096 return AddFontResourceExA( str, 0, NULL);
3099 /***********************************************************************
3100 * AddFontResourceW (GDI32.@)
3102 INT WINAPI AddFontResourceW( LPCWSTR str )
3104 return AddFontResourceExW(str, 0, NULL);
3108 /***********************************************************************
3109 * AddFontResourceExA (GDI32.@)
3111 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3113 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3114 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3115 INT ret;
3117 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3118 ret = AddFontResourceExW(strW, fl, pdv);
3119 HeapFree(GetProcessHeap(), 0, strW);
3120 return ret;
3123 static BOOL CALLBACK load_enumed_resource(HMODULE hModule, LPCWSTR type, LPWSTR name, LONG_PTR lParam)
3125 HRSRC rsrc = FindResourceW(hModule, name, type);
3126 HGLOBAL hMem = LoadResource(hModule, rsrc);
3127 LPVOID *pMem = LockResource(hMem);
3128 int *num_total = (int *)lParam;
3129 DWORD num_in_res;
3131 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type));
3132 if (!AddFontMemResourceEx(pMem, SizeofResource(hModule, rsrc), NULL, &num_in_res))
3134 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule, hMem);
3135 return FALSE;
3138 *num_total += num_in_res;
3139 return TRUE;
3142 /***********************************************************************
3143 * AddFontResourceExW (GDI32.@)
3145 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3147 int ret = WineEngAddFontResourceEx(str, fl, pdv);
3148 if (ret == 0)
3150 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3151 HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
3152 if (hModule != NULL)
3154 int num_resources = 0;
3155 LPWSTR rt_font = (LPWSTR)((ULONG_PTR)8); /* we don't want to include winuser.h */
3157 TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3158 wine_dbgstr_w(str));
3159 if (EnumResourceNamesW(hModule, rt_font, load_enumed_resource, (LONG_PTR)&num_resources))
3160 ret = num_resources;
3161 FreeLibrary(hModule);
3164 return ret;
3167 /***********************************************************************
3168 * RemoveFontResourceA (GDI32.@)
3170 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3172 return RemoveFontResourceExA(str, 0, 0);
3175 /***********************************************************************
3176 * RemoveFontResourceW (GDI32.@)
3178 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3180 return RemoveFontResourceExW(str, 0, 0);
3183 /***********************************************************************
3184 * AddFontMemResourceEx (GDI32.@)
3186 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3188 HANDLE ret;
3189 DWORD num_fonts;
3191 if (!pbFont || !cbFont || !pcFonts)
3193 SetLastError(ERROR_INVALID_PARAMETER);
3194 return NULL;
3197 ret = WineEngAddFontMemResourceEx(pbFont, cbFont, pdv, &num_fonts);
3198 if (ret)
3200 __TRY
3202 *pcFonts = num_fonts;
3204 __EXCEPT_PAGE_FAULT
3206 WARN("page fault while writing to *pcFonts (%p)\n", pcFonts);
3207 RemoveFontMemResourceEx(ret);
3208 ret = 0;
3210 __ENDTRY
3212 return ret;
3215 /***********************************************************************
3216 * RemoveFontMemResourceEx (GDI32.@)
3218 BOOL WINAPI RemoveFontMemResourceEx( HANDLE fh )
3220 FIXME("(%p) stub\n", fh);
3221 return TRUE;
3224 /***********************************************************************
3225 * RemoveFontResourceExA (GDI32.@)
3227 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3229 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3230 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3231 INT ret;
3233 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3234 ret = RemoveFontResourceExW(strW, fl, pdv);
3235 HeapFree(GetProcessHeap(), 0, strW);
3236 return ret;
3239 /***********************************************************************
3240 * RemoveFontResourceExW (GDI32.@)
3242 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3244 return WineEngRemoveFontResourceEx(str, fl, pdv);
3247 /***********************************************************************
3248 * GetTextCharset (GDI32.@)
3250 UINT WINAPI GetTextCharset(HDC hdc)
3252 /* MSDN docs say this is equivalent */
3253 return GetTextCharsetInfo(hdc, NULL, 0);
3256 /***********************************************************************
3257 * GetTextCharsetInfo (GDI32.@)
3259 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3261 UINT ret = DEFAULT_CHARSET;
3262 DC *dc = get_dc_ptr(hdc);
3264 if (dc)
3266 if (dc->gdiFont)
3267 ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
3269 release_dc_ptr( dc );
3272 if (ret == DEFAULT_CHARSET && fs)
3273 memset(fs, 0, sizeof(FONTSIGNATURE));
3274 return ret;
3277 /***********************************************************************
3278 * GdiGetCharDimensions (GDI32.@)
3280 * Gets the average width of the characters in the English alphabet.
3282 * PARAMS
3283 * hdc [I] Handle to the device context to measure on.
3284 * lptm [O] Pointer to memory to store the text metrics into.
3285 * height [O] On exit, the maximum height of characters in the English alphabet.
3287 * RETURNS
3288 * The average width of characters in the English alphabet.
3290 * NOTES
3291 * This function is used by the dialog manager to get the size of a dialog
3292 * unit. It should also be used by other pieces of code that need to know
3293 * the size of a dialog unit in logical units without having access to the
3294 * window handle of the dialog.
3295 * Windows caches the font metrics from this function, but we don't and
3296 * there doesn't appear to be an immediate advantage to do so.
3298 * SEE ALSO
3299 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3301 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3303 SIZE sz;
3304 static const WCHAR alphabet[] = {
3305 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3306 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3307 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3309 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3311 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3313 if (height) *height = sz.cy;
3314 return (sz.cx / 26 + 1) / 2;
3317 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3319 FIXME("(%d): stub\n", fEnableEUDC);
3320 return FALSE;
3323 /***********************************************************************
3324 * GetCharWidthI (GDI32.@)
3326 * Retrieve widths of characters.
3328 * PARAMS
3329 * hdc [I] Handle to a device context.
3330 * first [I] First glyph in range to query.
3331 * count [I] Number of glyph indices to query.
3332 * glyphs [I] Array of glyphs to query.
3333 * buffer [O] Buffer to receive character widths.
3335 * NOTES
3336 * Only works with TrueType fonts.
3338 * RETURNS
3339 * Success: TRUE
3340 * Failure: FALSE
3342 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3344 ABC *abc;
3345 unsigned int i;
3347 TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3349 if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3350 return FALSE;
3352 if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3354 HeapFree(GetProcessHeap(), 0, abc);
3355 return FALSE;
3358 for (i = 0; i < count; i++)
3359 buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3361 HeapFree(GetProcessHeap(), 0, abc);
3362 return TRUE;
3365 /***********************************************************************
3366 * GetFontUnicodeRanges (GDI32.@)
3368 * Retrieve a list of supported Unicode characters in a font.
3370 * PARAMS
3371 * hdc [I] Handle to a device context.
3372 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3374 * RETURNS
3375 * Success: Number of bytes written to the buffer pointed to by lpgs.
3376 * Failure: 0
3379 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3381 DWORD ret = 0;
3382 DC *dc = get_dc_ptr(hdc);
3384 TRACE("(%p, %p)\n", hdc, lpgs);
3386 if (!dc) return 0;
3388 if (dc->gdiFont) ret = WineEngGetFontUnicodeRanges(dc->gdiFont, lpgs);
3389 release_dc_ptr(dc);
3390 return ret;
3394 /*************************************************************
3395 * FontIsLinked (GDI32.@)
3397 BOOL WINAPI FontIsLinked(HDC hdc)
3399 DC *dc = get_dc_ptr(hdc);
3400 BOOL ret = FALSE;
3402 if (!dc) return FALSE;
3403 if (dc->gdiFont) ret = WineEngFontIsLinked(dc->gdiFont);
3404 release_dc_ptr(dc);
3405 TRACE("returning %d\n", ret);
3406 return ret;
3409 /*************************************************************
3410 * GdiRealizationInfo (GDI32.@)
3412 * Returns a structure that contains some font information.
3414 BOOL WINAPI GdiRealizationInfo(HDC hdc, realization_info_t *info)
3416 DC *dc = get_dc_ptr(hdc);
3417 BOOL ret = FALSE;
3419 if (!dc) return FALSE;
3420 if (dc->gdiFont) ret = WineEngRealizationInfo(dc->gdiFont, info);
3421 release_dc_ptr(dc);
3423 return ret;