gdi32: Add a null driver fallback implementation for non-antialiased text output.
[wine/multimedia.git] / dlls / gdi32 / font.c
blobee824f0b2d4803434e943959cd1537e290a39376
1 /*
2 * GDI font objects
4 * Copyright 1993 Alexandre Julliard
5 * 1997 Alex Korobka
6 * Copyright 2002,2003 Shachar Shemesh
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "config.h"
24 #include "wine/port.h"
26 #include <stdarg.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <assert.h>
30 #include "winerror.h"
31 #include "windef.h"
32 #include "winbase.h"
33 #include "winnls.h"
34 #include "gdi_private.h"
35 #include "wine/exception.h"
36 #include "wine/unicode.h"
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(font);
41 /* Device -> World size conversion */
43 /* Performs a device to world transformation on the specified width (which
44 * is in integer format).
46 static inline INT INTERNAL_XDSTOWS(DC *dc, INT width)
48 double floatWidth;
50 /* Perform operation with floating point */
51 floatWidth = (double)width * dc->xformVport2World.eM11;
52 /* Round to integers */
53 return GDI_ROUND(floatWidth);
56 /* Performs a device to world transformation on the specified size (which
57 * is in integer format).
59 static inline INT INTERNAL_YDSTOWS(DC *dc, INT height)
61 double floatHeight;
63 /* Perform operation with floating point */
64 floatHeight = (double)height * dc->xformVport2World.eM22;
65 /* Round to integers */
66 return GDI_ROUND(floatHeight);
69 static inline INT INTERNAL_XWSTODS(DC *dc, INT width)
71 POINT pt[2];
72 pt[0].x = pt[0].y = 0;
73 pt[1].x = width;
74 pt[1].y = 0;
75 LPtoDP(dc->hSelf, pt, 2);
76 return pt[1].x - pt[0].x;
79 static inline INT INTERNAL_YWSTODS(DC *dc, INT height)
81 POINT pt[2];
82 pt[0].x = pt[0].y = 0;
83 pt[1].x = 0;
84 pt[1].y = height;
85 LPtoDP(dc->hSelf, pt, 2);
86 return pt[1].y - pt[0].y;
89 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc );
90 static INT FONT_GetObjectA( HGDIOBJ handle, INT count, LPVOID buffer );
91 static INT FONT_GetObjectW( HGDIOBJ handle, INT count, LPVOID buffer );
92 static BOOL FONT_DeleteObject( HGDIOBJ handle );
94 static const struct gdi_obj_funcs font_funcs =
96 FONT_SelectObject, /* pSelectObject */
97 FONT_GetObjectA, /* pGetObjectA */
98 FONT_GetObjectW, /* pGetObjectW */
99 NULL, /* pUnrealizeObject */
100 FONT_DeleteObject /* pDeleteObject */
103 typedef struct
105 GDIOBJHDR header;
106 LOGFONTW logfont;
107 } FONTOBJ;
109 struct font_enum
111 LPLOGFONTW lpLogFontParam;
112 FONTENUMPROCW lpEnumFunc;
113 LPARAM lpData;
114 BOOL unicode;
115 HDC hdc;
119 * For TranslateCharsetInfo
121 #define MAXTCIINDEX 32
122 static const CHARSETINFO FONT_tci[MAXTCIINDEX] = {
123 /* ANSI */
124 { ANSI_CHARSET, 1252, {{0,0,0,0},{FS_LATIN1,0}} },
125 { EASTEUROPE_CHARSET, 1250, {{0,0,0,0},{FS_LATIN2,0}} },
126 { RUSSIAN_CHARSET, 1251, {{0,0,0,0},{FS_CYRILLIC,0}} },
127 { GREEK_CHARSET, 1253, {{0,0,0,0},{FS_GREEK,0}} },
128 { TURKISH_CHARSET, 1254, {{0,0,0,0},{FS_TURKISH,0}} },
129 { HEBREW_CHARSET, 1255, {{0,0,0,0},{FS_HEBREW,0}} },
130 { ARABIC_CHARSET, 1256, {{0,0,0,0},{FS_ARABIC,0}} },
131 { BALTIC_CHARSET, 1257, {{0,0,0,0},{FS_BALTIC,0}} },
132 { VIETNAMESE_CHARSET, 1258, {{0,0,0,0},{FS_VIETNAMESE,0}} },
133 /* reserved by ANSI */
134 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
135 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
136 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
137 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
138 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
139 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
140 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
141 /* ANSI and OEM */
142 { THAI_CHARSET, 874, {{0,0,0,0},{FS_THAI,0}} },
143 { SHIFTJIS_CHARSET, 932, {{0,0,0,0},{FS_JISJAPAN,0}} },
144 { GB2312_CHARSET, 936, {{0,0,0,0},{FS_CHINESESIMP,0}} },
145 { HANGEUL_CHARSET, 949, {{0,0,0,0},{FS_WANSUNG,0}} },
146 { CHINESEBIG5_CHARSET, 950, {{0,0,0,0},{FS_CHINESETRAD,0}} },
147 { JOHAB_CHARSET, 1361, {{0,0,0,0},{FS_JOHAB,0}} },
148 /* reserved for alternate ANSI and OEM */
149 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
150 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
151 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
152 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
153 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
154 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
155 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
156 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
157 /* reserved for system */
158 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
159 { SYMBOL_CHARSET, CP_SYMBOL, {{0,0,0,0},{FS_SYMBOL,0}} }
162 static void FONT_LogFontAToW( const LOGFONTA *fontA, LPLOGFONTW fontW )
164 memcpy(fontW, fontA, sizeof(LOGFONTA) - LF_FACESIZE);
165 MultiByteToWideChar(CP_ACP, 0, fontA->lfFaceName, -1, fontW->lfFaceName,
166 LF_FACESIZE);
167 fontW->lfFaceName[LF_FACESIZE-1] = 0;
170 static void FONT_LogFontWToA( const LOGFONTW *fontW, LPLOGFONTA fontA )
172 memcpy(fontA, fontW, sizeof(LOGFONTA) - LF_FACESIZE);
173 WideCharToMultiByte(CP_ACP, 0, fontW->lfFaceName, -1, fontA->lfFaceName,
174 LF_FACESIZE, NULL, NULL);
175 fontA->lfFaceName[LF_FACESIZE-1] = 0;
178 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEXA fontA )
180 FONT_LogFontWToA( &fontW->elfLogFont, &fontA->elfLogFont );
182 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
183 (LPSTR) fontA->elfFullName, LF_FULLFACESIZE, NULL, NULL );
184 fontA->elfFullName[LF_FULLFACESIZE-1] = '\0';
185 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
186 (LPSTR) fontA->elfStyle, LF_FACESIZE, NULL, NULL );
187 fontA->elfStyle[LF_FACESIZE-1] = '\0';
188 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
189 (LPSTR) fontA->elfScript, LF_FACESIZE, NULL, NULL );
190 fontA->elfScript[LF_FACESIZE-1] = '\0';
193 static void FONT_EnumLogFontExAToW( const ENUMLOGFONTEXA *fontA, LPENUMLOGFONTEXW fontW )
195 FONT_LogFontAToW( &fontA->elfLogFont, &fontW->elfLogFont );
197 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfFullName, -1,
198 fontW->elfFullName, LF_FULLFACESIZE );
199 fontW->elfFullName[LF_FULLFACESIZE-1] = '\0';
200 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfStyle, -1,
201 fontW->elfStyle, LF_FACESIZE );
202 fontW->elfStyle[LF_FACESIZE-1] = '\0';
203 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfScript, -1,
204 fontW->elfScript, LF_FACESIZE );
205 fontW->elfScript[LF_FACESIZE-1] = '\0';
208 /***********************************************************************
209 * TEXTMETRIC conversion functions.
211 static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
213 ptmA->tmHeight = ptmW->tmHeight;
214 ptmA->tmAscent = ptmW->tmAscent;
215 ptmA->tmDescent = ptmW->tmDescent;
216 ptmA->tmInternalLeading = ptmW->tmInternalLeading;
217 ptmA->tmExternalLeading = ptmW->tmExternalLeading;
218 ptmA->tmAveCharWidth = ptmW->tmAveCharWidth;
219 ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth;
220 ptmA->tmWeight = ptmW->tmWeight;
221 ptmA->tmOverhang = ptmW->tmOverhang;
222 ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX;
223 ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
224 ptmA->tmFirstChar = min(ptmW->tmFirstChar, 255);
225 if (ptmW->tmCharSet == SYMBOL_CHARSET)
227 ptmA->tmFirstChar = 0x1e;
228 ptmA->tmLastChar = 0xff; /* win9x behaviour - we need the OS2 table data to calculate correctly */
230 else if (ptmW->tmPitchAndFamily & TMPF_TRUETYPE)
232 ptmA->tmFirstChar = ptmW->tmDefaultChar - 1;
233 ptmA->tmLastChar = min(ptmW->tmLastChar, 0xff);
235 else
237 ptmA->tmFirstChar = min(ptmW->tmFirstChar, 0xff);
238 ptmA->tmLastChar = min(ptmW->tmLastChar, 0xff);
240 ptmA->tmDefaultChar = ptmW->tmDefaultChar;
241 ptmA->tmBreakChar = ptmW->tmBreakChar;
242 ptmA->tmItalic = ptmW->tmItalic;
243 ptmA->tmUnderlined = ptmW->tmUnderlined;
244 ptmA->tmStruckOut = ptmW->tmStruckOut;
245 ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
246 ptmA->tmCharSet = ptmW->tmCharSet;
250 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW *ptmW, NEWTEXTMETRICEXA *ptmA )
252 FONT_TextMetricWToA((const TEXTMETRICW *)ptmW, (LPTEXTMETRICA)ptmA);
253 ptmA->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
254 ptmA->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
255 ptmA->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
256 ptmA->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
257 memcpy(&ptmA->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
261 /***********************************************************************
262 * GdiGetCodePage (GDI32.@)
264 DWORD WINAPI GdiGetCodePage( HDC hdc )
266 UINT cp = CP_ACP;
267 DC *dc = get_dc_ptr( hdc );
269 if (dc)
271 cp = dc->font_code_page;
272 release_dc_ptr( dc );
274 return cp;
277 /***********************************************************************
278 * FONT_mbtowc
280 * Returns a Unicode translation of str using the charset of the
281 * currently selected font in hdc. If count is -1 then str is assumed
282 * to be '\0' terminated, otherwise it contains the number of bytes to
283 * convert. If plenW is non-NULL, on return it will point to the
284 * number of WCHARs that have been written. If pCP is non-NULL, on
285 * return it will point to the codepage used in the conversion. The
286 * caller should free the returned LPWSTR from the process heap
287 * itself.
289 static LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
291 UINT cp;
292 INT lenW;
293 LPWSTR strW;
295 cp = GdiGetCodePage( hdc );
297 if(count == -1) count = strlen(str);
298 lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
299 strW = HeapAlloc(GetProcessHeap(), 0, lenW*sizeof(WCHAR));
300 MultiByteToWideChar(cp, 0, str, count, strW, lenW);
301 TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW));
302 if(plenW) *plenW = lenW;
303 if(pCP) *pCP = cp;
304 return strW;
307 /***********************************************************************
308 * CreateFontIndirectExA (GDI32.@)
310 HFONT WINAPI CreateFontIndirectExA( const ENUMLOGFONTEXDVA *penumexA )
312 ENUMLOGFONTEXDVW enumexW;
314 if (!penumexA) return 0;
316 FONT_EnumLogFontExAToW( &penumexA->elfEnumLogfontEx, &enumexW.elfEnumLogfontEx );
317 enumexW.elfDesignVector = penumexA->elfDesignVector;
318 return CreateFontIndirectExW( &enumexW );
321 /***********************************************************************
322 * CreateFontIndirectExW (GDI32.@)
324 HFONT WINAPI CreateFontIndirectExW( const ENUMLOGFONTEXDVW *penumex )
326 HFONT hFont;
327 FONTOBJ *fontPtr;
328 const LOGFONTW *plf;
330 if (!penumex) return 0;
332 if (penumex->elfEnumLogfontEx.elfFullName[0] ||
333 penumex->elfEnumLogfontEx.elfStyle[0] ||
334 penumex->elfEnumLogfontEx.elfScript[0])
336 FIXME("some fields ignored. fullname=%s, style=%s, script=%s\n",
337 debugstr_w(penumex->elfEnumLogfontEx.elfFullName),
338 debugstr_w(penumex->elfEnumLogfontEx.elfStyle),
339 debugstr_w(penumex->elfEnumLogfontEx.elfScript));
342 plf = &penumex->elfEnumLogfontEx.elfLogFont;
343 if (!(fontPtr = HeapAlloc( GetProcessHeap(), 0, sizeof(*fontPtr) ))) return 0;
345 fontPtr->logfont = *plf;
347 if (plf->lfEscapement != plf->lfOrientation)
349 /* this should really depend on whether GM_ADVANCED is set */
350 fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
351 WARN("orientation angle %f set to "
352 "escapement angle %f for new font %p\n",
353 plf->lfOrientation/10., plf->lfEscapement/10., fontPtr);
356 if (!(hFont = alloc_gdi_handle( &fontPtr->header, OBJ_FONT, &font_funcs )))
358 HeapFree( GetProcessHeap(), 0, fontPtr );
359 return 0;
362 TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
363 plf->lfHeight, plf->lfWidth,
364 plf->lfEscapement, plf->lfOrientation,
365 plf->lfPitchAndFamily,
366 plf->lfOutPrecision, plf->lfClipPrecision,
367 plf->lfQuality, plf->lfCharSet,
368 debugstr_w(plf->lfFaceName),
369 plf->lfWeight > 400 ? "Bold" : "",
370 plf->lfItalic ? "Italic" : "",
371 plf->lfUnderline ? "Underline" : "", hFont);
373 return hFont;
376 /***********************************************************************
377 * CreateFontIndirectA (GDI32.@)
379 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *plfA )
381 LOGFONTW lfW;
383 if (!plfA) return 0;
385 FONT_LogFontAToW( plfA, &lfW );
386 return CreateFontIndirectW( &lfW );
389 /***********************************************************************
390 * CreateFontIndirectW (GDI32.@)
392 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
394 ENUMLOGFONTEXDVW exdv;
396 if (!plf) return 0;
398 exdv.elfEnumLogfontEx.elfLogFont = *plf;
399 exdv.elfEnumLogfontEx.elfFullName[0] = 0;
400 exdv.elfEnumLogfontEx.elfStyle[0] = 0;
401 exdv.elfEnumLogfontEx.elfScript[0] = 0;
402 return CreateFontIndirectExW( &exdv );
405 /*************************************************************************
406 * CreateFontA (GDI32.@)
408 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
409 INT orient, INT weight, DWORD italic,
410 DWORD underline, DWORD strikeout, DWORD charset,
411 DWORD outpres, DWORD clippres, DWORD quality,
412 DWORD pitch, LPCSTR name )
414 LOGFONTA logfont;
416 logfont.lfHeight = height;
417 logfont.lfWidth = width;
418 logfont.lfEscapement = esc;
419 logfont.lfOrientation = orient;
420 logfont.lfWeight = weight;
421 logfont.lfItalic = italic;
422 logfont.lfUnderline = underline;
423 logfont.lfStrikeOut = strikeout;
424 logfont.lfCharSet = charset;
425 logfont.lfOutPrecision = outpres;
426 logfont.lfClipPrecision = clippres;
427 logfont.lfQuality = quality;
428 logfont.lfPitchAndFamily = pitch;
430 if (name)
431 lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
432 else
433 logfont.lfFaceName[0] = '\0';
435 return CreateFontIndirectA( &logfont );
438 /*************************************************************************
439 * CreateFontW (GDI32.@)
441 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
442 INT orient, INT weight, DWORD italic,
443 DWORD underline, DWORD strikeout, DWORD charset,
444 DWORD outpres, DWORD clippres, DWORD quality,
445 DWORD pitch, LPCWSTR name )
447 LOGFONTW logfont;
449 logfont.lfHeight = height;
450 logfont.lfWidth = width;
451 logfont.lfEscapement = esc;
452 logfont.lfOrientation = orient;
453 logfont.lfWeight = weight;
454 logfont.lfItalic = italic;
455 logfont.lfUnderline = underline;
456 logfont.lfStrikeOut = strikeout;
457 logfont.lfCharSet = charset;
458 logfont.lfOutPrecision = outpres;
459 logfont.lfClipPrecision = clippres;
460 logfont.lfQuality = quality;
461 logfont.lfPitchAndFamily = pitch;
463 if (name)
464 lstrcpynW(logfont.lfFaceName, name,
465 sizeof(logfont.lfFaceName) / sizeof(WCHAR));
466 else
467 logfont.lfFaceName[0] = '\0';
469 return CreateFontIndirectW( &logfont );
472 static void update_font_code_page( DC *dc )
474 CHARSETINFO csi;
475 int charset = GetTextCharsetInfo( dc->hSelf, NULL, 0 );
477 /* Hmm, nicely designed api this one! */
478 if (TranslateCharsetInfo( ULongToPtr(charset), &csi, TCI_SRCCHARSET) )
479 dc->font_code_page = csi.ciACP;
480 else {
481 switch(charset) {
482 case OEM_CHARSET:
483 dc->font_code_page = GetOEMCP();
484 break;
485 case DEFAULT_CHARSET:
486 dc->font_code_page = GetACP();
487 break;
489 case VISCII_CHARSET:
490 case TCVN_CHARSET:
491 case KOI8_CHARSET:
492 case ISO3_CHARSET:
493 case ISO4_CHARSET:
494 case ISO10_CHARSET:
495 case CELTIC_CHARSET:
496 /* FIXME: These have no place here, but because x11drv
497 enumerates fonts with these (made up) charsets some apps
498 might use them and then the FIXME below would become
499 annoying. Now we could pick the intended codepage for
500 each of these, but since it's broken anyway we'll just
501 use CP_ACP and hope it'll go away...
503 dc->font_code_page = CP_ACP;
504 break;
506 default:
507 FIXME("Can't find codepage for charset %d\n", charset);
508 dc->font_code_page = CP_ACP;
509 break;
513 TRACE("charset %d => cp %d\n", charset, dc->font_code_page);
516 /***********************************************************************
517 * FONT_SelectObject
519 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc )
521 HGDIOBJ ret = 0;
522 DC *dc = get_dc_ptr( hdc );
523 PHYSDEV physdev;
525 if (!dc) return 0;
527 if (!GDI_inc_ref_count( handle ))
529 release_dc_ptr( dc );
530 return 0;
533 physdev = GET_DC_PHYSDEV( dc, pSelectFont );
534 if (physdev->funcs->pSelectFont( physdev, handle ))
536 ret = dc->hFont;
537 dc->hFont = handle;
538 update_font_code_page( dc );
539 GDI_dec_ref_count( ret );
541 else GDI_dec_ref_count( handle );
543 release_dc_ptr( dc );
544 return ret;
548 /***********************************************************************
549 * FONT_GetObjectA
551 static INT FONT_GetObjectA( HGDIOBJ handle, INT count, LPVOID buffer )
553 FONTOBJ *font = GDI_GetObjPtr( handle, OBJ_FONT );
554 LOGFONTA lfA;
556 if (!font) return 0;
557 if (buffer)
559 FONT_LogFontWToA( &font->logfont, &lfA );
560 if (count > sizeof(lfA)) count = sizeof(lfA);
561 memcpy( buffer, &lfA, count );
563 else count = sizeof(lfA);
564 GDI_ReleaseObj( handle );
565 return count;
568 /***********************************************************************
569 * FONT_GetObjectW
571 static INT FONT_GetObjectW( HGDIOBJ handle, INT count, LPVOID buffer )
573 FONTOBJ *font = GDI_GetObjPtr( handle, OBJ_FONT );
575 if (!font) return 0;
576 if (buffer)
578 if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
579 memcpy( buffer, &font->logfont, count );
581 else count = sizeof(LOGFONTW);
582 GDI_ReleaseObj( handle );
583 return count;
587 /***********************************************************************
588 * FONT_DeleteObject
590 static BOOL FONT_DeleteObject( HGDIOBJ handle )
592 FONTOBJ *obj;
594 WineEngDestroyFontInstance( handle );
596 if (!(obj = free_gdi_handle( handle ))) return FALSE;
597 return HeapFree( GetProcessHeap(), 0, obj );
601 /***********************************************************************
602 * FONT_EnumInstance
604 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
605 * We have to use other types because of the FONTENUMPROCW definition.
607 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
608 DWORD fType, LPARAM lp )
610 struct font_enum *pfe = (struct font_enum *)lp;
611 INT ret = 1;
613 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
614 if ((!pfe->lpLogFontParam ||
615 pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
616 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
617 (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
619 /* convert font metrics */
620 ENUMLOGFONTEXA logfont;
621 NEWTEXTMETRICEXA tmA;
623 if (!pfe->unicode)
625 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
626 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
627 plf = (LOGFONTW *)&logfont.elfLogFont;
628 ptm = (TEXTMETRICW *)&tmA;
630 ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
632 return ret;
635 /***********************************************************************
636 * FONT_EnumFontFamiliesEx
638 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf, FONTENUMPROCW efproc,
639 LPARAM lParam, BOOL unicode )
641 INT ret = 0;
642 DC *dc = get_dc_ptr( hDC );
643 struct font_enum fe;
645 if (dc)
647 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pEnumFonts );
649 if (plf) TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName), plf->lfCharSet);
650 fe.lpLogFontParam = plf;
651 fe.lpEnumFunc = efproc;
652 fe.lpData = lParam;
653 fe.unicode = unicode;
654 fe.hdc = hDC;
655 ret = physdev->funcs->pEnumFonts( physdev, plf, FONT_EnumInstance, (LPARAM)&fe );
656 release_dc_ptr( dc );
658 return ret;
661 /***********************************************************************
662 * EnumFontFamiliesExW (GDI32.@)
664 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
665 FONTENUMPROCW efproc,
666 LPARAM lParam, DWORD dwFlags )
668 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, TRUE );
671 /***********************************************************************
672 * EnumFontFamiliesExA (GDI32.@)
674 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
675 FONTENUMPROCA efproc,
676 LPARAM lParam, DWORD dwFlags)
678 LOGFONTW lfW, *plfW;
680 if (plf)
682 FONT_LogFontAToW( plf, &lfW );
683 plfW = &lfW;
685 else plfW = NULL;
687 return FONT_EnumFontFamiliesEx( hDC, plfW, (FONTENUMPROCW)efproc, lParam, FALSE );
690 /***********************************************************************
691 * EnumFontFamiliesA (GDI32.@)
693 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
694 FONTENUMPROCA efproc, LPARAM lpData )
696 LOGFONTA lf, *plf;
698 if (lpFamily)
700 if (!*lpFamily) return 1;
701 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
702 lf.lfCharSet = DEFAULT_CHARSET;
703 lf.lfPitchAndFamily = 0;
704 plf = &lf;
706 else plf = NULL;
708 return EnumFontFamiliesExA( hDC, plf, efproc, lpData, 0 );
711 /***********************************************************************
712 * EnumFontFamiliesW (GDI32.@)
714 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
715 FONTENUMPROCW efproc, LPARAM lpData )
717 LOGFONTW lf, *plf;
719 if (lpFamily)
721 if (!*lpFamily) return 1;
722 lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
723 lf.lfCharSet = DEFAULT_CHARSET;
724 lf.lfPitchAndFamily = 0;
725 plf = &lf;
727 else plf = NULL;
729 return EnumFontFamiliesExW( hDC, plf, efproc, lpData, 0 );
732 /***********************************************************************
733 * EnumFontsA (GDI32.@)
735 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
736 LPARAM lpData )
738 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
741 /***********************************************************************
742 * EnumFontsW (GDI32.@)
744 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
745 LPARAM lpData )
747 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
751 /***********************************************************************
752 * GetTextCharacterExtra (GDI32.@)
754 INT WINAPI GetTextCharacterExtra( HDC hdc )
756 INT ret;
757 DC *dc = get_dc_ptr( hdc );
758 if (!dc) return 0x80000000;
759 ret = dc->charExtra;
760 release_dc_ptr( dc );
761 return ret;
765 /***********************************************************************
766 * SetTextCharacterExtra (GDI32.@)
768 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
770 INT ret = 0x80000000;
771 DC * dc = get_dc_ptr( hdc );
773 if (dc)
775 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetTextCharacterExtra );
776 extra = physdev->funcs->pSetTextCharacterExtra( physdev, extra );
777 if (extra != 0x80000000)
779 ret = dc->charExtra;
780 dc->charExtra = extra;
782 release_dc_ptr( dc );
784 return ret;
788 /***********************************************************************
789 * SetTextJustification (GDI32.@)
791 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
793 BOOL ret;
794 PHYSDEV physdev;
795 DC * dc = get_dc_ptr( hdc );
797 if (!dc) return FALSE;
799 physdev = GET_DC_PHYSDEV( dc, pSetTextJustification );
800 ret = physdev->funcs->pSetTextJustification( physdev, extra, breaks );
801 if (ret)
803 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
804 if (!extra) breaks = 0;
805 if (breaks)
807 dc->breakExtra = extra / breaks;
808 dc->breakRem = extra - (breaks * dc->breakExtra);
810 else
812 dc->breakExtra = 0;
813 dc->breakRem = 0;
816 release_dc_ptr( dc );
817 return ret;
821 /***********************************************************************
822 * GetTextFaceA (GDI32.@)
824 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
826 INT res = GetTextFaceW(hdc, 0, NULL);
827 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
828 GetTextFaceW( hdc, res, nameW );
830 if (name)
832 if (count)
834 res = WideCharToMultiByte(CP_ACP, 0, nameW, -1, name, count, NULL, NULL);
835 if (res == 0)
836 res = count;
837 name[count-1] = 0;
838 /* GetTextFaceA does NOT include the nul byte in the return count. */
839 res--;
841 else
842 res = 0;
844 else
845 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
846 HeapFree( GetProcessHeap(), 0, nameW );
847 return res;
850 /***********************************************************************
851 * GetTextFaceW (GDI32.@)
853 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
855 PHYSDEV dev;
856 INT ret;
858 DC * dc = get_dc_ptr( hdc );
859 if (!dc) return 0;
861 dev = GET_DC_PHYSDEV( dc, pGetTextFace );
862 ret = dev->funcs->pGetTextFace( dev, count, name );
863 release_dc_ptr( dc );
864 return ret;
868 /***********************************************************************
869 * GetTextExtentPoint32A (GDI32.@)
871 * See GetTextExtentPoint32W.
873 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
874 LPSIZE size )
876 BOOL ret = FALSE;
877 INT wlen;
878 LPWSTR p;
880 if (count < 0) return FALSE;
882 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
884 if (p)
886 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
887 HeapFree( GetProcessHeap(), 0, p );
890 TRACE("(%p %s %d %p): returning %d x %d\n",
891 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
892 return ret;
896 /***********************************************************************
897 * GetTextExtentPoint32W [GDI32.@]
899 * Computes width/height for a string.
901 * Computes width and height of the specified string.
903 * RETURNS
904 * Success: TRUE
905 * Failure: FALSE
907 BOOL WINAPI GetTextExtentPoint32W(
908 HDC hdc, /* [in] Handle of device context */
909 LPCWSTR str, /* [in] Address of text string */
910 INT count, /* [in] Number of characters in string */
911 LPSIZE size) /* [out] Address of structure for string size */
913 return GetTextExtentExPointW(hdc, str, count, 0, NULL, NULL, size);
916 /***********************************************************************
917 * GetTextExtentExPointI [GDI32.@]
919 * Computes width and height of the array of glyph indices.
921 * PARAMS
922 * hdc [I] Handle of device context.
923 * indices [I] Glyph index array.
924 * count [I] Number of glyphs in array.
925 * max_ext [I] Maximum width in glyphs.
926 * nfit [O] Maximum number of characters.
927 * dxs [O] Partial string widths.
928 * size [O] Returned string size.
930 * RETURNS
931 * Success: TRUE
932 * Failure: FALSE
934 BOOL WINAPI GetTextExtentExPointI( HDC hdc, const WORD *indices, INT count, INT max_ext,
935 LPINT nfit, LPINT dxs, LPSIZE size )
937 PHYSDEV dev;
938 BOOL ret;
939 DC *dc;
941 if (count < 0) return FALSE;
943 dc = get_dc_ptr( hdc );
944 if (!dc) return FALSE;
946 dev = GET_DC_PHYSDEV( dc, pGetTextExtentExPointI );
947 ret = dev->funcs->pGetTextExtentExPointI( dev, indices, count, max_ext, nfit, dxs, size );
948 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
949 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
950 size->cx += count * dc->charExtra;
951 release_dc_ptr( dc );
953 TRACE("(%p %p %d %p): returning %d x %d\n",
954 hdc, indices, count, size, size->cx, size->cy );
955 return ret;
958 /***********************************************************************
959 * GetTextExtentPointI [GDI32.@]
961 * Computes width and height of the array of glyph indices.
963 * PARAMS
964 * hdc [I] Handle of device context.
965 * indices [I] Glyph index array.
966 * count [I] Number of glyphs in array.
967 * size [O] Returned string size.
969 * RETURNS
970 * Success: TRUE
971 * Failure: FALSE
973 BOOL WINAPI GetTextExtentPointI( HDC hdc, const WORD *indices, INT count, LPSIZE size )
975 return GetTextExtentExPointI( hdc, indices, count, 0, NULL, NULL, size );
979 /***********************************************************************
980 * GetTextExtentPointA (GDI32.@)
982 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
983 LPSIZE size )
985 TRACE("not bug compatible.\n");
986 return GetTextExtentPoint32A( hdc, str, count, size );
989 /***********************************************************************
990 * GetTextExtentPointW (GDI32.@)
992 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
993 LPSIZE size )
995 TRACE("not bug compatible.\n");
996 return GetTextExtentPoint32W( hdc, str, count, size );
1000 /***********************************************************************
1001 * GetTextExtentExPointA (GDI32.@)
1003 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1004 INT maxExt, LPINT lpnFit,
1005 LPINT alpDx, LPSIZE size )
1007 BOOL ret;
1008 INT wlen;
1009 INT *walpDx = NULL;
1010 LPWSTR p = NULL;
1012 if (count < 0) return FALSE;
1014 if (alpDx)
1016 walpDx = HeapAlloc( GetProcessHeap(), 0, count * sizeof(INT) );
1017 if (!walpDx) return FALSE;
1020 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1021 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
1022 if (walpDx)
1024 INT n = lpnFit ? *lpnFit : wlen;
1025 INT i, j;
1026 for(i = 0, j = 0; i < n; i++, j++)
1028 alpDx[j] = walpDx[i];
1029 if (IsDBCSLeadByte(str[j])) alpDx[++j] = walpDx[i];
1032 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1033 HeapFree( GetProcessHeap(), 0, p );
1034 HeapFree( GetProcessHeap(), 0, walpDx );
1035 return ret;
1039 /***********************************************************************
1040 * GetTextExtentExPointW (GDI32.@)
1042 * Return the size of the string as it would be if it was output properly by
1043 * e.g. TextOut.
1045 * This should include
1046 * - Intercharacter spacing
1047 * - justification spacing (not yet done)
1048 * - kerning? see below
1050 * Kerning. Since kerning would be carried out by the rendering code it should
1051 * be done by the driver. However they don't support it yet. Also I am not
1052 * yet persuaded that (certainly under Win95) any kerning is actually done.
1054 * str: According to MSDN this should be null-terminated. That is not true; a
1055 * null will not terminate it early.
1056 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1057 * than count. I have seen it be either the size of the full string or
1058 * 1 less than the size of the full string. I have not seen it bear any
1059 * resemblance to the portion that would fit.
1060 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1061 * trailing intercharacter spacing and any trailing justification.
1063 * FIXME
1064 * Currently we do this by measuring each character etc. We should do it by
1065 * passing the request to the driver, perhaps by extending the
1066 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1067 * thinking about kerning issues and rounding issues in the justification.
1070 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1071 INT maxExt, LPINT lpnFit,
1072 LPINT alpDx, LPSIZE size )
1074 INT nFit = 0;
1075 LPINT dxs = NULL;
1076 DC *dc;
1077 BOOL ret = FALSE;
1078 TEXTMETRICW tm;
1079 PHYSDEV dev;
1081 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1083 if (count < 0) return FALSE;
1085 dc = get_dc_ptr(hdc);
1086 if (!dc) return FALSE;
1088 GetTextMetricsW(hdc, &tm);
1090 /* If we need to calculate nFit, then we need the partial extents even if
1091 the user hasn't provided us with an array. */
1092 if (lpnFit)
1094 dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]);
1095 if (! dxs)
1097 release_dc_ptr(dc);
1098 SetLastError(ERROR_OUTOFMEMORY);
1099 return FALSE;
1102 else
1103 dxs = alpDx;
1105 dev = GET_DC_PHYSDEV( dc, pGetTextExtentExPoint );
1106 ret = dev->funcs->pGetTextExtentExPoint(dev, str, count, 0, NULL, dxs, size);
1108 /* Perform device size to world size transformations. */
1109 if (ret)
1111 INT extra = dc->charExtra,
1112 breakExtra = dc->breakExtra,
1113 breakRem = dc->breakRem,
1116 if (dxs)
1118 for (i = 0; i < count; ++i)
1120 dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
1121 dxs[i] += (i+1) * extra;
1122 if (count > 1 && (breakExtra || breakRem) && str[i] == tm.tmBreakChar)
1124 dxs[i] += breakExtra;
1125 if (breakRem > 0)
1127 breakRem--;
1128 dxs[i]++;
1131 if (dxs[i] <= maxExt)
1132 ++nFit;
1134 breakRem = dc->breakRem;
1136 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1137 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1139 if (!dxs && count > 1 && (breakExtra || breakRem))
1141 for (i = 0; i < count; i++)
1143 if (str[i] == tm.tmBreakChar)
1145 size->cx += breakExtra;
1146 if (breakRem > 0)
1148 breakRem--;
1149 (size->cx)++;
1156 if (lpnFit)
1157 *lpnFit = nFit;
1159 if (! alpDx)
1160 HeapFree(GetProcessHeap(), 0, dxs);
1162 release_dc_ptr( dc );
1164 TRACE("returning %d %d x %d\n",nFit,size->cx,size->cy);
1165 return ret;
1168 /***********************************************************************
1169 * GetTextMetricsA (GDI32.@)
1171 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1173 TEXTMETRICW tm32;
1175 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1176 FONT_TextMetricWToA( &tm32, metrics );
1177 return TRUE;
1180 /***********************************************************************
1181 * GetTextMetricsW (GDI32.@)
1183 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1185 PHYSDEV physdev;
1186 BOOL ret = FALSE;
1187 DC * dc = get_dc_ptr( hdc );
1188 if (!dc) return FALSE;
1190 physdev = GET_DC_PHYSDEV( dc, pGetTextMetrics );
1191 ret = physdev->funcs->pGetTextMetrics( physdev, metrics );
1193 if (ret)
1195 /* device layer returns values in device units
1196 * therefore we have to convert them to logical */
1198 metrics->tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1199 metrics->tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1201 #define WDPTOLP(x) ((x<0)? \
1202 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1203 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1204 #define HDPTOLP(y) ((y<0)? \
1205 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1206 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1208 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1209 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1210 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1211 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1212 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1213 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1214 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1215 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1216 ret = TRUE;
1217 #undef WDPTOLP
1218 #undef HDPTOLP
1219 TRACE("text metrics:\n"
1220 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1221 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1222 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1223 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1224 " PitchAndFamily = %02x\n"
1225 " --------------------\n"
1226 " InternalLeading = %i\n"
1227 " Ascent = %i\n"
1228 " Descent = %i\n"
1229 " Height = %i\n",
1230 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1231 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1232 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1233 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1234 metrics->tmPitchAndFamily,
1235 metrics->tmInternalLeading,
1236 metrics->tmAscent,
1237 metrics->tmDescent,
1238 metrics->tmHeight );
1240 release_dc_ptr( dc );
1241 return ret;
1245 /***********************************************************************
1246 * GetOutlineTextMetricsA (GDI32.@)
1247 * Gets metrics for TrueType fonts.
1249 * NOTES
1250 * If the supplied buffer isn't big enough Windows partially fills it up to
1251 * its given length and returns that length.
1253 * RETURNS
1254 * Success: Non-zero or size of required buffer
1255 * Failure: 0
1257 UINT WINAPI GetOutlineTextMetricsA(
1258 HDC hdc, /* [in] Handle of device context */
1259 UINT cbData, /* [in] Size of metric data array */
1260 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1262 char buf[512], *ptr;
1263 UINT ret, needed;
1264 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1265 OUTLINETEXTMETRICA *output = lpOTM;
1266 INT left, len;
1268 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1269 return 0;
1270 if(ret > sizeof(buf))
1271 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1272 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1274 needed = sizeof(OUTLINETEXTMETRICA);
1275 if(lpOTMW->otmpFamilyName)
1276 needed += WideCharToMultiByte(CP_ACP, 0,
1277 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1278 NULL, 0, NULL, NULL);
1279 if(lpOTMW->otmpFaceName)
1280 needed += WideCharToMultiByte(CP_ACP, 0,
1281 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1282 NULL, 0, NULL, NULL);
1283 if(lpOTMW->otmpStyleName)
1284 needed += WideCharToMultiByte(CP_ACP, 0,
1285 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1286 NULL, 0, NULL, NULL);
1287 if(lpOTMW->otmpFullName)
1288 needed += WideCharToMultiByte(CP_ACP, 0,
1289 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1290 NULL, 0, NULL, NULL);
1292 if(!lpOTM) {
1293 ret = needed;
1294 goto end;
1297 TRACE("needed = %d\n", needed);
1298 if(needed > cbData)
1299 /* Since the supplied buffer isn't big enough, we'll alloc one
1300 that is and memcpy the first cbData bytes into the lpOTM at
1301 the end. */
1302 output = HeapAlloc(GetProcessHeap(), 0, needed);
1304 ret = output->otmSize = min(needed, cbData);
1305 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1306 output->otmFiller = 0;
1307 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1308 output->otmfsSelection = lpOTMW->otmfsSelection;
1309 output->otmfsType = lpOTMW->otmfsType;
1310 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1311 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1312 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1313 output->otmEMSquare = lpOTMW->otmEMSquare;
1314 output->otmAscent = lpOTMW->otmAscent;
1315 output->otmDescent = lpOTMW->otmDescent;
1316 output->otmLineGap = lpOTMW->otmLineGap;
1317 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1318 output->otmsXHeight = lpOTMW->otmsXHeight;
1319 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1320 output->otmMacAscent = lpOTMW->otmMacAscent;
1321 output->otmMacDescent = lpOTMW->otmMacDescent;
1322 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1323 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1324 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1325 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1326 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1327 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1328 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1329 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1330 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1331 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1334 ptr = (char*)(output + 1);
1335 left = needed - sizeof(*output);
1337 if(lpOTMW->otmpFamilyName) {
1338 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1339 len = WideCharToMultiByte(CP_ACP, 0,
1340 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1341 ptr, left, NULL, NULL);
1342 left -= len;
1343 ptr += len;
1344 } else
1345 output->otmpFamilyName = 0;
1347 if(lpOTMW->otmpFaceName) {
1348 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1349 len = WideCharToMultiByte(CP_ACP, 0,
1350 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1351 ptr, left, NULL, NULL);
1352 left -= len;
1353 ptr += len;
1354 } else
1355 output->otmpFaceName = 0;
1357 if(lpOTMW->otmpStyleName) {
1358 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1359 len = WideCharToMultiByte(CP_ACP, 0,
1360 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1361 ptr, left, NULL, NULL);
1362 left -= len;
1363 ptr += len;
1364 } else
1365 output->otmpStyleName = 0;
1367 if(lpOTMW->otmpFullName) {
1368 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1369 len = WideCharToMultiByte(CP_ACP, 0,
1370 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1371 ptr, left, NULL, NULL);
1372 left -= len;
1373 } else
1374 output->otmpFullName = 0;
1376 assert(left == 0);
1378 if(output != lpOTM) {
1379 memcpy(lpOTM, output, cbData);
1380 HeapFree(GetProcessHeap(), 0, output);
1382 /* check if the string offsets really fit into the provided size */
1383 /* FIXME: should we check string length as well? */
1384 /* make sure that we don't read/write beyond the provided buffer */
1385 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(LPSTR))
1387 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1388 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1391 /* make sure that we don't read/write beyond the provided buffer */
1392 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(LPSTR))
1394 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1395 lpOTM->otmpFaceName = 0; /* doesn't fit */
1398 /* make sure that we don't read/write beyond the provided buffer */
1399 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(LPSTR))
1401 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1402 lpOTM->otmpStyleName = 0; /* doesn't fit */
1405 /* make sure that we don't read/write beyond the provided buffer */
1406 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(LPSTR))
1408 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1409 lpOTM->otmpFullName = 0; /* doesn't fit */
1413 end:
1414 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1415 HeapFree(GetProcessHeap(), 0, lpOTMW);
1417 return ret;
1421 /***********************************************************************
1422 * GetOutlineTextMetricsW [GDI32.@]
1424 UINT WINAPI GetOutlineTextMetricsW(
1425 HDC hdc, /* [in] Handle of device context */
1426 UINT cbData, /* [in] Size of metric data array */
1427 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1429 DC *dc = get_dc_ptr( hdc );
1430 OUTLINETEXTMETRICW *output = lpOTM;
1431 PHYSDEV dev;
1432 UINT ret;
1434 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1435 if(!dc) return 0;
1437 dev = GET_DC_PHYSDEV( dc, pGetOutlineTextMetrics );
1438 ret = dev->funcs->pGetOutlineTextMetrics( dev, cbData, output );
1440 if (lpOTM && ret > cbData)
1442 output = HeapAlloc(GetProcessHeap(), 0, ret);
1443 ret = dev->funcs->pGetOutlineTextMetrics( dev, ret, output );
1446 if (lpOTM && ret)
1448 output->otmTextMetrics.tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1449 output->otmTextMetrics.tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1451 #define WDPTOLP(x) ((x<0)? \
1452 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1453 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1454 #define HDPTOLP(y) ((y<0)? \
1455 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1456 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1458 output->otmTextMetrics.tmHeight = HDPTOLP(output->otmTextMetrics.tmHeight);
1459 output->otmTextMetrics.tmAscent = HDPTOLP(output->otmTextMetrics.tmAscent);
1460 output->otmTextMetrics.tmDescent = HDPTOLP(output->otmTextMetrics.tmDescent);
1461 output->otmTextMetrics.tmInternalLeading = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1462 output->otmTextMetrics.tmExternalLeading = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1463 output->otmTextMetrics.tmAveCharWidth = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1464 output->otmTextMetrics.tmMaxCharWidth = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1465 output->otmTextMetrics.tmOverhang = WDPTOLP(output->otmTextMetrics.tmOverhang);
1466 output->otmAscent = HDPTOLP(output->otmAscent);
1467 output->otmDescent = HDPTOLP(output->otmDescent);
1468 output->otmLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmLineGap));
1469 output->otmsCapEmHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsCapEmHeight));
1470 output->otmsXHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsXHeight));
1471 output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1472 output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1473 output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1474 output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1475 output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1476 output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1477 output->otmMacLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmMacLineGap));
1478 output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1479 output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1480 output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1481 output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1482 output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1483 output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1484 output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1485 output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1486 output->otmsStrikeoutSize = abs(INTERNAL_YDSTOWS(dc,output->otmsStrikeoutSize));
1487 output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1488 output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1489 output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1490 #undef WDPTOLP
1491 #undef HDPTOLP
1492 if(output != lpOTM)
1494 memcpy(lpOTM, output, cbData);
1495 HeapFree(GetProcessHeap(), 0, output);
1496 ret = cbData;
1499 release_dc_ptr(dc);
1500 return ret;
1503 static LPSTR FONT_GetCharsByRangeA(HDC hdc, UINT firstChar, UINT lastChar, PINT pByteLen)
1505 INT i, count = lastChar - firstChar + 1;
1506 UINT c;
1507 LPSTR str;
1509 if (count <= 0)
1510 return NULL;
1512 switch (GdiGetCodePage(hdc))
1514 case 932:
1515 case 936:
1516 case 949:
1517 case 950:
1518 case 1361:
1519 if (lastChar > 0xffff)
1520 return NULL;
1521 if ((firstChar ^ lastChar) > 0xff)
1522 return NULL;
1523 break;
1524 default:
1525 if (lastChar > 0xff)
1526 return NULL;
1527 break;
1530 str = HeapAlloc(GetProcessHeap(), 0, count * 2 + 1);
1531 if (str == NULL)
1532 return NULL;
1534 for(i = 0, c = firstChar; c <= lastChar; i++, c++)
1536 if (c > 0xff)
1537 str[i++] = (BYTE)(c >> 8);
1538 str[i] = (BYTE)c;
1540 str[i] = '\0';
1542 *pByteLen = i;
1544 return str;
1547 /***********************************************************************
1548 * GetCharWidthW (GDI32.@)
1549 * GetCharWidth32W (GDI32.@)
1551 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1552 LPINT buffer )
1554 UINT i;
1555 BOOL ret;
1556 PHYSDEV dev;
1557 DC * dc = get_dc_ptr( hdc );
1559 if (!dc) return FALSE;
1561 dev = GET_DC_PHYSDEV( dc, pGetCharWidth );
1562 ret = dev->funcs->pGetCharWidth( dev, firstChar, lastChar, buffer );
1564 if (ret)
1566 /* convert device units to logical */
1567 for( i = firstChar; i <= lastChar; i++, buffer++ )
1568 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1570 release_dc_ptr( dc );
1571 return ret;
1575 /***********************************************************************
1576 * GetCharWidthA (GDI32.@)
1577 * GetCharWidth32A (GDI32.@)
1579 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1580 LPINT buffer )
1582 INT i, wlen;
1583 LPSTR str;
1584 LPWSTR wstr;
1585 BOOL ret = TRUE;
1587 str = FONT_GetCharsByRangeA(hdc, firstChar, lastChar, &i);
1588 if(str == NULL)
1589 return FALSE;
1591 wstr = FONT_mbtowc(hdc, str, i, &wlen, NULL);
1593 for(i = 0; i < wlen; i++)
1595 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1597 ret = FALSE;
1598 break;
1600 buffer++;
1603 HeapFree(GetProcessHeap(), 0, str);
1604 HeapFree(GetProcessHeap(), 0, wstr);
1606 return ret;
1610 /* helper for nulldrv_ExtTextOut */
1611 static DWORD get_glyph_bitmap( HDC hdc, UINT index, UINT aa_flags,
1612 GLYPHMETRICS *metrics, struct gdi_image_bits *image )
1614 UINT ggo_flags = aa_flags | GGO_GLYPH_INDEX;
1615 static const MAT2 identity = { {0,1}, {0,0}, {0,0}, {0,1} };
1616 UINT indices[3] = {0, 0, 0x20};
1617 int i;
1618 DWORD ret, size;
1619 int stride;
1621 indices[0] = index;
1623 for (i = 0; i < sizeof(indices) / sizeof(indices[0]); index = indices[++i])
1625 ret = GetGlyphOutlineW( hdc, index, ggo_flags, metrics, 0, NULL, &identity );
1626 if (ret != GDI_ERROR) break;
1629 if (ret == GDI_ERROR) return ERROR_NOT_FOUND;
1630 if (!image) return ERROR_SUCCESS;
1632 image->ptr = NULL;
1633 image->free = NULL;
1634 if (!ret) return ERROR_SUCCESS; /* empty glyph */
1636 stride = get_dib_stride( metrics->gmBlackBoxX, 1 );
1637 size = metrics->gmBlackBoxY * stride;
1639 if (!(image->ptr = HeapAlloc( GetProcessHeap(), 0, size ))) return ERROR_OUTOFMEMORY;
1640 image->is_copy = TRUE;
1641 image->free = free_heap_bits;
1643 ret = GetGlyphOutlineW( hdc, index, ggo_flags, metrics, size, image->ptr, &identity );
1644 if (ret == GDI_ERROR)
1646 HeapFree( GetProcessHeap(), 0, image->ptr );
1647 return ERROR_NOT_FOUND;
1649 return ERROR_SUCCESS;
1652 /* helper for nulldrv_ExtTextOut */
1653 static void draw_glyph( HDC hdc, INT origin_x, INT origin_y, const GLYPHMETRICS *metrics,
1654 const struct gdi_image_bits *image, const RECT *clip )
1656 static const BYTE masks[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
1657 UINT x, y, i, count;
1658 BYTE *ptr = image->ptr;
1659 int stride = get_dib_stride( metrics->gmBlackBoxX, 1 );
1660 POINT *pts;
1661 RECT rect, clipped_rect;
1663 rect.left = origin_x + metrics->gmptGlyphOrigin.x;
1664 rect.top = origin_y - metrics->gmptGlyphOrigin.y;
1665 rect.right = rect.left + metrics->gmBlackBoxX;
1666 rect.bottom = rect.top + metrics->gmBlackBoxY;
1667 if (!clip) clipped_rect = rect;
1668 else if (!intersect_rect( &clipped_rect, &rect, clip )) return;
1670 pts = HeapAlloc( GetProcessHeap(), 0,
1671 max(2,metrics->gmBlackBoxX) * metrics->gmBlackBoxY * sizeof(*pts) );
1672 if (!pts) return;
1674 count = 0;
1675 ptr += (clipped_rect.top - rect.top) * stride;
1676 for (y = clipped_rect.top; y < clipped_rect.bottom; y++, ptr += stride)
1678 for (x = clipped_rect.left - rect.left; x < clipped_rect.right - rect.left; x++)
1680 while (x < clipped_rect.right - rect.left && !(ptr[x / 8] & masks[x % 8])) x++;
1681 pts[count].x = rect.left + x;
1682 while (x < clipped_rect.right - rect.left && (ptr[x / 8] & masks[x % 8])) x++;
1683 pts[count + 1].x = rect.left + x;
1684 if (pts[count + 1].x > pts[count].x)
1686 pts[count].y = pts[count + 1].y = y;
1687 count += 2;
1691 DPtoLP( hdc, pts, count );
1692 for (i = 0; i < count; i += 2) Polyline( hdc, pts + i, 2 );
1693 HeapFree( GetProcessHeap(), 0, pts );
1696 /***********************************************************************
1697 * nulldrv_ExtTextOut
1699 BOOL nulldrv_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags, const RECT *rect,
1700 LPCWSTR str, UINT count, const INT *dx )
1702 UINT i;
1703 DWORD err;
1704 HGDIOBJ orig;
1705 HPEN pen;
1707 if (flags & ETO_OPAQUE)
1709 RECT rc = *rect;
1710 HBRUSH brush = CreateSolidBrush( GetNearestColor( dev->hdc, GetBkColor(dev->hdc) ));
1712 if (brush)
1714 orig = SelectObject( dev->hdc, brush );
1715 DPtoLP( dev->hdc, (POINT *)&rc, 2 );
1716 PatBlt( dev->hdc, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, PATCOPY );
1717 SelectObject( dev->hdc, orig );
1718 DeleteObject( brush );
1722 if (!count) return TRUE;
1724 pen = CreatePen( PS_SOLID, 1, GetTextColor(dev->hdc) );
1725 orig = SelectObject( dev->hdc, pen );
1727 for (i = 0; i < count; i++)
1729 GLYPHMETRICS metrics;
1730 struct gdi_image_bits image;
1732 err = get_glyph_bitmap( dev->hdc, (UINT)str[i], GGO_BITMAP, &metrics, &image );
1733 if (err) continue;
1735 if (image.ptr) draw_glyph( dev->hdc, x, y, &metrics, &image, (flags & ETO_CLIPPED) ? rect : NULL );
1736 if (image.free) image.free( &image );
1738 if (dx)
1740 if (flags & ETO_PDY)
1742 x += dx[ i * 2 ];
1743 y += dx[ i * 2 + 1];
1745 else x += dx[ i ];
1747 else
1749 x += metrics.gmCellIncX;
1750 y += metrics.gmCellIncY;
1754 SelectObject( dev->hdc, orig );
1755 DeleteObject( pen );
1756 return TRUE;
1760 /***********************************************************************
1761 * ExtTextOutA (GDI32.@)
1763 * See ExtTextOutW.
1765 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1766 const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1768 INT wlen;
1769 UINT codepage;
1770 LPWSTR p;
1771 BOOL ret;
1772 LPINT lpDxW = NULL;
1774 if (flags & ETO_GLYPH_INDEX)
1775 return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
1777 p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
1779 if (lpDx) {
1780 unsigned int i = 0, j = 0;
1782 /* allocate enough for a ETO_PDY */
1783 lpDxW = HeapAlloc( GetProcessHeap(), 0, 2*wlen*sizeof(INT));
1784 while(i < count) {
1785 if(IsDBCSLeadByteEx(codepage, str[i]))
1787 if(flags & ETO_PDY)
1789 lpDxW[j++] = lpDx[i * 2] + lpDx[(i + 1) * 2];
1790 lpDxW[j++] = lpDx[i * 2 + 1] + lpDx[(i + 1) * 2 + 1];
1792 else
1793 lpDxW[j++] = lpDx[i] + lpDx[i + 1];
1794 i = i + 2;
1796 else
1798 if(flags & ETO_PDY)
1800 lpDxW[j++] = lpDx[i * 2];
1801 lpDxW[j++] = lpDx[i * 2 + 1];
1803 else
1804 lpDxW[j++] = lpDx[i];
1805 i = i + 1;
1810 ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1812 HeapFree( GetProcessHeap(), 0, p );
1813 HeapFree( GetProcessHeap(), 0, lpDxW );
1814 return ret;
1818 /***********************************************************************
1819 * ExtTextOutW (GDI32.@)
1821 * Draws text using the currently selected font, background color, and text color.
1824 * PARAMS
1825 * x,y [I] coordinates of string
1826 * flags [I]
1827 * ETO_GRAYED - undocumented on MSDN
1828 * ETO_OPAQUE - use background color for fill the rectangle
1829 * ETO_CLIPPED - clipping text to the rectangle
1830 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1831 * than encoded characters. Implies ETO_IGNORELANGUAGE
1832 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1833 * Affects BiDi ordering
1834 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1835 * ETO_PDY - unimplemented
1836 * ETO_NUMERICSLATIN - unimplemented always assumed -
1837 * do not translate numbers into locale representations
1838 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1839 * lprect [I] dimensions for clipping or/and opaquing
1840 * str [I] text string
1841 * count [I] number of symbols in string
1842 * lpDx [I] optional parameter with distance between drawing characters
1844 * RETURNS
1845 * Success: TRUE
1846 * Failure: FALSE
1848 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1849 const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1851 BOOL ret = FALSE;
1852 LPWSTR reordered_str = (LPWSTR)str;
1853 WORD *glyphs = NULL;
1854 UINT align = GetTextAlign( hdc );
1855 DWORD layout = GetLayout( hdc );
1856 POINT pt;
1857 TEXTMETRICW tm;
1858 LOGFONTW lf;
1859 double cosEsc, sinEsc;
1860 INT char_extra;
1861 SIZE sz;
1862 RECT rc;
1863 BOOL done_extents = FALSE;
1864 POINT *deltas = NULL, width = {0, 0};
1865 DWORD type;
1866 DC * dc = get_dc_ptr( hdc );
1867 PHYSDEV physdev;
1868 INT breakRem;
1869 static int quietfixme = 0;
1871 if (!dc) return FALSE;
1873 breakRem = dc->breakRem;
1875 if (quietfixme == 0 && flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN))
1877 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN unimplemented\n");
1878 quietfixme = 1;
1881 update_dc( dc );
1882 physdev = GET_DC_PHYSDEV( dc, pExtTextOut );
1883 type = GetObjectType(hdc);
1884 if(type == OBJ_METADC || type == OBJ_ENHMETADC)
1886 ret = physdev->funcs->pExtTextOut( physdev, x, y, flags, lprect, str, count, lpDx );
1887 release_dc_ptr( dc );
1888 return ret;
1891 if (!lprect)
1892 flags &= ~ETO_CLIPPED;
1894 if (flags & ETO_RTLREADING) align |= TA_RTLREADING;
1895 if (layout & LAYOUT_RTL)
1897 if ((align & TA_CENTER) != TA_CENTER) align ^= TA_RIGHT;
1898 align ^= TA_RTLREADING;
1901 if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && count > 0 )
1903 INT cGlyphs;
1904 reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1906 BIDI_Reorder( hdc, str, count, GCP_REORDER,
1907 (align & TA_RTLREADING) ? WINE_GCPW_FORCE_RTL : WINE_GCPW_FORCE_LTR,
1908 reordered_str, count, NULL, &glyphs, &cGlyphs);
1910 flags |= ETO_IGNORELANGUAGE;
1911 if (glyphs)
1913 flags |= ETO_GLYPH_INDEX;
1914 if (cGlyphs != count)
1915 count = cGlyphs;
1918 else if(flags & ETO_GLYPH_INDEX)
1919 glyphs = reordered_str;
1921 TRACE("%p, %d, %d, %08x, %s, %s, %d, %p)\n", hdc, x, y, flags,
1922 wine_dbgstr_rect(lprect), debugstr_wn(str, count), count, lpDx);
1923 TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
1925 if(align & TA_UPDATECP)
1927 GetCurrentPositionEx( hdc, &pt );
1928 x = pt.x;
1929 y = pt.y;
1932 GetTextMetricsW(hdc, &tm);
1933 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1935 if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
1936 lf.lfEscapement = 0;
1938 if(lf.lfEscapement != 0)
1940 cosEsc = cos(lf.lfEscapement * M_PI / 1800);
1941 sinEsc = sin(lf.lfEscapement * M_PI / 1800);
1943 else
1945 cosEsc = 1;
1946 sinEsc = 0;
1949 if(flags & (ETO_CLIPPED | ETO_OPAQUE))
1951 if(!lprect)
1953 if(flags & ETO_GLYPH_INDEX)
1954 GetTextExtentPointI(hdc, glyphs, count, &sz);
1955 else
1956 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1958 done_extents = TRUE;
1959 rc.left = x;
1960 rc.top = y;
1961 rc.right = x + sz.cx;
1962 rc.bottom = y + sz.cy;
1964 else
1966 rc = *lprect;
1969 LPtoDP(hdc, (POINT*)&rc, 2);
1971 if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
1972 if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
1975 if (flags & ETO_OPAQUE)
1976 physdev->funcs->pExtTextOut( physdev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL );
1978 if(count == 0)
1980 ret = TRUE;
1981 goto done;
1984 pt.x = x;
1985 pt.y = y;
1986 LPtoDP(hdc, &pt, 1);
1987 x = pt.x;
1988 y = pt.y;
1990 char_extra = GetTextCharacterExtra(hdc);
1991 if(char_extra || dc->breakExtra || breakRem || lpDx || lf.lfEscapement != 0)
1993 UINT i;
1994 SIZE tmpsz;
1995 POINT total = {0, 0}, desired[2];
1997 deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
1998 for(i = 0; i < count; i++)
2000 if(lpDx)
2002 if(flags & ETO_PDY)
2004 deltas[i].x = lpDx[i * 2] + char_extra;
2005 deltas[i].y = -lpDx[i * 2 + 1];
2007 else
2009 deltas[i].x = lpDx[i] + char_extra;
2010 deltas[i].y = 0;
2014 else
2016 if(flags & ETO_GLYPH_INDEX)
2017 GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
2018 else
2019 GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
2021 deltas[i].x = tmpsz.cx;
2022 deltas[i].y = 0;
2025 if (!(flags & ETO_GLYPH_INDEX) && (dc->breakExtra || breakRem) && reordered_str[i] == tm.tmBreakChar)
2027 deltas[i].x = deltas[i].x + dc->breakExtra;
2028 if (breakRem > 0)
2030 breakRem--;
2031 deltas[i].x++;
2034 total.x += deltas[i].x;
2035 total.y += deltas[i].y;
2037 desired[0].x = desired[0].y = 0;
2039 desired[1].x = cosEsc * total.x + sinEsc * total.y;
2040 desired[1].y = -sinEsc * total.x + cosEsc * total.y;
2042 LPtoDP(hdc, desired, 2);
2043 desired[1].x -= desired[0].x;
2044 desired[1].y -= desired[0].y;
2045 if (layout & LAYOUT_RTL) desired[1].x = -desired[1].x;
2047 deltas[i].x = desired[1].x - width.x;
2048 deltas[i].y = desired[1].y - width.y;
2050 width = desired[1];
2052 flags |= ETO_PDY;
2054 else
2056 if(!done_extents)
2058 if(flags & ETO_GLYPH_INDEX)
2059 GetTextExtentPointI(hdc, glyphs, count, &sz);
2060 else
2061 GetTextExtentPointW(hdc, reordered_str, count, &sz);
2062 done_extents = TRUE;
2064 width.x = abs(INTERNAL_XWSTODS(dc, sz.cx));
2065 width.y = 0;
2068 tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
2069 tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
2070 switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
2072 case TA_LEFT:
2073 if (align & TA_UPDATECP)
2075 pt.x = x + width.x;
2076 pt.y = y + width.y;
2077 DPtoLP(hdc, &pt, 1);
2078 MoveToEx(hdc, pt.x, pt.y, NULL);
2080 break;
2082 case TA_CENTER:
2083 x -= width.x / 2;
2084 y -= width.y / 2;
2085 break;
2087 case TA_RIGHT:
2088 x -= width.x;
2089 y -= width.y;
2090 if (align & TA_UPDATECP)
2092 pt.x = x;
2093 pt.y = y;
2094 DPtoLP(hdc, &pt, 1);
2095 MoveToEx(hdc, pt.x, pt.y, NULL);
2097 break;
2100 switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
2102 case TA_TOP:
2103 y += tm.tmAscent * cosEsc;
2104 x += tm.tmAscent * sinEsc;
2105 break;
2107 case TA_BOTTOM:
2108 y -= tm.tmDescent * cosEsc;
2109 x -= tm.tmDescent * sinEsc;
2110 break;
2112 case TA_BASELINE:
2113 break;
2116 if (GetBkMode(hdc) != TRANSPARENT)
2118 if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
2120 if(!(flags & ETO_OPAQUE) || x < rc.left || x + width.x >= rc.right ||
2121 y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
2123 RECT rc;
2124 rc.left = x;
2125 rc.right = x + width.x;
2126 rc.top = y - tm.tmAscent;
2127 rc.bottom = y + tm.tmDescent;
2129 if(flags & ETO_CLIPPED)
2131 rc.left = max(lprect->left, rc.left);
2132 rc.right = min(lprect->right, rc.right);
2133 rc.top = max(lprect->top, rc.top);
2134 rc.bottom = min(lprect->bottom, rc.bottom);
2136 if(rc.left < rc.right && rc.top < rc.bottom)
2137 physdev->funcs->pExtTextOut( physdev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL );
2142 if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
2144 HFONT orig_font = dc->hFont, cur_font;
2145 UINT glyph;
2146 INT span = 0;
2147 POINT *offsets = NULL;
2148 unsigned int i;
2150 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2151 for(i = 0; i < count; i++)
2153 WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
2154 if(cur_font != dc->hFont)
2156 if(!offsets)
2158 unsigned int j;
2159 offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
2160 offsets[0].x = offsets[0].y = 0;
2162 if(!deltas)
2164 SIZE tmpsz;
2165 for(j = 1; j < count; j++)
2167 GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
2168 offsets[j].x = offsets[j - 1].x + abs(INTERNAL_XWSTODS(dc, tmpsz.cx));
2169 offsets[j].y = 0;
2172 else
2174 for(j = 1; j < count; j++)
2176 offsets[j].x = offsets[j - 1].x + deltas[j].x;
2177 offsets[j].y = offsets[j - 1].y + deltas[j].y;
2181 if(span)
2183 physdev->funcs->pExtTextOut( physdev, x + offsets[i - span].x,
2184 y + offsets[i - span].y,
2185 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc, glyphs,
2186 span, deltas ? (INT*)(deltas + (i - span)) : NULL);
2187 span = 0;
2189 SelectObject(hdc, cur_font);
2191 glyphs[span++] = glyph;
2193 if(i == count - 1)
2195 ret = physdev->funcs->pExtTextOut(physdev, x + (offsets ? offsets[count - span].x : 0),
2196 y + (offsets ? offsets[count - span].y : 0),
2197 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc, glyphs,
2198 span, deltas ? (INT*)(deltas + (count - span)) : NULL);
2199 SelectObject(hdc, orig_font);
2200 HeapFree(GetProcessHeap(), 0, offsets);
2204 else
2206 if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
2208 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2209 GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
2210 flags |= ETO_GLYPH_INDEX;
2212 ret = physdev->funcs->pExtTextOut( physdev, x, y, (flags & ~ETO_OPAQUE), &rc,
2213 glyphs ? glyphs : reordered_str, count, (INT*)deltas );
2216 done:
2217 HeapFree(GetProcessHeap(), 0, deltas);
2218 if(glyphs != reordered_str)
2219 HeapFree(GetProcessHeap(), 0, glyphs);
2220 if(reordered_str != str)
2221 HeapFree(GetProcessHeap(), 0, reordered_str);
2223 release_dc_ptr( dc );
2225 if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2227 int underlinePos, strikeoutPos;
2228 int underlineWidth, strikeoutWidth;
2229 UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2230 OUTLINETEXTMETRICW* otm = NULL;
2231 POINT pts[5];
2232 HPEN hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2233 HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2235 hbrush = SelectObject(hdc, hbrush);
2237 if(!size)
2239 underlinePos = 0;
2240 underlineWidth = tm.tmAscent / 20 + 1;
2241 strikeoutPos = tm.tmAscent / 2;
2242 strikeoutWidth = underlineWidth;
2244 else
2246 otm = HeapAlloc(GetProcessHeap(), 0, size);
2247 GetOutlineTextMetricsW(hdc, size, otm);
2248 underlinePos = abs( INTERNAL_YWSTODS( dc, otm->otmsUnderscorePosition ));
2249 if (otm->otmsUnderscorePosition < 0) underlinePos = -underlinePos;
2250 underlineWidth = abs( INTERNAL_YWSTODS( dc, otm->otmsUnderscoreSize ));
2251 if (otm->otmsUnderscoreSize < 0) underlineWidth = -underlineWidth;
2252 strikeoutPos = abs( INTERNAL_YWSTODS( dc, otm->otmsStrikeoutPosition ));
2253 if (otm->otmsStrikeoutPosition < 0) strikeoutPos = -strikeoutPos;
2254 strikeoutWidth = abs( INTERNAL_YWSTODS( dc, otm->otmsStrikeoutSize ));
2255 HeapFree(GetProcessHeap(), 0, otm);
2259 if (lf.lfUnderline)
2261 pts[0].x = x - (underlinePos + underlineWidth / 2) * sinEsc;
2262 pts[0].y = y - (underlinePos + underlineWidth / 2) * cosEsc;
2263 pts[1].x = x + width.x - (underlinePos + underlineWidth / 2) * sinEsc;
2264 pts[1].y = y + width.y - (underlinePos + underlineWidth / 2) * cosEsc;
2265 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2266 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2267 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2268 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2269 pts[4].x = pts[0].x;
2270 pts[4].y = pts[0].y;
2271 DPtoLP(hdc, pts, 5);
2272 Polygon(hdc, pts, 5);
2275 if (lf.lfStrikeOut)
2277 pts[0].x = x - (strikeoutPos + strikeoutWidth / 2) * sinEsc;
2278 pts[0].y = y - (strikeoutPos + strikeoutWidth / 2) * cosEsc;
2279 pts[1].x = x + width.x - (strikeoutPos + strikeoutWidth / 2) * sinEsc;
2280 pts[1].y = y + width.y - (strikeoutPos + strikeoutWidth / 2) * cosEsc;
2281 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2282 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2283 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2284 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2285 pts[4].x = pts[0].x;
2286 pts[4].y = pts[0].y;
2287 DPtoLP(hdc, pts, 5);
2288 Polygon(hdc, pts, 5);
2291 SelectObject(hdc, hpen);
2292 hbrush = SelectObject(hdc, hbrush);
2293 DeleteObject(hbrush);
2296 return ret;
2300 /***********************************************************************
2301 * TextOutA (GDI32.@)
2303 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2305 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2309 /***********************************************************************
2310 * TextOutW (GDI32.@)
2312 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2314 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2318 /***********************************************************************
2319 * PolyTextOutA (GDI32.@)
2321 * See PolyTextOutW.
2323 BOOL WINAPI PolyTextOutA( HDC hdc, const POLYTEXTA *pptxt, INT cStrings )
2325 for (; cStrings>0; cStrings--, pptxt++)
2326 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2327 return FALSE;
2328 return TRUE;
2333 /***********************************************************************
2334 * PolyTextOutW (GDI32.@)
2336 * Draw several Strings
2338 * RETURNS
2339 * TRUE: Success.
2340 * FALSE: Failure.
2342 BOOL WINAPI PolyTextOutW( HDC hdc, const POLYTEXTW *pptxt, INT cStrings )
2344 for (; cStrings>0; cStrings--, pptxt++)
2345 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2346 return FALSE;
2347 return TRUE;
2351 /***********************************************************************
2352 * SetMapperFlags (GDI32.@)
2354 DWORD WINAPI SetMapperFlags( HDC hdc, DWORD flags )
2356 DC *dc = get_dc_ptr( hdc );
2357 DWORD ret = GDI_ERROR;
2359 if (dc)
2361 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetMapperFlags );
2362 flags = physdev->funcs->pSetMapperFlags( physdev, flags );
2363 if (flags != GDI_ERROR)
2365 ret = dc->mapperFlags;
2366 dc->mapperFlags = flags;
2368 release_dc_ptr( dc );
2370 return ret;
2373 /***********************************************************************
2374 * GetAspectRatioFilterEx (GDI32.@)
2376 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2378 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2379 return FALSE;
2383 /***********************************************************************
2384 * GetCharABCWidthsA (GDI32.@)
2386 * See GetCharABCWidthsW.
2388 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2389 LPABC abc )
2391 INT i, wlen;
2392 LPSTR str;
2393 LPWSTR wstr;
2394 BOOL ret = TRUE;
2396 str = FONT_GetCharsByRangeA(hdc, firstChar, lastChar, &i);
2397 if (str == NULL)
2398 return FALSE;
2400 wstr = FONT_mbtowc(hdc, str, i, &wlen, NULL);
2401 if (wstr == NULL)
2403 HeapFree(GetProcessHeap(), 0, str);
2404 return FALSE;
2407 for(i = 0; i < wlen; i++)
2409 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2411 ret = FALSE;
2412 break;
2414 abc++;
2417 HeapFree(GetProcessHeap(), 0, str);
2418 HeapFree(GetProcessHeap(), 0, wstr);
2420 return ret;
2424 /******************************************************************************
2425 * GetCharABCWidthsW [GDI32.@]
2427 * Retrieves widths of characters in range.
2429 * PARAMS
2430 * hdc [I] Handle of device context
2431 * firstChar [I] First character in range to query
2432 * lastChar [I] Last character in range to query
2433 * abc [O] Address of character-width structure
2435 * NOTES
2436 * Only works with TrueType fonts
2438 * RETURNS
2439 * Success: TRUE
2440 * Failure: FALSE
2442 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2443 LPABC abc )
2445 DC *dc = get_dc_ptr(hdc);
2446 PHYSDEV dev;
2447 unsigned int i;
2448 BOOL ret;
2450 if (!dc) return FALSE;
2452 if (!abc)
2454 release_dc_ptr( dc );
2455 return FALSE;
2458 dev = GET_DC_PHYSDEV( dc, pGetCharABCWidths );
2459 ret = dev->funcs->pGetCharABCWidths( dev, firstChar, lastChar, abc );
2460 if (ret)
2462 /* convert device units to logical */
2463 for( i = firstChar; i <= lastChar; i++, abc++ ) {
2464 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2465 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2466 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2470 release_dc_ptr( dc );
2471 return ret;
2475 /******************************************************************************
2476 * GetCharABCWidthsI [GDI32.@]
2478 * Retrieves widths of characters in range.
2480 * PARAMS
2481 * hdc [I] Handle of device context
2482 * firstChar [I] First glyphs in range to query
2483 * count [I] Last glyphs in range to query
2484 * pgi [i] Array of glyphs to query
2485 * abc [O] Address of character-width structure
2487 * NOTES
2488 * Only works with TrueType fonts
2490 * RETURNS
2491 * Success: TRUE
2492 * Failure: FALSE
2494 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2495 LPWORD pgi, LPABC abc)
2497 DC *dc = get_dc_ptr(hdc);
2498 PHYSDEV dev;
2499 unsigned int i;
2500 BOOL ret;
2502 if (!dc) return FALSE;
2504 if (!abc)
2506 release_dc_ptr( dc );
2507 return FALSE;
2510 dev = GET_DC_PHYSDEV( dc, pGetCharABCWidthsI );
2511 ret = dev->funcs->pGetCharABCWidthsI( dev, firstChar, count, pgi, abc );
2512 if (ret)
2514 /* convert device units to logical */
2515 for( i = 0; i < count; i++, abc++ ) {
2516 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2517 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2518 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2522 release_dc_ptr( dc );
2523 return ret;
2527 /***********************************************************************
2528 * GetGlyphOutlineA (GDI32.@)
2530 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2531 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2532 LPVOID lpBuffer, const MAT2 *lpmat2 )
2534 if (!lpmat2) return GDI_ERROR;
2536 if(!(fuFormat & GGO_GLYPH_INDEX)) {
2537 UINT cp;
2538 int len;
2539 char mbchs[2];
2541 cp = GdiGetCodePage(hdc);
2542 if (IsDBCSLeadByteEx(cp, uChar >> 8)) {
2543 len = 2;
2544 mbchs[0] = (uChar & 0xff00) >> 8;
2545 mbchs[1] = (uChar & 0xff);
2546 } else {
2547 len = 1;
2548 mbchs[0] = (uChar & 0xff);
2550 uChar = 0;
2551 MultiByteToWideChar(cp, 0, mbchs, len, (LPWSTR)&uChar, 1);
2554 return GetGlyphOutlineW(hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer,
2555 lpmat2);
2558 /***********************************************************************
2559 * GetGlyphOutlineW (GDI32.@)
2561 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2562 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2563 LPVOID lpBuffer, const MAT2 *lpmat2 )
2565 DC *dc;
2566 DWORD ret;
2567 PHYSDEV dev;
2569 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2570 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2572 if (!lpmat2) return GDI_ERROR;
2574 dc = get_dc_ptr(hdc);
2575 if(!dc) return GDI_ERROR;
2577 dev = GET_DC_PHYSDEV( dc, pGetGlyphOutline );
2578 ret = dev->funcs->pGetGlyphOutline( dev, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2579 release_dc_ptr( dc );
2580 return ret;
2584 /***********************************************************************
2585 * CreateScalableFontResourceA (GDI32.@)
2587 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2588 LPCSTR lpszResourceFile,
2589 LPCSTR lpszFontFile,
2590 LPCSTR lpszCurrentPath )
2592 LPWSTR lpszResourceFileW = NULL;
2593 LPWSTR lpszFontFileW = NULL;
2594 LPWSTR lpszCurrentPathW = NULL;
2595 int len;
2596 BOOL ret;
2598 if (lpszResourceFile)
2600 len = MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, NULL, 0);
2601 lpszResourceFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2602 MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, lpszResourceFileW, len);
2605 if (lpszFontFile)
2607 len = MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, NULL, 0);
2608 lpszFontFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2609 MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, lpszFontFileW, len);
2612 if (lpszCurrentPath)
2614 len = MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, NULL, 0);
2615 lpszCurrentPathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2616 MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, lpszCurrentPathW, len);
2619 ret = CreateScalableFontResourceW(fHidden, lpszResourceFileW,
2620 lpszFontFileW, lpszCurrentPathW);
2622 HeapFree(GetProcessHeap(), 0, lpszResourceFileW);
2623 HeapFree(GetProcessHeap(), 0, lpszFontFileW);
2624 HeapFree(GetProcessHeap(), 0, lpszCurrentPathW);
2626 return ret;
2629 /***********************************************************************
2630 * CreateScalableFontResourceW (GDI32.@)
2632 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2633 LPCWSTR lpszResourceFile,
2634 LPCWSTR lpszFontFile,
2635 LPCWSTR lpszCurrentPath )
2637 HANDLE f;
2638 FIXME("(%d,%s,%s,%s): stub\n",
2639 fHidden, debugstr_w(lpszResourceFile), debugstr_w(lpszFontFile),
2640 debugstr_w(lpszCurrentPath) );
2642 /* fHidden=1 - only visible for the calling app, read-only, not
2643 * enumerated with EnumFonts/EnumFontFamilies
2644 * lpszCurrentPath can be NULL
2647 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2648 if ((f = CreateFileW(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2649 CloseHandle(f);
2650 SetLastError(ERROR_FILE_EXISTS);
2651 return FALSE;
2653 return FALSE; /* create failed */
2656 /*************************************************************************
2657 * GetKerningPairsA (GDI32.@)
2659 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2660 LPKERNINGPAIR kern_pairA )
2662 UINT cp;
2663 CPINFO cpi;
2664 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2665 KERNINGPAIR *kern_pairW;
2667 if (!cPairs && kern_pairA)
2669 SetLastError(ERROR_INVALID_PARAMETER);
2670 return 0;
2673 cp = GdiGetCodePage(hDC);
2675 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2676 * to fail on an invalid character for CP_SYMBOL.
2678 cpi.DefaultChar[0] = 0;
2679 if (cp != CP_SYMBOL && !GetCPInfo(cp, &cpi))
2681 FIXME("Can't find codepage %u info\n", cp);
2682 return 0;
2685 total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2686 if (!total_kern_pairs) return 0;
2688 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2689 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2691 for (i = 0; i < total_kern_pairs; i++)
2693 char first, second;
2695 if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2696 continue;
2698 if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2699 continue;
2701 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2702 continue;
2704 if (kern_pairA)
2706 if (kern_pairs_copied >= cPairs) break;
2708 kern_pairA->wFirst = (BYTE)first;
2709 kern_pairA->wSecond = (BYTE)second;
2710 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2711 kern_pairA++;
2713 kern_pairs_copied++;
2716 HeapFree(GetProcessHeap(), 0, kern_pairW);
2718 return kern_pairs_copied;
2721 /*************************************************************************
2722 * GetKerningPairsW (GDI32.@)
2724 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2725 LPKERNINGPAIR lpKerningPairs )
2727 DC *dc;
2728 DWORD ret;
2729 PHYSDEV dev;
2731 TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2733 if (!cPairs && lpKerningPairs)
2735 SetLastError(ERROR_INVALID_PARAMETER);
2736 return 0;
2739 dc = get_dc_ptr(hDC);
2740 if (!dc) return 0;
2742 dev = GET_DC_PHYSDEV( dc, pGetKerningPairs );
2743 ret = dev->funcs->pGetKerningPairs( dev, cPairs, lpKerningPairs );
2744 release_dc_ptr( dc );
2745 return ret;
2748 /*************************************************************************
2749 * TranslateCharsetInfo [GDI32.@]
2751 * Fills a CHARSETINFO structure for a character set, code page, or
2752 * font. This allows making the correspondence between different labels
2753 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2754 * of the same encoding.
2756 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2757 * only one codepage should be set in *lpSrc.
2759 * RETURNS
2760 * TRUE on success, FALSE on failure.
2763 BOOL WINAPI TranslateCharsetInfo(
2764 LPDWORD lpSrc, /* [in]
2765 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2766 if flags == TCI_SRCCHARSET: a character set value
2767 if flags == TCI_SRCCODEPAGE: a code page value
2769 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2770 DWORD flags /* [in] determines interpretation of lpSrc */)
2772 int index = 0;
2773 switch (flags) {
2774 case TCI_SRCFONTSIG:
2775 while (index < MAXTCIINDEX && !(*lpSrc>>index & 0x0001)) index++;
2776 break;
2777 case TCI_SRCCODEPAGE:
2778 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciACP) index++;
2779 break;
2780 case TCI_SRCCHARSET:
2781 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciCharset) index++;
2782 break;
2783 default:
2784 return FALSE;
2786 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2787 *lpCs = FONT_tci[index];
2788 return TRUE;
2791 /*************************************************************************
2792 * GetFontLanguageInfo (GDI32.@)
2794 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2796 FONTSIGNATURE fontsig;
2797 static const DWORD GCP_DBCS_MASK=0x003F0000,
2798 GCP_DIACRITIC_MASK=0x00000000,
2799 FLI_GLYPHS_MASK=0x00000000,
2800 GCP_GLYPHSHAPE_MASK=0x00000040,
2801 GCP_KASHIDA_MASK=0x00000000,
2802 GCP_LIGATE_MASK=0x00000000,
2803 GCP_USEKERNING_MASK=0x00000000,
2804 GCP_REORDER_MASK=0x00000060;
2806 DWORD result=0;
2808 GetTextCharsetInfo( hdc, &fontsig, 0 );
2809 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2811 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2812 result|=GCP_DBCS;
2814 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2815 result|=GCP_DIACRITIC;
2817 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2818 result|=FLI_GLYPHS;
2820 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2821 result|=GCP_GLYPHSHAPE;
2823 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2824 result|=GCP_KASHIDA;
2826 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2827 result|=GCP_LIGATE;
2829 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2830 result|=GCP_USEKERNING;
2832 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2833 if( GetTextAlign( hdc) & TA_RTLREADING )
2834 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2835 result|=GCP_REORDER;
2837 return result;
2841 /*************************************************************************
2842 * GetFontData [GDI32.@]
2844 * Retrieve data for TrueType font.
2846 * RETURNS
2848 * success: Number of bytes returned
2849 * failure: GDI_ERROR
2851 * NOTES
2853 * Calls SetLastError()
2856 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2857 LPVOID buffer, DWORD length)
2859 DC *dc = get_dc_ptr(hdc);
2860 PHYSDEV dev;
2861 DWORD ret;
2863 if(!dc) return GDI_ERROR;
2865 dev = GET_DC_PHYSDEV( dc, pGetFontData );
2866 ret = dev->funcs->pGetFontData( dev, table, offset, buffer, length );
2867 release_dc_ptr( dc );
2868 return ret;
2871 /*************************************************************************
2872 * GetGlyphIndicesA [GDI32.@]
2874 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2875 LPWORD pgi, DWORD flags)
2877 DWORD ret;
2878 WCHAR *lpstrW;
2879 INT countW;
2881 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2882 hdc, debugstr_an(lpstr, count), count, pgi, flags);
2884 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2885 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2886 HeapFree(GetProcessHeap(), 0, lpstrW);
2888 return ret;
2891 /*************************************************************************
2892 * GetGlyphIndicesW [GDI32.@]
2894 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2895 LPWORD pgi, DWORD flags)
2897 DC *dc = get_dc_ptr(hdc);
2898 PHYSDEV dev;
2899 DWORD ret;
2901 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2902 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2904 if(!dc) return GDI_ERROR;
2906 dev = GET_DC_PHYSDEV( dc, pGetGlyphIndices );
2907 ret = dev->funcs->pGetGlyphIndices( dev, lpstr, count, pgi, flags );
2908 release_dc_ptr( dc );
2909 return ret;
2912 /*************************************************************************
2913 * GetCharacterPlacementA [GDI32.@]
2915 * See GetCharacterPlacementW.
2917 * NOTES:
2918 * the web browser control of ie4 calls this with dwFlags=0
2920 DWORD WINAPI
2921 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2922 INT nMaxExtent, GCP_RESULTSA *lpResults,
2923 DWORD dwFlags)
2925 WCHAR *lpStringW;
2926 INT uCountW;
2927 GCP_RESULTSW resultsW;
2928 DWORD ret;
2929 UINT font_cp;
2931 TRACE("%s, %d, %d, 0x%08x\n",
2932 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2934 /* both structs are equal in size */
2935 memcpy(&resultsW, lpResults, sizeof(resultsW));
2937 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2938 if(lpResults->lpOutString)
2939 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2941 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2943 lpResults->nGlyphs = resultsW.nGlyphs;
2944 lpResults->nMaxFit = resultsW.nMaxFit;
2946 if(lpResults->lpOutString) {
2947 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2948 lpResults->lpOutString, uCount, NULL, NULL );
2951 HeapFree(GetProcessHeap(), 0, lpStringW);
2952 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2954 return ret;
2957 /*************************************************************************
2958 * GetCharacterPlacementW [GDI32.@]
2960 * Retrieve information about a string. This includes the width, reordering,
2961 * Glyphing and so on.
2963 * RETURNS
2965 * The width and height of the string if successful, 0 if failed.
2967 * BUGS
2969 * All flags except GCP_REORDER are not yet implemented.
2970 * Reordering is not 100% compliant to the Windows BiDi method.
2971 * Caret positioning is not yet implemented for BiDi.
2972 * Classes are not yet implemented.
2975 DWORD WINAPI
2976 GetCharacterPlacementW(
2977 HDC hdc, /* [in] Device context for which the rendering is to be done */
2978 LPCWSTR lpString, /* [in] The string for which information is to be returned */
2979 INT uCount, /* [in] Number of WORDS in string. */
2980 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
2981 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2982 DWORD dwFlags /* [in] Flags specifying how to process the string */
2985 DWORD ret=0;
2986 SIZE size;
2987 UINT i, nSet;
2989 TRACE("%s, %d, %d, 0x%08x\n",
2990 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2992 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2993 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2994 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2995 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2996 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2998 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08x ignored\n", dwFlags);
2999 if(lpResults->lpClass) FIXME("classes not implemented\n");
3000 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
3001 FIXME("Caret positions for complex scripts not implemented\n");
3003 nSet = (UINT)uCount;
3004 if(nSet > lpResults->nGlyphs)
3005 nSet = lpResults->nGlyphs;
3007 /* return number of initialized fields */
3008 lpResults->nGlyphs = nSet;
3010 if((dwFlags&GCP_REORDER)==0 )
3012 /* Treat the case where no special handling was requested in a fastpath way */
3013 /* copy will do if the GCP_REORDER flag is not set */
3014 if(lpResults->lpOutString)
3015 memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
3017 if(lpResults->lpOrder)
3019 for(i = 0; i < nSet; i++)
3020 lpResults->lpOrder[i] = i;
3022 } else
3024 BIDI_Reorder(NULL, lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
3025 nSet, lpResults->lpOrder, NULL, NULL );
3028 /* FIXME: Will use the placement chars */
3029 if (lpResults->lpDx)
3031 int c;
3032 for (i = 0; i < nSet; i++)
3034 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
3035 lpResults->lpDx[i]= c;
3039 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
3041 int pos = 0;
3043 lpResults->lpCaretPos[0] = 0;
3044 for (i = 1; i < nSet; i++)
3045 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
3046 lpResults->lpCaretPos[i] = (pos += size.cx);
3049 if(lpResults->lpGlyphs)
3050 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
3052 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
3053 ret = MAKELONG(size.cx, size.cy);
3055 return ret;
3058 /*************************************************************************
3059 * GetCharABCWidthsFloatA [GDI32.@]
3061 * See GetCharABCWidthsFloatW.
3063 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3065 INT i, wlen;
3066 LPSTR str;
3067 LPWSTR wstr;
3068 BOOL ret = TRUE;
3070 str = FONT_GetCharsByRangeA(hdc, first, last, &i);
3071 if (str == NULL)
3072 return FALSE;
3074 wstr = FONT_mbtowc( hdc, str, i, &wlen, NULL );
3076 for (i = 0; i < wlen; i++)
3078 if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
3080 ret = FALSE;
3081 break;
3083 abcf++;
3086 HeapFree( GetProcessHeap(), 0, str );
3087 HeapFree( GetProcessHeap(), 0, wstr );
3089 return ret;
3092 /*************************************************************************
3093 * GetCharABCWidthsFloatW [GDI32.@]
3095 * Retrieves widths of a range of characters.
3097 * PARAMS
3098 * hdc [I] Handle to device context.
3099 * first [I] First character in range to query.
3100 * last [I] Last character in range to query.
3101 * abcf [O] Array of LPABCFLOAT structures.
3103 * RETURNS
3104 * Success: TRUE
3105 * Failure: FALSE
3107 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3109 UINT i;
3110 ABC *abc;
3111 PHYSDEV dev;
3112 BOOL ret = FALSE;
3113 DC *dc = get_dc_ptr( hdc );
3115 TRACE("%p, %d, %d, %p\n", hdc, first, last, abcf);
3117 if (!dc) return FALSE;
3119 if (!abcf) goto done;
3120 if (!(abc = HeapAlloc( GetProcessHeap(), 0, (last - first + 1) * sizeof(*abc) ))) goto done;
3122 dev = GET_DC_PHYSDEV( dc, pGetCharABCWidths );
3123 ret = dev->funcs->pGetCharABCWidths( dev, first, last, abc );
3124 if (ret)
3126 /* convert device units to logical */
3127 for (i = first; i <= last; i++, abcf++)
3129 abcf->abcfA = abc->abcA * dc->xformVport2World.eM11;
3130 abcf->abcfB = abc->abcB * dc->xformVport2World.eM11;
3131 abcf->abcfC = abc->abcC * dc->xformVport2World.eM11;
3134 HeapFree( GetProcessHeap(), 0, abc );
3136 done:
3137 release_dc_ptr( dc );
3138 return ret;
3141 /*************************************************************************
3142 * GetCharWidthFloatA [GDI32.@]
3144 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
3145 UINT iLastChar, PFLOAT pxBuffer)
3147 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3148 return 0;
3151 /*************************************************************************
3152 * GetCharWidthFloatW [GDI32.@]
3154 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
3155 UINT iLastChar, PFLOAT pxBuffer)
3157 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3158 return 0;
3162 /***********************************************************************
3164 * Font Resource API *
3166 ***********************************************************************/
3168 /***********************************************************************
3169 * AddFontResourceA (GDI32.@)
3171 INT WINAPI AddFontResourceA( LPCSTR str )
3173 return AddFontResourceExA( str, 0, NULL);
3176 /***********************************************************************
3177 * AddFontResourceW (GDI32.@)
3179 INT WINAPI AddFontResourceW( LPCWSTR str )
3181 return AddFontResourceExW(str, 0, NULL);
3185 /***********************************************************************
3186 * AddFontResourceExA (GDI32.@)
3188 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3190 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3191 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3192 INT ret;
3194 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3195 ret = AddFontResourceExW(strW, fl, pdv);
3196 HeapFree(GetProcessHeap(), 0, strW);
3197 return ret;
3200 static BOOL CALLBACK load_enumed_resource(HMODULE hModule, LPCWSTR type, LPWSTR name, LONG_PTR lParam)
3202 HRSRC rsrc = FindResourceW(hModule, name, type);
3203 HGLOBAL hMem = LoadResource(hModule, rsrc);
3204 LPVOID *pMem = LockResource(hMem);
3205 int *num_total = (int *)lParam;
3206 DWORD num_in_res;
3208 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type));
3209 if (!AddFontMemResourceEx(pMem, SizeofResource(hModule, rsrc), NULL, &num_in_res))
3211 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule, hMem);
3212 return FALSE;
3215 *num_total += num_in_res;
3216 return TRUE;
3219 /***********************************************************************
3220 * AddFontResourceExW (GDI32.@)
3222 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3224 int ret = WineEngAddFontResourceEx(str, fl, pdv);
3225 if (ret == 0)
3227 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3228 HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
3229 if (hModule != NULL)
3231 int num_resources = 0;
3232 LPWSTR rt_font = (LPWSTR)((ULONG_PTR)8); /* we don't want to include winuser.h */
3234 TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3235 wine_dbgstr_w(str));
3236 if (EnumResourceNamesW(hModule, rt_font, load_enumed_resource, (LONG_PTR)&num_resources))
3237 ret = num_resources;
3238 FreeLibrary(hModule);
3241 return ret;
3244 /***********************************************************************
3245 * RemoveFontResourceA (GDI32.@)
3247 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3249 return RemoveFontResourceExA(str, 0, 0);
3252 /***********************************************************************
3253 * RemoveFontResourceW (GDI32.@)
3255 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3257 return RemoveFontResourceExW(str, 0, 0);
3260 /***********************************************************************
3261 * AddFontMemResourceEx (GDI32.@)
3263 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3265 HANDLE ret;
3266 DWORD num_fonts;
3268 if (!pbFont || !cbFont || !pcFonts)
3270 SetLastError(ERROR_INVALID_PARAMETER);
3271 return NULL;
3274 ret = WineEngAddFontMemResourceEx(pbFont, cbFont, pdv, &num_fonts);
3275 if (ret)
3277 __TRY
3279 *pcFonts = num_fonts;
3281 __EXCEPT_PAGE_FAULT
3283 WARN("page fault while writing to *pcFonts (%p)\n", pcFonts);
3284 RemoveFontMemResourceEx(ret);
3285 ret = 0;
3287 __ENDTRY
3289 return ret;
3292 /***********************************************************************
3293 * RemoveFontMemResourceEx (GDI32.@)
3295 BOOL WINAPI RemoveFontMemResourceEx( HANDLE fh )
3297 FIXME("(%p) stub\n", fh);
3298 return TRUE;
3301 /***********************************************************************
3302 * RemoveFontResourceExA (GDI32.@)
3304 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3306 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3307 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3308 INT ret;
3310 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3311 ret = RemoveFontResourceExW(strW, fl, pdv);
3312 HeapFree(GetProcessHeap(), 0, strW);
3313 return ret;
3316 /***********************************************************************
3317 * RemoveFontResourceExW (GDI32.@)
3319 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3321 return WineEngRemoveFontResourceEx(str, fl, pdv);
3324 /***********************************************************************
3325 * GetTextCharset (GDI32.@)
3327 UINT WINAPI GetTextCharset(HDC hdc)
3329 /* MSDN docs say this is equivalent */
3330 return GetTextCharsetInfo(hdc, NULL, 0);
3333 /***********************************************************************
3334 * GetTextCharsetInfo (GDI32.@)
3336 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3338 UINT ret = DEFAULT_CHARSET;
3339 DC *dc = get_dc_ptr(hdc);
3340 PHYSDEV dev;
3342 if (dc)
3344 dev = GET_DC_PHYSDEV( dc, pGetTextCharsetInfo );
3345 ret = dev->funcs->pGetTextCharsetInfo( dev, fs, flags );
3346 release_dc_ptr( dc );
3349 if (ret == DEFAULT_CHARSET && fs)
3350 memset(fs, 0, sizeof(FONTSIGNATURE));
3351 return ret;
3354 /***********************************************************************
3355 * GdiGetCharDimensions (GDI32.@)
3357 * Gets the average width of the characters in the English alphabet.
3359 * PARAMS
3360 * hdc [I] Handle to the device context to measure on.
3361 * lptm [O] Pointer to memory to store the text metrics into.
3362 * height [O] On exit, the maximum height of characters in the English alphabet.
3364 * RETURNS
3365 * The average width of characters in the English alphabet.
3367 * NOTES
3368 * This function is used by the dialog manager to get the size of a dialog
3369 * unit. It should also be used by other pieces of code that need to know
3370 * the size of a dialog unit in logical units without having access to the
3371 * window handle of the dialog.
3372 * Windows caches the font metrics from this function, but we don't and
3373 * there doesn't appear to be an immediate advantage to do so.
3375 * SEE ALSO
3376 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3378 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3380 SIZE sz;
3381 static const WCHAR alphabet[] = {
3382 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3383 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3384 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3386 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3388 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3390 if (height) *height = sz.cy;
3391 return (sz.cx / 26 + 1) / 2;
3394 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3396 FIXME("(%d): stub\n", fEnableEUDC);
3397 return FALSE;
3400 /***********************************************************************
3401 * GetCharWidthI (GDI32.@)
3403 * Retrieve widths of characters.
3405 * PARAMS
3406 * hdc [I] Handle to a device context.
3407 * first [I] First glyph in range to query.
3408 * count [I] Number of glyph indices to query.
3409 * glyphs [I] Array of glyphs to query.
3410 * buffer [O] Buffer to receive character widths.
3412 * NOTES
3413 * Only works with TrueType fonts.
3415 * RETURNS
3416 * Success: TRUE
3417 * Failure: FALSE
3419 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3421 ABC *abc;
3422 unsigned int i;
3424 TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3426 if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3427 return FALSE;
3429 if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3431 HeapFree(GetProcessHeap(), 0, abc);
3432 return FALSE;
3435 for (i = 0; i < count; i++)
3436 buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3438 HeapFree(GetProcessHeap(), 0, abc);
3439 return TRUE;
3442 /***********************************************************************
3443 * GetFontUnicodeRanges (GDI32.@)
3445 * Retrieve a list of supported Unicode characters in a font.
3447 * PARAMS
3448 * hdc [I] Handle to a device context.
3449 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3451 * RETURNS
3452 * Success: Number of bytes written to the buffer pointed to by lpgs.
3453 * Failure: 0
3456 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3458 DWORD ret;
3459 PHYSDEV dev;
3460 DC *dc = get_dc_ptr(hdc);
3462 TRACE("(%p, %p)\n", hdc, lpgs);
3464 if (!dc) return 0;
3466 dev = GET_DC_PHYSDEV( dc, pGetFontUnicodeRanges );
3467 ret = dev->funcs->pGetFontUnicodeRanges( dev, lpgs );
3468 release_dc_ptr(dc);
3469 return ret;
3473 /*************************************************************
3474 * FontIsLinked (GDI32.@)
3476 BOOL WINAPI FontIsLinked(HDC hdc)
3478 DC *dc = get_dc_ptr(hdc);
3479 PHYSDEV dev;
3480 BOOL ret;
3482 if (!dc) return FALSE;
3483 dev = GET_DC_PHYSDEV( dc, pFontIsLinked );
3484 ret = dev->funcs->pFontIsLinked( dev );
3485 release_dc_ptr(dc);
3486 TRACE("returning %d\n", ret);
3487 return ret;
3490 /*************************************************************
3491 * GdiRealizationInfo (GDI32.@)
3493 * Returns a structure that contains some font information.
3495 BOOL WINAPI GdiRealizationInfo(HDC hdc, realization_info_t *info)
3497 DC *dc = get_dc_ptr(hdc);
3498 PHYSDEV dev;
3499 BOOL ret;
3501 if (!dc) return FALSE;
3502 dev = GET_DC_PHYSDEV( dc, pGdiRealizationInfo );
3503 ret = dev->funcs->pGdiRealizationInfo( dev, info );
3504 release_dc_ptr(dc);
3505 return ret;