4 * Copyright 1993 Alexandre Julliard
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
24 #include "wine/port.h"
37 #include "gdi_private.h"
38 #include "wine/exception.h"
39 #include "wine/unicode.h"
40 #include "wine/debug.h"
42 #ifdef WORDS_BIGENDIAN
43 #define get_be_word(x) (x)
45 #define get_be_word(x) RtlUshortByteSwap(x)
48 WINE_DEFAULT_DEBUG_CHANNEL(font);
50 /* Device -> World size conversion */
52 /* Performs a device to world transformation on the specified width (which
53 * is in integer format).
55 static inline INT INTERNAL_XDSTOWS(DC *dc, INT width)
59 /* Perform operation with floating point */
60 floatWidth = (double)width * dc->xformVport2World.eM11;
61 /* Round to integers */
62 return GDI_ROUND(floatWidth);
65 /* Performs a device to world transformation on the specified size (which
66 * is in integer format).
68 static inline INT INTERNAL_YDSTOWS(DC *dc, INT height)
72 /* Perform operation with floating point */
73 floatHeight = (double)height * dc->xformVport2World.eM22;
74 /* Round to integers */
75 return GDI_ROUND(floatHeight);
78 static inline INT INTERNAL_XWSTODS(DC *dc, INT width)
81 pt[0].x = pt[0].y = 0;
84 LPtoDP(dc->hSelf, pt, 2);
85 return pt[1].x - pt[0].x;
88 static inline INT INTERNAL_YWSTODS(DC *dc, INT height)
91 pt[0].x = pt[0].y = 0;
94 LPtoDP(dc->hSelf, pt, 2);
95 return pt[1].y - pt[0].y;
98 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc );
99 static INT FONT_GetObjectA( HGDIOBJ handle, INT count, LPVOID buffer );
100 static INT FONT_GetObjectW( HGDIOBJ handle, INT count, LPVOID buffer );
101 static BOOL FONT_DeleteObject( HGDIOBJ handle );
103 static const struct gdi_obj_funcs font_funcs =
105 FONT_SelectObject, /* pSelectObject */
106 FONT_GetObjectA, /* pGetObjectA */
107 FONT_GetObjectW, /* pGetObjectW */
108 NULL, /* pUnrealizeObject */
109 FONT_DeleteObject /* pDeleteObject */
119 LPLOGFONTW lpLogFontParam;
120 FONTENUMPROCW lpEnumFunc;
128 * For TranslateCharsetInfo
130 #define MAXTCIINDEX 32
131 static const CHARSETINFO FONT_tci[MAXTCIINDEX] = {
133 { ANSI_CHARSET, 1252, {{0,0,0,0},{FS_LATIN1,0}} },
134 { EASTEUROPE_CHARSET, 1250, {{0,0,0,0},{FS_LATIN2,0}} },
135 { RUSSIAN_CHARSET, 1251, {{0,0,0,0},{FS_CYRILLIC,0}} },
136 { GREEK_CHARSET, 1253, {{0,0,0,0},{FS_GREEK,0}} },
137 { TURKISH_CHARSET, 1254, {{0,0,0,0},{FS_TURKISH,0}} },
138 { HEBREW_CHARSET, 1255, {{0,0,0,0},{FS_HEBREW,0}} },
139 { ARABIC_CHARSET, 1256, {{0,0,0,0},{FS_ARABIC,0}} },
140 { BALTIC_CHARSET, 1257, {{0,0,0,0},{FS_BALTIC,0}} },
141 { VIETNAMESE_CHARSET, 1258, {{0,0,0,0},{FS_VIETNAMESE,0}} },
142 /* reserved by ANSI */
143 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
144 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
145 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
146 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
147 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
148 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
149 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
151 { THAI_CHARSET, 874, {{0,0,0,0},{FS_THAI,0}} },
152 { SHIFTJIS_CHARSET, 932, {{0,0,0,0},{FS_JISJAPAN,0}} },
153 { GB2312_CHARSET, 936, {{0,0,0,0},{FS_CHINESESIMP,0}} },
154 { HANGEUL_CHARSET, 949, {{0,0,0,0},{FS_WANSUNG,0}} },
155 { CHINESEBIG5_CHARSET, 950, {{0,0,0,0},{FS_CHINESETRAD,0}} },
156 { JOHAB_CHARSET, 1361, {{0,0,0,0},{FS_JOHAB,0}} },
157 /* reserved for alternate ANSI and OEM */
158 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
159 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
160 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
161 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
162 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
163 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
164 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
165 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
166 /* reserved for system */
167 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
168 { SYMBOL_CHARSET, CP_SYMBOL, {{0,0,0,0},{FS_SYMBOL,0}} }
171 static void FONT_LogFontAToW( const LOGFONTA *fontA, LPLOGFONTW fontW )
173 memcpy(fontW, fontA, sizeof(LOGFONTA) - LF_FACESIZE);
174 MultiByteToWideChar(CP_ACP, 0, fontA->lfFaceName, -1, fontW->lfFaceName,
176 fontW->lfFaceName[LF_FACESIZE-1] = 0;
179 static void FONT_LogFontWToA( const LOGFONTW *fontW, LPLOGFONTA fontA )
181 memcpy(fontA, fontW, sizeof(LOGFONTA) - LF_FACESIZE);
182 WideCharToMultiByte(CP_ACP, 0, fontW->lfFaceName, -1, fontA->lfFaceName,
183 LF_FACESIZE, NULL, NULL);
184 fontA->lfFaceName[LF_FACESIZE-1] = 0;
187 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEXA fontA )
189 FONT_LogFontWToA( &fontW->elfLogFont, &fontA->elfLogFont );
191 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
192 (LPSTR) fontA->elfFullName, LF_FULLFACESIZE, NULL, NULL );
193 fontA->elfFullName[LF_FULLFACESIZE-1] = '\0';
194 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
195 (LPSTR) fontA->elfStyle, LF_FACESIZE, NULL, NULL );
196 fontA->elfStyle[LF_FACESIZE-1] = '\0';
197 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
198 (LPSTR) fontA->elfScript, LF_FACESIZE, NULL, NULL );
199 fontA->elfScript[LF_FACESIZE-1] = '\0';
202 static void FONT_EnumLogFontExAToW( const ENUMLOGFONTEXA *fontA, LPENUMLOGFONTEXW fontW )
204 FONT_LogFontAToW( &fontA->elfLogFont, &fontW->elfLogFont );
206 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfFullName, -1,
207 fontW->elfFullName, LF_FULLFACESIZE );
208 fontW->elfFullName[LF_FULLFACESIZE-1] = '\0';
209 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfStyle, -1,
210 fontW->elfStyle, LF_FACESIZE );
211 fontW->elfStyle[LF_FACESIZE-1] = '\0';
212 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfScript, -1,
213 fontW->elfScript, LF_FACESIZE );
214 fontW->elfScript[LF_FACESIZE-1] = '\0';
217 /***********************************************************************
218 * TEXTMETRIC conversion functions.
220 static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
222 ptmA->tmHeight = ptmW->tmHeight;
223 ptmA->tmAscent = ptmW->tmAscent;
224 ptmA->tmDescent = ptmW->tmDescent;
225 ptmA->tmInternalLeading = ptmW->tmInternalLeading;
226 ptmA->tmExternalLeading = ptmW->tmExternalLeading;
227 ptmA->tmAveCharWidth = ptmW->tmAveCharWidth;
228 ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth;
229 ptmA->tmWeight = ptmW->tmWeight;
230 ptmA->tmOverhang = ptmW->tmOverhang;
231 ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX;
232 ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
233 ptmA->tmFirstChar = min(ptmW->tmFirstChar, 255);
234 if (ptmW->tmCharSet == SYMBOL_CHARSET)
236 ptmA->tmFirstChar = 0x1e;
237 ptmA->tmLastChar = 0xff; /* win9x behaviour - we need the OS2 table data to calculate correctly */
239 else if (ptmW->tmPitchAndFamily & TMPF_TRUETYPE)
241 ptmA->tmFirstChar = ptmW->tmDefaultChar - 1;
242 ptmA->tmLastChar = min(ptmW->tmLastChar, 0xff);
246 ptmA->tmFirstChar = min(ptmW->tmFirstChar, 0xff);
247 ptmA->tmLastChar = min(ptmW->tmLastChar, 0xff);
249 ptmA->tmDefaultChar = ptmW->tmDefaultChar;
250 ptmA->tmBreakChar = ptmW->tmBreakChar;
251 ptmA->tmItalic = ptmW->tmItalic;
252 ptmA->tmUnderlined = ptmW->tmUnderlined;
253 ptmA->tmStruckOut = ptmW->tmStruckOut;
254 ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
255 ptmA->tmCharSet = ptmW->tmCharSet;
259 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW *ptmW, NEWTEXTMETRICEXA *ptmA )
261 FONT_TextMetricWToA((const TEXTMETRICW *)ptmW, (LPTEXTMETRICA)ptmA);
262 ptmA->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
263 ptmA->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
264 ptmA->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
265 ptmA->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
266 memcpy(&ptmA->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
269 static DWORD get_font_ppem( HDC hdc )
273 DC *dc = get_dc_ptr( hdc );
275 if (!dc) return GDI_ERROR;
277 GetTextMetricsW( hdc, &tm );
278 ppem = abs( INTERNAL_YWSTODS( dc, tm.tmAscent + tm.tmDescent - tm.tmInternalLeading ) );
279 release_dc_ptr( dc );
283 #define GASP_GRIDFIT 0x01
284 #define GASP_DOGRAY 0x02
286 static BOOL get_gasp_flags( HDC hdc, WORD *flags )
288 DWORD size, gasp_tag = 0x70736167;
289 WORD buf[16]; /* Enough for seven ranges before we need to alloc */
290 WORD *alloced = NULL, *ptr = buf;
291 WORD num_recs, version;
292 DWORD ppem = get_font_ppem( hdc );
296 if (ppem == GDI_ERROR) return FALSE;
298 size = GetFontData( hdc, gasp_tag, 0, NULL, 0 );
299 if (size == GDI_ERROR) return FALSE;
300 if (size < 4 * sizeof(WORD)) return FALSE;
301 if (size > sizeof(buf))
303 ptr = alloced = HeapAlloc( GetProcessHeap(), 0, size );
304 if (!ptr) return FALSE;
307 GetFontData( hdc, gasp_tag, 0, ptr, size );
309 version = get_be_word( *ptr++ );
310 num_recs = get_be_word( *ptr++ );
312 if (version > 1 || size < (num_recs * 2 + 2) * sizeof(WORD))
314 FIXME( "Unsupported gasp table: ver %d size %d recs %d\n", version, size, num_recs );
320 *flags = get_be_word( *(ptr + 1) );
321 if (ppem <= get_be_word( *ptr )) break;
324 TRACE( "got flags %04x for ppem %d\n", *flags, ppem );
328 HeapFree( GetProcessHeap(), 0, alloced );
332 enum smoothing { no_smoothing, aa_smoothing, subpixel_smoothing };
334 static DWORD get_desktop_value( const WCHAR *name, DWORD *value )
336 static const WCHAR desktop[] = {'C','o','n','t','r','o','l',' ','P','a','n','e','l','\\','D','e','s','k','t','o','p',0};
339 DWORD count = sizeof(buf), type, err;
341 err = RegOpenKeyW( HKEY_CURRENT_USER, desktop, &key );
344 err = RegQueryValueExW( key, name, NULL, &type, (BYTE*)buf, &count );
345 if (!err) *value = atoiW( buf );
351 static enum smoothing get_default_smoothing( void )
353 static const WCHAR smoothing_type[] = {'F','o','n','t','S','m','o','o','t','h','i','n','g','T','y','p','e',0};
356 /* FIXME: Ignoring FontSmoothing for now since this is
357 set to off by default in wine.inf */
359 err = get_desktop_value( smoothing_type, &type );
360 if (err) return aa_smoothing;
364 case 1: /* FE_FONTSMOOTHINGSTANDARD */
366 case 2: /* FE_FONTSMOOTHINGCLEARTYPE */
367 return subpixel_smoothing;
373 static UINT get_subpixel_orientation( void )
375 static const WCHAR smoothing_orientation[] = {'F','o','n','t','S','m','o','o','t','h','i','n','g',
376 'O','r','i','e','n','t','a','t','i','o','n',0};
379 /* FIXME: handle vertical orientations even though Windows doesn't */
380 err = get_desktop_value( smoothing_orientation, &orient );
381 if (err) return GGO_GRAY4_BITMAP;
385 case 0: /* FE_FONTSMOOTHINGORIENTATIONBGR */
386 return WINE_GGO_HBGR_BITMAP;
387 case 1: /* FE_FONTSMOOTHINGORIENTATIONRGB */
388 return WINE_GGO_HRGB_BITMAP;
390 return GGO_GRAY4_BITMAP;
393 UINT get_font_aa_flags( HDC hdc )
397 static int hinter = -1;
398 static int subpixel_enabled = -1;
399 enum smoothing smoothing;
401 if (GetObjectType( hdc ) == OBJ_MEMDC)
404 GetObjectW( GetCurrentObject( hdc, OBJ_BITMAP ), sizeof(bm), &bm );
405 if (bm.bmBitsPixel <= 8) return GGO_BITMAP;
407 else if (GetDeviceCaps( hdc, BITSPIXEL ) <= 8) return GGO_BITMAP;
409 GetObjectW( GetCurrentObject( hdc, OBJ_FONT ), sizeof(lf), &lf );
410 if (lf.lfQuality == NONANTIALIASED_QUALITY) return GGO_BITMAP;
412 if (hinter == -1 || subpixel_enabled == -1)
414 RASTERIZER_STATUS status;
415 GetRasterizerCaps(&status, sizeof(status));
416 hinter = status.wFlags & WINE_TT_HINTER_ENABLED;
417 subpixel_enabled = status.wFlags & WINE_TT_SUBPIXEL_RENDERING_ENABLED;
420 switch (lf.lfQuality)
422 case ANTIALIASED_QUALITY:
423 smoothing = aa_smoothing;
425 case CLEARTYPE_QUALITY:
426 case CLEARTYPE_NATURAL_QUALITY:
427 smoothing = subpixel_smoothing;
429 case DEFAULT_QUALITY:
433 smoothing = get_default_smoothing();
436 if (smoothing == subpixel_smoothing)
438 if (subpixel_enabled)
440 UINT ret = get_subpixel_orientation();
441 if (ret != GGO_GRAY4_BITMAP) return ret;
443 smoothing = aa_smoothing;
446 if (smoothing == aa_smoothing)
448 if (hinter && get_gasp_flags( hdc, &gasp_flags ) && !(gasp_flags & GASP_DOGRAY))
450 return GGO_GRAY4_BITMAP;
456 /***********************************************************************
457 * GdiGetCodePage (GDI32.@)
459 DWORD WINAPI GdiGetCodePage( HDC hdc )
462 DC *dc = get_dc_ptr( hdc );
466 cp = dc->font_code_page;
467 release_dc_ptr( dc );
472 /***********************************************************************
475 * Returns a Unicode translation of str using the charset of the
476 * currently selected font in hdc. If count is -1 then str is assumed
477 * to be '\0' terminated, otherwise it contains the number of bytes to
478 * convert. If plenW is non-NULL, on return it will point to the
479 * number of WCHARs that have been written. If pCP is non-NULL, on
480 * return it will point to the codepage used in the conversion. The
481 * caller should free the returned LPWSTR from the process heap
484 static LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
490 cp = GdiGetCodePage( hdc );
492 if(count == -1) count = strlen(str);
493 lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
494 strW = HeapAlloc(GetProcessHeap(), 0, lenW*sizeof(WCHAR));
495 MultiByteToWideChar(cp, 0, str, count, strW, lenW);
496 TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW));
497 if(plenW) *plenW = lenW;
502 /***********************************************************************
503 * CreateFontIndirectExA (GDI32.@)
505 HFONT WINAPI CreateFontIndirectExA( const ENUMLOGFONTEXDVA *penumexA )
507 ENUMLOGFONTEXDVW enumexW;
509 if (!penumexA) return 0;
511 FONT_EnumLogFontExAToW( &penumexA->elfEnumLogfontEx, &enumexW.elfEnumLogfontEx );
512 enumexW.elfDesignVector = penumexA->elfDesignVector;
513 return CreateFontIndirectExW( &enumexW );
516 /***********************************************************************
517 * CreateFontIndirectExW (GDI32.@)
519 HFONT WINAPI CreateFontIndirectExW( const ENUMLOGFONTEXDVW *penumex )
525 if (!penumex) return 0;
527 if (penumex->elfEnumLogfontEx.elfFullName[0] ||
528 penumex->elfEnumLogfontEx.elfStyle[0] ||
529 penumex->elfEnumLogfontEx.elfScript[0])
531 FIXME("some fields ignored. fullname=%s, style=%s, script=%s\n",
532 debugstr_w(penumex->elfEnumLogfontEx.elfFullName),
533 debugstr_w(penumex->elfEnumLogfontEx.elfStyle),
534 debugstr_w(penumex->elfEnumLogfontEx.elfScript));
537 plf = &penumex->elfEnumLogfontEx.elfLogFont;
538 if (!(fontPtr = HeapAlloc( GetProcessHeap(), 0, sizeof(*fontPtr) ))) return 0;
540 fontPtr->logfont = *plf;
542 if (plf->lfEscapement != plf->lfOrientation)
544 /* this should really depend on whether GM_ADVANCED is set */
545 fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
546 WARN("orientation angle %f set to "
547 "escapement angle %f for new font %p\n",
548 plf->lfOrientation/10., plf->lfEscapement/10., fontPtr);
551 if (!(hFont = alloc_gdi_handle( fontPtr, OBJ_FONT, &font_funcs )))
553 HeapFree( GetProcessHeap(), 0, fontPtr );
557 TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
558 plf->lfHeight, plf->lfWidth,
559 plf->lfEscapement, plf->lfOrientation,
560 plf->lfPitchAndFamily,
561 plf->lfOutPrecision, plf->lfClipPrecision,
562 plf->lfQuality, plf->lfCharSet,
563 debugstr_w(plf->lfFaceName),
564 plf->lfWeight > 400 ? "Bold" : "",
565 plf->lfItalic ? "Italic" : "",
566 plf->lfUnderline ? "Underline" : "", hFont);
571 /***********************************************************************
572 * CreateFontIndirectA (GDI32.@)
574 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *plfA )
580 FONT_LogFontAToW( plfA, &lfW );
581 return CreateFontIndirectW( &lfW );
584 /***********************************************************************
585 * CreateFontIndirectW (GDI32.@)
587 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
589 ENUMLOGFONTEXDVW exdv;
593 exdv.elfEnumLogfontEx.elfLogFont = *plf;
594 exdv.elfEnumLogfontEx.elfFullName[0] = 0;
595 exdv.elfEnumLogfontEx.elfStyle[0] = 0;
596 exdv.elfEnumLogfontEx.elfScript[0] = 0;
597 return CreateFontIndirectExW( &exdv );
600 /*************************************************************************
601 * CreateFontA (GDI32.@)
603 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
604 INT orient, INT weight, DWORD italic,
605 DWORD underline, DWORD strikeout, DWORD charset,
606 DWORD outpres, DWORD clippres, DWORD quality,
607 DWORD pitch, LPCSTR name )
611 logfont.lfHeight = height;
612 logfont.lfWidth = width;
613 logfont.lfEscapement = esc;
614 logfont.lfOrientation = orient;
615 logfont.lfWeight = weight;
616 logfont.lfItalic = italic;
617 logfont.lfUnderline = underline;
618 logfont.lfStrikeOut = strikeout;
619 logfont.lfCharSet = charset;
620 logfont.lfOutPrecision = outpres;
621 logfont.lfClipPrecision = clippres;
622 logfont.lfQuality = quality;
623 logfont.lfPitchAndFamily = pitch;
626 lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
628 logfont.lfFaceName[0] = '\0';
630 return CreateFontIndirectA( &logfont );
633 /*************************************************************************
634 * CreateFontW (GDI32.@)
636 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
637 INT orient, INT weight, DWORD italic,
638 DWORD underline, DWORD strikeout, DWORD charset,
639 DWORD outpres, DWORD clippres, DWORD quality,
640 DWORD pitch, LPCWSTR name )
644 logfont.lfHeight = height;
645 logfont.lfWidth = width;
646 logfont.lfEscapement = esc;
647 logfont.lfOrientation = orient;
648 logfont.lfWeight = weight;
649 logfont.lfItalic = italic;
650 logfont.lfUnderline = underline;
651 logfont.lfStrikeOut = strikeout;
652 logfont.lfCharSet = charset;
653 logfont.lfOutPrecision = outpres;
654 logfont.lfClipPrecision = clippres;
655 logfont.lfQuality = quality;
656 logfont.lfPitchAndFamily = pitch;
659 lstrcpynW(logfont.lfFaceName, name,
660 sizeof(logfont.lfFaceName) / sizeof(WCHAR));
662 logfont.lfFaceName[0] = '\0';
664 return CreateFontIndirectW( &logfont );
667 static void update_font_code_page( DC *dc )
670 int charset = GetTextCharsetInfo( dc->hSelf, NULL, 0 );
672 /* Hmm, nicely designed api this one! */
673 if (TranslateCharsetInfo( ULongToPtr(charset), &csi, TCI_SRCCHARSET) )
674 dc->font_code_page = csi.ciACP;
678 dc->font_code_page = GetOEMCP();
680 case DEFAULT_CHARSET:
681 dc->font_code_page = GetACP();
691 /* FIXME: These have no place here, but because x11drv
692 enumerates fonts with these (made up) charsets some apps
693 might use them and then the FIXME below would become
694 annoying. Now we could pick the intended codepage for
695 each of these, but since it's broken anyway we'll just
696 use CP_ACP and hope it'll go away...
698 dc->font_code_page = CP_ACP;
702 FIXME("Can't find codepage for charset %d\n", charset);
703 dc->font_code_page = CP_ACP;
708 TRACE("charset %d => cp %d\n", charset, dc->font_code_page);
711 /***********************************************************************
714 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc )
717 DC *dc = get_dc_ptr( hdc );
722 if (!GDI_inc_ref_count( handle ))
724 release_dc_ptr( dc );
728 physdev = GET_DC_PHYSDEV( dc, pSelectFont );
729 if (physdev->funcs->pSelectFont( physdev, handle ))
733 update_font_code_page( dc );
734 GDI_dec_ref_count( ret );
736 else GDI_dec_ref_count( handle );
738 release_dc_ptr( dc );
743 /***********************************************************************
746 static INT FONT_GetObjectA( HGDIOBJ handle, INT count, LPVOID buffer )
748 FONTOBJ *font = GDI_GetObjPtr( handle, OBJ_FONT );
754 FONT_LogFontWToA( &font->logfont, &lfA );
755 if (count > sizeof(lfA)) count = sizeof(lfA);
756 memcpy( buffer, &lfA, count );
758 else count = sizeof(lfA);
759 GDI_ReleaseObj( handle );
763 /***********************************************************************
766 static INT FONT_GetObjectW( HGDIOBJ handle, INT count, LPVOID buffer )
768 FONTOBJ *font = GDI_GetObjPtr( handle, OBJ_FONT );
773 if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
774 memcpy( buffer, &font->logfont, count );
776 else count = sizeof(LOGFONTW);
777 GDI_ReleaseObj( handle );
782 /***********************************************************************
785 static BOOL FONT_DeleteObject( HGDIOBJ handle )
789 WineEngDestroyFontInstance( handle );
791 if (!(obj = free_gdi_handle( handle ))) return FALSE;
792 return HeapFree( GetProcessHeap(), 0, obj );
796 /***********************************************************************
799 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
800 * We have to use other types because of the FONTENUMPROCW definition.
802 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
803 DWORD fType, LPARAM lp )
805 struct font_enum *pfe = (struct font_enum *)lp;
808 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
809 if ((!pfe->lpLogFontParam ||
810 pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
811 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
812 (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
814 /* convert font metrics */
815 ENUMLOGFONTEXA logfont;
816 NEWTEXTMETRICEXA tmA;
820 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
821 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
822 plf = (LOGFONTW *)&logfont.elfLogFont;
823 ptm = (TEXTMETRICW *)&tmA;
825 ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
831 /***********************************************************************
832 * FONT_EnumFontFamiliesEx
834 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf, FONTENUMPROCW efproc,
835 LPARAM lParam, BOOL unicode )
838 DC *dc = get_dc_ptr( hDC );
843 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pEnumFonts );
845 if (plf) TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName), plf->lfCharSet);
846 fe.lpLogFontParam = plf;
847 fe.lpEnumFunc = efproc;
849 fe.unicode = unicode;
852 ret = physdev->funcs->pEnumFonts( physdev, plf, FONT_EnumInstance, (LPARAM)&fe );
853 release_dc_ptr( dc );
855 return ret ? fe.retval : 0;
858 /***********************************************************************
859 * EnumFontFamiliesExW (GDI32.@)
861 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
862 FONTENUMPROCW efproc,
863 LPARAM lParam, DWORD dwFlags )
865 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, TRUE );
868 /***********************************************************************
869 * EnumFontFamiliesExA (GDI32.@)
871 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
872 FONTENUMPROCA efproc,
873 LPARAM lParam, DWORD dwFlags)
879 FONT_LogFontAToW( plf, &lfW );
884 return FONT_EnumFontFamiliesEx( hDC, plfW, (FONTENUMPROCW)efproc, lParam, FALSE );
887 /***********************************************************************
888 * EnumFontFamiliesA (GDI32.@)
890 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
891 FONTENUMPROCA efproc, LPARAM lpData )
897 if (!*lpFamily) return 1;
898 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
899 lf.lfCharSet = DEFAULT_CHARSET;
900 lf.lfPitchAndFamily = 0;
905 return EnumFontFamiliesExA( hDC, plf, efproc, lpData, 0 );
908 /***********************************************************************
909 * EnumFontFamiliesW (GDI32.@)
911 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
912 FONTENUMPROCW efproc, LPARAM lpData )
918 if (!*lpFamily) return 1;
919 lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
920 lf.lfCharSet = DEFAULT_CHARSET;
921 lf.lfPitchAndFamily = 0;
926 return EnumFontFamiliesExW( hDC, plf, efproc, lpData, 0 );
929 /***********************************************************************
930 * EnumFontsA (GDI32.@)
932 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
935 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
938 /***********************************************************************
939 * EnumFontsW (GDI32.@)
941 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
944 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
948 /***********************************************************************
949 * GetTextCharacterExtra (GDI32.@)
951 INT WINAPI GetTextCharacterExtra( HDC hdc )
954 DC *dc = get_dc_ptr( hdc );
955 if (!dc) return 0x80000000;
957 release_dc_ptr( dc );
962 /***********************************************************************
963 * SetTextCharacterExtra (GDI32.@)
965 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
967 INT ret = 0x80000000;
968 DC * dc = get_dc_ptr( hdc );
972 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetTextCharacterExtra );
973 extra = physdev->funcs->pSetTextCharacterExtra( physdev, extra );
974 if (extra != 0x80000000)
977 dc->charExtra = extra;
979 release_dc_ptr( dc );
985 /***********************************************************************
986 * SetTextJustification (GDI32.@)
988 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
992 DC * dc = get_dc_ptr( hdc );
994 if (!dc) return FALSE;
996 physdev = GET_DC_PHYSDEV( dc, pSetTextJustification );
997 ret = physdev->funcs->pSetTextJustification( physdev, extra, breaks );
1000 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
1001 if (!extra) breaks = 0;
1004 dc->breakExtra = extra / breaks;
1005 dc->breakRem = extra - (breaks * dc->breakExtra);
1013 release_dc_ptr( dc );
1018 /***********************************************************************
1019 * GetTextFaceA (GDI32.@)
1021 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
1023 INT res = GetTextFaceW(hdc, 0, NULL);
1024 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
1025 GetTextFaceW( hdc, res, nameW );
1031 res = WideCharToMultiByte(CP_ACP, 0, nameW, -1, name, count, NULL, NULL);
1035 /* GetTextFaceA does NOT include the nul byte in the return count. */
1042 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
1043 HeapFree( GetProcessHeap(), 0, nameW );
1047 /***********************************************************************
1048 * GetTextFaceW (GDI32.@)
1050 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
1055 DC * dc = get_dc_ptr( hdc );
1058 dev = GET_DC_PHYSDEV( dc, pGetTextFace );
1059 ret = dev->funcs->pGetTextFace( dev, count, name );
1060 release_dc_ptr( dc );
1065 /***********************************************************************
1066 * GetTextExtentPoint32A (GDI32.@)
1068 * See GetTextExtentPoint32W.
1070 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
1077 if (count < 0) return FALSE;
1079 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1083 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
1084 HeapFree( GetProcessHeap(), 0, p );
1087 TRACE("(%p %s %d %p): returning %d x %d\n",
1088 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
1093 /***********************************************************************
1094 * GetTextExtentPoint32W [GDI32.@]
1096 * Computes width/height for a string.
1098 * Computes width and height of the specified string.
1104 BOOL WINAPI GetTextExtentPoint32W(
1105 HDC hdc, /* [in] Handle of device context */
1106 LPCWSTR str, /* [in] Address of text string */
1107 INT count, /* [in] Number of characters in string */
1108 LPSIZE size) /* [out] Address of structure for string size */
1110 return GetTextExtentExPointW(hdc, str, count, 0, NULL, NULL, size);
1113 /***********************************************************************
1114 * GetTextExtentExPointI [GDI32.@]
1116 * Computes width and height of the array of glyph indices.
1119 * hdc [I] Handle of device context.
1120 * indices [I] Glyph index array.
1121 * count [I] Number of glyphs in array.
1122 * max_ext [I] Maximum width in glyphs.
1123 * nfit [O] Maximum number of characters.
1124 * dxs [O] Partial string widths.
1125 * size [O] Returned string size.
1131 BOOL WINAPI GetTextExtentExPointI( HDC hdc, const WORD *indices, INT count, INT max_ext,
1132 LPINT nfit, LPINT dxs, LPSIZE size )
1138 if (count < 0) return FALSE;
1140 dc = get_dc_ptr( hdc );
1141 if (!dc) return FALSE;
1143 dev = GET_DC_PHYSDEV( dc, pGetTextExtentExPointI );
1144 ret = dev->funcs->pGetTextExtentExPointI( dev, indices, count, max_ext, nfit, dxs, size );
1145 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1146 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1147 size->cx += count * dc->charExtra;
1148 release_dc_ptr( dc );
1150 TRACE("(%p %p %d %p): returning %d x %d\n",
1151 hdc, indices, count, size, size->cx, size->cy );
1155 /***********************************************************************
1156 * GetTextExtentPointI [GDI32.@]
1158 * Computes width and height of the array of glyph indices.
1161 * hdc [I] Handle of device context.
1162 * indices [I] Glyph index array.
1163 * count [I] Number of glyphs in array.
1164 * size [O] Returned string size.
1170 BOOL WINAPI GetTextExtentPointI( HDC hdc, const WORD *indices, INT count, LPSIZE size )
1172 return GetTextExtentExPointI( hdc, indices, count, 0, NULL, NULL, size );
1176 /***********************************************************************
1177 * GetTextExtentPointA (GDI32.@)
1179 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
1182 TRACE("not bug compatible.\n");
1183 return GetTextExtentPoint32A( hdc, str, count, size );
1186 /***********************************************************************
1187 * GetTextExtentPointW (GDI32.@)
1189 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1192 TRACE("not bug compatible.\n");
1193 return GetTextExtentPoint32W( hdc, str, count, size );
1197 /***********************************************************************
1198 * GetTextExtentExPointA (GDI32.@)
1200 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1201 INT maxExt, LPINT lpnFit,
1202 LPINT alpDx, LPSIZE size )
1209 if (count < 0) return FALSE;
1213 walpDx = HeapAlloc( GetProcessHeap(), 0, count * sizeof(INT) );
1214 if (!walpDx) return FALSE;
1217 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1218 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
1221 INT n = lpnFit ? *lpnFit : wlen;
1223 for(i = 0, j = 0; i < n; i++, j++)
1225 alpDx[j] = walpDx[i];
1226 if (IsDBCSLeadByte(str[j])) alpDx[++j] = walpDx[i];
1229 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1230 HeapFree( GetProcessHeap(), 0, p );
1231 HeapFree( GetProcessHeap(), 0, walpDx );
1236 /***********************************************************************
1237 * GetTextExtentExPointW (GDI32.@)
1239 * Return the size of the string as it would be if it was output properly by
1242 * This should include
1243 * - Intercharacter spacing
1244 * - justification spacing (not yet done)
1245 * - kerning? see below
1247 * Kerning. Since kerning would be carried out by the rendering code it should
1248 * be done by the driver. However they don't support it yet. Also I am not
1249 * yet persuaded that (certainly under Win95) any kerning is actually done.
1251 * str: According to MSDN this should be null-terminated. That is not true; a
1252 * null will not terminate it early.
1253 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1254 * than count. I have seen it be either the size of the full string or
1255 * 1 less than the size of the full string. I have not seen it bear any
1256 * resemblance to the portion that would fit.
1257 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1258 * trailing intercharacter spacing and any trailing justification.
1261 * Currently we do this by measuring each character etc. We should do it by
1262 * passing the request to the driver, perhaps by extending the
1263 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1264 * thinking about kerning issues and rounding issues in the justification.
1267 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1268 INT maxExt, LPINT lpnFit,
1269 LPINT alpDx, LPSIZE size )
1278 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1280 if (count < 0) return FALSE;
1282 dc = get_dc_ptr(hdc);
1283 if (!dc) return FALSE;
1285 GetTextMetricsW(hdc, &tm);
1287 /* If we need to calculate nFit, then we need the partial extents even if
1288 the user hasn't provided us with an array. */
1291 dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]);
1295 SetLastError(ERROR_OUTOFMEMORY);
1302 dev = GET_DC_PHYSDEV( dc, pGetTextExtentExPoint );
1303 ret = dev->funcs->pGetTextExtentExPoint(dev, str, count, 0, NULL, dxs, size);
1305 /* Perform device size to world size transformations. */
1308 INT extra = dc->charExtra,
1309 breakExtra = dc->breakExtra,
1310 breakRem = dc->breakRem,
1315 for (i = 0; i < count; ++i)
1317 dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
1318 dxs[i] += (i+1) * extra;
1319 if (count > 1 && (breakExtra || breakRem) && str[i] == tm.tmBreakChar)
1321 dxs[i] += breakExtra;
1328 if (dxs[i] <= maxExt)
1331 breakRem = dc->breakRem;
1333 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1334 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1336 if (!dxs && count > 1 && (breakExtra || breakRem))
1338 for (i = 0; i < count; i++)
1340 if (str[i] == tm.tmBreakChar)
1342 size->cx += breakExtra;
1357 HeapFree(GetProcessHeap(), 0, dxs);
1359 release_dc_ptr( dc );
1361 TRACE("returning %d %d x %d\n",nFit,size->cx,size->cy);
1365 /***********************************************************************
1366 * GetTextMetricsA (GDI32.@)
1368 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1372 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1373 FONT_TextMetricWToA( &tm32, metrics );
1377 /***********************************************************************
1378 * GetTextMetricsW (GDI32.@)
1380 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1384 DC * dc = get_dc_ptr( hdc );
1385 if (!dc) return FALSE;
1387 physdev = GET_DC_PHYSDEV( dc, pGetTextMetrics );
1388 ret = physdev->funcs->pGetTextMetrics( physdev, metrics );
1392 /* device layer returns values in device units
1393 * therefore we have to convert them to logical */
1395 metrics->tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1396 metrics->tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1398 #define WDPTOLP(x) ((x<0)? \
1399 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1400 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1401 #define HDPTOLP(y) ((y<0)? \
1402 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1403 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1405 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1406 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1407 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1408 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1409 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1410 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1411 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1412 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1416 TRACE("text metrics:\n"
1417 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1418 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1419 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1420 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1421 " PitchAndFamily = %02x\n"
1422 " --------------------\n"
1423 " InternalLeading = %i\n"
1427 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1428 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1429 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1430 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1431 metrics->tmPitchAndFamily,
1432 metrics->tmInternalLeading,
1435 metrics->tmHeight );
1437 release_dc_ptr( dc );
1442 /***********************************************************************
1443 * GetOutlineTextMetricsA (GDI32.@)
1444 * Gets metrics for TrueType fonts.
1447 * If the supplied buffer isn't big enough Windows partially fills it up to
1448 * its given length and returns that length.
1451 * Success: Non-zero or size of required buffer
1454 UINT WINAPI GetOutlineTextMetricsA(
1455 HDC hdc, /* [in] Handle of device context */
1456 UINT cbData, /* [in] Size of metric data array */
1457 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1459 char buf[512], *ptr;
1461 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1462 OUTLINETEXTMETRICA *output = lpOTM;
1465 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1467 if(ret > sizeof(buf))
1468 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1469 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1471 needed = sizeof(OUTLINETEXTMETRICA);
1472 if(lpOTMW->otmpFamilyName)
1473 needed += WideCharToMultiByte(CP_ACP, 0,
1474 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1475 NULL, 0, NULL, NULL);
1476 if(lpOTMW->otmpFaceName)
1477 needed += WideCharToMultiByte(CP_ACP, 0,
1478 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1479 NULL, 0, NULL, NULL);
1480 if(lpOTMW->otmpStyleName)
1481 needed += WideCharToMultiByte(CP_ACP, 0,
1482 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1483 NULL, 0, NULL, NULL);
1484 if(lpOTMW->otmpFullName)
1485 needed += WideCharToMultiByte(CP_ACP, 0,
1486 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1487 NULL, 0, NULL, NULL);
1494 TRACE("needed = %d\n", needed);
1496 /* Since the supplied buffer isn't big enough, we'll alloc one
1497 that is and memcpy the first cbData bytes into the lpOTM at
1499 output = HeapAlloc(GetProcessHeap(), 0, needed);
1501 ret = output->otmSize = min(needed, cbData);
1502 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1503 output->otmFiller = 0;
1504 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1505 output->otmfsSelection = lpOTMW->otmfsSelection;
1506 output->otmfsType = lpOTMW->otmfsType;
1507 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1508 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1509 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1510 output->otmEMSquare = lpOTMW->otmEMSquare;
1511 output->otmAscent = lpOTMW->otmAscent;
1512 output->otmDescent = lpOTMW->otmDescent;
1513 output->otmLineGap = lpOTMW->otmLineGap;
1514 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1515 output->otmsXHeight = lpOTMW->otmsXHeight;
1516 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1517 output->otmMacAscent = lpOTMW->otmMacAscent;
1518 output->otmMacDescent = lpOTMW->otmMacDescent;
1519 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1520 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1521 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1522 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1523 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1524 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1525 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1526 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1527 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1528 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1531 ptr = (char*)(output + 1);
1532 left = needed - sizeof(*output);
1534 if(lpOTMW->otmpFamilyName) {
1535 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1536 len = WideCharToMultiByte(CP_ACP, 0,
1537 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1538 ptr, left, NULL, NULL);
1542 output->otmpFamilyName = 0;
1544 if(lpOTMW->otmpFaceName) {
1545 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1546 len = WideCharToMultiByte(CP_ACP, 0,
1547 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1548 ptr, left, NULL, NULL);
1552 output->otmpFaceName = 0;
1554 if(lpOTMW->otmpStyleName) {
1555 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1556 len = WideCharToMultiByte(CP_ACP, 0,
1557 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1558 ptr, left, NULL, NULL);
1562 output->otmpStyleName = 0;
1564 if(lpOTMW->otmpFullName) {
1565 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1566 len = WideCharToMultiByte(CP_ACP, 0,
1567 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1568 ptr, left, NULL, NULL);
1571 output->otmpFullName = 0;
1575 if(output != lpOTM) {
1576 memcpy(lpOTM, output, cbData);
1577 HeapFree(GetProcessHeap(), 0, output);
1579 /* check if the string offsets really fit into the provided size */
1580 /* FIXME: should we check string length as well? */
1581 /* make sure that we don't read/write beyond the provided buffer */
1582 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(LPSTR))
1584 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1585 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1588 /* make sure that we don't read/write beyond the provided buffer */
1589 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(LPSTR))
1591 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1592 lpOTM->otmpFaceName = 0; /* doesn't fit */
1595 /* make sure that we don't read/write beyond the provided buffer */
1596 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(LPSTR))
1598 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1599 lpOTM->otmpStyleName = 0; /* doesn't fit */
1602 /* make sure that we don't read/write beyond the provided buffer */
1603 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(LPSTR))
1605 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1606 lpOTM->otmpFullName = 0; /* doesn't fit */
1611 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1612 HeapFree(GetProcessHeap(), 0, lpOTMW);
1618 /***********************************************************************
1619 * GetOutlineTextMetricsW [GDI32.@]
1621 UINT WINAPI GetOutlineTextMetricsW(
1622 HDC hdc, /* [in] Handle of device context */
1623 UINT cbData, /* [in] Size of metric data array */
1624 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1626 DC *dc = get_dc_ptr( hdc );
1627 OUTLINETEXTMETRICW *output = lpOTM;
1631 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1634 dev = GET_DC_PHYSDEV( dc, pGetOutlineTextMetrics );
1635 ret = dev->funcs->pGetOutlineTextMetrics( dev, cbData, output );
1637 if (lpOTM && ret > cbData)
1639 output = HeapAlloc(GetProcessHeap(), 0, ret);
1640 ret = dev->funcs->pGetOutlineTextMetrics( dev, ret, output );
1645 output->otmTextMetrics.tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1646 output->otmTextMetrics.tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1648 #define WDPTOLP(x) ((x<0)? \
1649 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1650 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1651 #define HDPTOLP(y) ((y<0)? \
1652 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1653 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1655 output->otmTextMetrics.tmHeight = HDPTOLP(output->otmTextMetrics.tmHeight);
1656 output->otmTextMetrics.tmAscent = HDPTOLP(output->otmTextMetrics.tmAscent);
1657 output->otmTextMetrics.tmDescent = HDPTOLP(output->otmTextMetrics.tmDescent);
1658 output->otmTextMetrics.tmInternalLeading = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1659 output->otmTextMetrics.tmExternalLeading = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1660 output->otmTextMetrics.tmAveCharWidth = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1661 output->otmTextMetrics.tmMaxCharWidth = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1662 output->otmTextMetrics.tmOverhang = WDPTOLP(output->otmTextMetrics.tmOverhang);
1663 output->otmAscent = HDPTOLP(output->otmAscent);
1664 output->otmDescent = HDPTOLP(output->otmDescent);
1665 output->otmLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmLineGap));
1666 output->otmsCapEmHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsCapEmHeight));
1667 output->otmsXHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsXHeight));
1668 output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1669 output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1670 output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1671 output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1672 output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1673 output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1674 output->otmMacLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmMacLineGap));
1675 output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1676 output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1677 output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1678 output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1679 output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1680 output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1681 output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1682 output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1683 output->otmsStrikeoutSize = abs(INTERNAL_YDSTOWS(dc,output->otmsStrikeoutSize));
1684 output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1685 output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1686 output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1691 memcpy(lpOTM, output, cbData);
1692 HeapFree(GetProcessHeap(), 0, output);
1700 static LPSTR FONT_GetCharsByRangeA(HDC hdc, UINT firstChar, UINT lastChar, PINT pByteLen)
1702 INT i, count = lastChar - firstChar + 1;
1710 mbcp = GdiGetCodePage(hdc);
1718 if (lastChar > 0xffff)
1720 if ((firstChar ^ lastChar) > 0xff)
1724 if (lastChar > 0xff)
1730 str = HeapAlloc(GetProcessHeap(), 0, count * 2 + 1);
1734 for(i = 0, c = firstChar; c <= lastChar; i++, c++)
1738 str[i++] = (BYTE)(c >> 8);
1739 if (c <= 0xff && IsDBCSLeadByteEx(mbcp, c))
1740 str[i] = 0x1f; /* FIXME: use default character */
1754 /***********************************************************************
1755 * GetCharWidthW (GDI32.@)
1756 * GetCharWidth32W (GDI32.@)
1758 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1764 DC * dc = get_dc_ptr( hdc );
1766 if (!dc) return FALSE;
1768 dev = GET_DC_PHYSDEV( dc, pGetCharWidth );
1769 ret = dev->funcs->pGetCharWidth( dev, firstChar, lastChar, buffer );
1773 /* convert device units to logical */
1774 for( i = firstChar; i <= lastChar; i++, buffer++ )
1775 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1777 release_dc_ptr( dc );
1782 /***********************************************************************
1783 * GetCharWidthA (GDI32.@)
1784 * GetCharWidth32A (GDI32.@)
1786 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1794 str = FONT_GetCharsByRangeA(hdc, firstChar, lastChar, &i);
1798 wstr = FONT_mbtowc(hdc, str, i, &wlen, NULL);
1800 for(i = 0; i < wlen; i++)
1802 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1810 HeapFree(GetProcessHeap(), 0, str);
1811 HeapFree(GetProcessHeap(), 0, wstr);
1817 /* helper for nulldrv_ExtTextOut */
1818 static DWORD get_glyph_bitmap( HDC hdc, UINT index, UINT aa_flags,
1819 GLYPHMETRICS *metrics, struct gdi_image_bits *image )
1821 UINT ggo_flags = aa_flags | GGO_GLYPH_INDEX;
1822 static const MAT2 identity = { {0,1}, {0,0}, {0,0}, {0,1} };
1823 UINT indices[3] = {0, 0, 0x20};
1830 for (i = 0; i < sizeof(indices) / sizeof(indices[0]); i++)
1833 ret = GetGlyphOutlineW( hdc, index, ggo_flags, metrics, 0, NULL, &identity );
1834 if (ret != GDI_ERROR) break;
1837 if (ret == GDI_ERROR) return ERROR_NOT_FOUND;
1838 if (!image) return ERROR_SUCCESS;
1842 if (!ret) return ERROR_SUCCESS; /* empty glyph */
1844 stride = get_dib_stride( metrics->gmBlackBoxX, 1 );
1845 size = metrics->gmBlackBoxY * stride;
1847 if (!(image->ptr = HeapAlloc( GetProcessHeap(), 0, size ))) return ERROR_OUTOFMEMORY;
1848 image->is_copy = TRUE;
1849 image->free = free_heap_bits;
1851 ret = GetGlyphOutlineW( hdc, index, ggo_flags, metrics, size, image->ptr, &identity );
1852 if (ret == GDI_ERROR)
1854 HeapFree( GetProcessHeap(), 0, image->ptr );
1855 return ERROR_NOT_FOUND;
1857 return ERROR_SUCCESS;
1860 /* helper for nulldrv_ExtTextOut */
1861 static RECT get_total_extents( HDC hdc, INT x, INT y, UINT flags, UINT aa_flags,
1862 LPCWSTR str, UINT count, const INT *dx )
1867 reset_bounds( &bounds );
1868 for (i = 0; i < count; i++)
1870 GLYPHMETRICS metrics;
1872 if (get_glyph_bitmap( hdc, (UINT)str[i], aa_flags, &metrics, NULL )) continue;
1874 rect.left = x + metrics.gmptGlyphOrigin.x;
1875 rect.top = y - metrics.gmptGlyphOrigin.y;
1876 rect.right = rect.left + metrics.gmBlackBoxX;
1877 rect.bottom = rect.top + metrics.gmBlackBoxY;
1878 add_bounds_rect( &bounds, &rect );
1882 if (flags & ETO_PDY)
1885 y += dx[ i * 2 + 1];
1891 x += metrics.gmCellIncX;
1892 y += metrics.gmCellIncY;
1898 /* helper for nulldrv_ExtTextOut */
1899 static void draw_glyph( HDC hdc, INT origin_x, INT origin_y, const GLYPHMETRICS *metrics,
1900 const struct gdi_image_bits *image, const RECT *clip )
1902 static const BYTE masks[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
1903 UINT x, y, i, count, max_count;
1904 BYTE *ptr = image->ptr;
1905 int stride = get_dib_stride( metrics->gmBlackBoxX, 1 );
1907 RECT rect, clipped_rect;
1909 rect.left = origin_x + metrics->gmptGlyphOrigin.x;
1910 rect.top = origin_y - metrics->gmptGlyphOrigin.y;
1911 rect.right = rect.left + metrics->gmBlackBoxX;
1912 rect.bottom = rect.top + metrics->gmBlackBoxY;
1913 if (!clip) clipped_rect = rect;
1914 else if (!intersect_rect( &clipped_rect, &rect, clip )) return;
1916 max_count = (metrics->gmBlackBoxX + 1) * metrics->gmBlackBoxY;
1917 pts = HeapAlloc( GetProcessHeap(), 0, max_count * sizeof(*pts) );
1921 ptr += (clipped_rect.top - rect.top) * stride;
1922 for (y = clipped_rect.top; y < clipped_rect.bottom; y++, ptr += stride)
1924 for (x = clipped_rect.left - rect.left; x < clipped_rect.right - rect.left; x++)
1926 while (x < clipped_rect.right - rect.left && !(ptr[x / 8] & masks[x % 8])) x++;
1927 pts[count].x = rect.left + x;
1928 while (x < clipped_rect.right - rect.left && (ptr[x / 8] & masks[x % 8])) x++;
1929 pts[count + 1].x = rect.left + x;
1930 if (pts[count + 1].x > pts[count].x)
1932 pts[count].y = pts[count + 1].y = y;
1937 assert( count <= max_count );
1938 DPtoLP( hdc, pts, count );
1939 for (i = 0; i < count; i += 2) Polyline( hdc, pts + i, 2 );
1940 HeapFree( GetProcessHeap(), 0, pts );
1943 /***********************************************************************
1944 * nulldrv_ExtTextOut
1946 BOOL nulldrv_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags, const RECT *rect,
1947 LPCWSTR str, UINT count, const INT *dx )
1949 DC *dc = get_nulldrv_dc( dev );
1955 if (flags & ETO_OPAQUE)
1958 HBRUSH brush = CreateSolidBrush( GetNearestColor( dev->hdc, GetBkColor(dev->hdc) ));
1962 orig = SelectObject( dev->hdc, brush );
1963 DPtoLP( dev->hdc, (POINT *)&rc, 2 );
1964 PatBlt( dev->hdc, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, PATCOPY );
1965 SelectObject( dev->hdc, orig );
1966 DeleteObject( brush );
1970 if (!count) return TRUE;
1972 aa_flags = get_font_aa_flags( dev->hdc );
1974 if (aa_flags != GGO_BITMAP)
1976 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1977 BITMAPINFO *info = (BITMAPINFO *)buffer;
1978 struct gdi_image_bits bits;
1979 struct bitblt_coords src, dst;
1982 /* FIXME Subpixel modes */
1983 aa_flags = GGO_GRAY4_BITMAP;
1985 dst_dev = GET_DC_PHYSDEV( dc, pPutImage );
1986 src.visrect = get_total_extents( dev->hdc, x, y, flags, aa_flags, str, count, dx );
1987 if (flags & ETO_CLIPPED) intersect_rect( &src.visrect, &src.visrect, rect );
1988 if (!clip_visrect( dc, &src.visrect, &src.visrect )) return TRUE;
1990 /* FIXME: check for ETO_OPAQUE and avoid GetImage */
1991 src.x = src.visrect.left;
1992 src.y = src.visrect.top;
1993 src.width = src.visrect.right - src.visrect.left;
1994 src.height = src.visrect.bottom - src.visrect.top;
1996 if ((flags & ETO_OPAQUE) && (src.visrect.left >= rect->left) && (src.visrect.top >= rect->top) &&
1997 (src.visrect.right <= rect->right) && (src.visrect.bottom <= rect->bottom))
1999 /* we can avoid the GetImage, just query the needed format */
2000 memset( &info->bmiHeader, 0, sizeof(info->bmiHeader) );
2001 info->bmiHeader.biSize = sizeof(info->bmiHeader);
2002 info->bmiHeader.biWidth = src.width;
2003 info->bmiHeader.biHeight = -src.height;
2004 err = dst_dev->funcs->pPutImage( dst_dev, 0, info, NULL, NULL, NULL, 0 );
2005 if (!err || err == ERROR_BAD_FORMAT)
2007 /* make the source rectangle relative to the source bits */
2009 src.visrect.left = src.visrect.top = 0;
2010 src.visrect.right = src.width;
2011 src.visrect.bottom = src.height;
2013 bits.ptr = HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( info ));
2014 if (!bits.ptr) return ERROR_OUTOFMEMORY;
2015 bits.is_copy = TRUE;
2016 bits.free = free_heap_bits;
2017 err = ERROR_SUCCESS;
2022 PHYSDEV src_dev = GET_DC_PHYSDEV( dc, pGetImage );
2023 err = src_dev->funcs->pGetImage( src_dev, info, &bits, &src );
2024 if (!err && !bits.is_copy)
2026 void *ptr = HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( info ));
2029 if (bits.free) bits.free( &bits );
2030 return ERROR_OUTOFMEMORY;
2032 memcpy( ptr, bits.ptr, get_dib_image_size( info ));
2033 if (bits.free) bits.free( &bits );
2035 bits.is_copy = TRUE;
2036 bits.free = free_heap_bits;
2041 /* make x,y relative to the image bits */
2042 x += src.visrect.left - dst.visrect.left;
2043 y += src.visrect.top - dst.visrect.top;
2044 render_aa_text_bitmapinfo( dev->hdc, info, &bits, &src, x, y, flags,
2045 aa_flags, str, count, dx );
2046 err = dst_dev->funcs->pPutImage( dst_dev, 0, info, &bits, &src, &dst, SRCCOPY );
2047 if (bits.free) bits.free( &bits );
2052 pen = CreatePen( PS_SOLID, 1, GetTextColor(dev->hdc) );
2053 orig = SelectObject( dev->hdc, pen );
2055 for (i = 0; i < count; i++)
2057 GLYPHMETRICS metrics;
2058 struct gdi_image_bits image;
2060 err = get_glyph_bitmap( dev->hdc, (UINT)str[i], GGO_BITMAP, &metrics, &image );
2063 if (image.ptr) draw_glyph( dev->hdc, x, y, &metrics, &image, (flags & ETO_CLIPPED) ? rect : NULL );
2064 if (image.free) image.free( &image );
2068 if (flags & ETO_PDY)
2071 y += dx[ i * 2 + 1];
2077 x += metrics.gmCellIncX;
2078 y += metrics.gmCellIncY;
2082 SelectObject( dev->hdc, orig );
2083 DeleteObject( pen );
2088 /***********************************************************************
2089 * ExtTextOutA (GDI32.@)
2093 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
2094 const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
2102 if (flags & ETO_GLYPH_INDEX)
2103 return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
2105 p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
2108 unsigned int i = 0, j = 0;
2110 /* allocate enough for a ETO_PDY */
2111 lpDxW = HeapAlloc( GetProcessHeap(), 0, 2*wlen*sizeof(INT));
2113 if(IsDBCSLeadByteEx(codepage, str[i]))
2117 lpDxW[j++] = lpDx[i * 2] + lpDx[(i + 1) * 2];
2118 lpDxW[j++] = lpDx[i * 2 + 1] + lpDx[(i + 1) * 2 + 1];
2121 lpDxW[j++] = lpDx[i] + lpDx[i + 1];
2128 lpDxW[j++] = lpDx[i * 2];
2129 lpDxW[j++] = lpDx[i * 2 + 1];
2132 lpDxW[j++] = lpDx[i];
2138 ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
2140 HeapFree( GetProcessHeap(), 0, p );
2141 HeapFree( GetProcessHeap(), 0, lpDxW );
2146 /***********************************************************************
2147 * ExtTextOutW (GDI32.@)
2149 * Draws text using the currently selected font, background color, and text color.
2153 * x,y [I] coordinates of string
2155 * ETO_GRAYED - undocumented on MSDN
2156 * ETO_OPAQUE - use background color for fill the rectangle
2157 * ETO_CLIPPED - clipping text to the rectangle
2158 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
2159 * than encoded characters. Implies ETO_IGNORELANGUAGE
2160 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
2161 * Affects BiDi ordering
2162 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
2163 * ETO_PDY - unimplemented
2164 * ETO_NUMERICSLATIN - unimplemented always assumed -
2165 * do not translate numbers into locale representations
2166 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
2167 * lprect [I] dimensions for clipping or/and opaquing
2168 * str [I] text string
2169 * count [I] number of symbols in string
2170 * lpDx [I] optional parameter with distance between drawing characters
2176 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
2177 const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
2180 LPWSTR reordered_str = (LPWSTR)str;
2181 WORD *glyphs = NULL;
2182 UINT align = GetTextAlign( hdc );
2183 DWORD layout = GetLayout( hdc );
2187 double cosEsc, sinEsc;
2191 BOOL done_extents = FALSE;
2192 POINT *deltas = NULL, width = {0, 0};
2194 DC * dc = get_dc_ptr( hdc );
2197 static int quietfixme = 0;
2199 if (!dc) return FALSE;
2201 breakRem = dc->breakRem;
2203 if (quietfixme == 0 && flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN))
2205 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN unimplemented\n");
2210 physdev = GET_DC_PHYSDEV( dc, pExtTextOut );
2211 type = GetObjectType(hdc);
2212 if(type == OBJ_METADC || type == OBJ_ENHMETADC)
2214 ret = physdev->funcs->pExtTextOut( physdev, x, y, flags, lprect, str, count, lpDx );
2215 release_dc_ptr( dc );
2220 flags &= ~ETO_CLIPPED;
2222 if (flags & ETO_RTLREADING) align |= TA_RTLREADING;
2223 if (layout & LAYOUT_RTL)
2225 if ((align & TA_CENTER) != TA_CENTER) align ^= TA_RIGHT;
2226 align ^= TA_RTLREADING;
2229 if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && count > 0 )
2232 reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
2234 BIDI_Reorder( hdc, str, count, GCP_REORDER,
2235 (align & TA_RTLREADING) ? WINE_GCPW_FORCE_RTL : WINE_GCPW_FORCE_LTR,
2236 reordered_str, count, NULL, &glyphs, &cGlyphs);
2238 flags |= ETO_IGNORELANGUAGE;
2241 flags |= ETO_GLYPH_INDEX;
2242 if (cGlyphs != count)
2246 else if(flags & ETO_GLYPH_INDEX)
2247 glyphs = reordered_str;
2249 TRACE("%p, %d, %d, %08x, %s, %s, %d, %p)\n", hdc, x, y, flags,
2250 wine_dbgstr_rect(lprect), debugstr_wn(str, count), count, lpDx);
2251 TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
2253 if(align & TA_UPDATECP)
2255 GetCurrentPositionEx( hdc, &pt );
2260 GetTextMetricsW(hdc, &tm);
2261 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
2263 if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
2264 lf.lfEscapement = 0;
2266 if ((dc->GraphicsMode == GM_COMPATIBLE) &&
2267 (dc->vport2WorldValid && dc->xformWorld2Vport.eM11 * dc->xformWorld2Vport.eM22 < 0))
2269 lf.lfEscapement = -lf.lfEscapement;
2272 if(lf.lfEscapement != 0)
2274 cosEsc = cos(lf.lfEscapement * M_PI / 1800);
2275 sinEsc = sin(lf.lfEscapement * M_PI / 1800);
2283 if(flags & (ETO_CLIPPED | ETO_OPAQUE))
2287 if(flags & ETO_GLYPH_INDEX)
2288 GetTextExtentPointI(hdc, glyphs, count, &sz);
2290 GetTextExtentPointW(hdc, reordered_str, count, &sz);
2292 done_extents = TRUE;
2295 rc.right = x + sz.cx;
2296 rc.bottom = y + sz.cy;
2303 LPtoDP(hdc, (POINT*)&rc, 2);
2305 if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
2306 if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
2309 if (lprect && (flags & ETO_OPAQUE))
2310 physdev->funcs->pExtTextOut( physdev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL );
2320 LPtoDP(hdc, &pt, 1);
2324 char_extra = GetTextCharacterExtra(hdc);
2325 if(char_extra || dc->breakExtra || breakRem || lpDx || lf.lfEscapement != 0)
2329 POINT total = {0, 0}, desired[2];
2331 deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
2332 for(i = 0; i < count; i++)
2338 deltas[i].x = lpDx[i * 2] + char_extra;
2339 deltas[i].y = -lpDx[i * 2 + 1];
2343 deltas[i].x = lpDx[i] + char_extra;
2350 if(flags & ETO_GLYPH_INDEX)
2351 GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
2353 GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
2355 deltas[i].x = tmpsz.cx;
2359 if (!(flags & ETO_GLYPH_INDEX) && (dc->breakExtra || breakRem) && reordered_str[i] == tm.tmBreakChar)
2361 deltas[i].x = deltas[i].x + dc->breakExtra;
2368 total.x += deltas[i].x;
2369 total.y += deltas[i].y;
2371 desired[0].x = desired[0].y = 0;
2373 desired[1].x = cosEsc * total.x + sinEsc * total.y;
2374 desired[1].y = -sinEsc * total.x + cosEsc * total.y;
2376 LPtoDP(hdc, desired, 2);
2377 desired[1].x -= desired[0].x;
2378 desired[1].y -= desired[0].y;
2380 if (dc->GraphicsMode == GM_COMPATIBLE)
2382 if (dc->vport2WorldValid && dc->xformWorld2Vport.eM11 < 0)
2383 desired[1].x = -desired[1].x;
2384 if (dc->vport2WorldValid && dc->xformWorld2Vport.eM22 < 0)
2385 desired[1].y = -desired[1].y;
2389 if (layout & LAYOUT_RTL) desired[1].x = -desired[1].x;
2392 deltas[i].x = desired[1].x - width.x;
2393 deltas[i].y = desired[1].y - width.y;
2403 if(flags & ETO_GLYPH_INDEX)
2404 GetTextExtentPointI(hdc, glyphs, count, &sz);
2406 GetTextExtentPointW(hdc, reordered_str, count, &sz);
2407 done_extents = TRUE;
2409 width.x = abs(INTERNAL_XWSTODS(dc, sz.cx));
2413 tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
2414 tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
2415 switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
2418 if (align & TA_UPDATECP)
2422 DPtoLP(hdc, &pt, 1);
2423 MoveToEx(hdc, pt.x, pt.y, NULL);
2435 if (align & TA_UPDATECP)
2439 DPtoLP(hdc, &pt, 1);
2440 MoveToEx(hdc, pt.x, pt.y, NULL);
2445 switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
2448 y += tm.tmAscent * cosEsc;
2449 x += tm.tmAscent * sinEsc;
2453 y -= tm.tmDescent * cosEsc;
2454 x -= tm.tmDescent * sinEsc;
2461 if (GetBkMode(hdc) != TRANSPARENT)
2463 if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
2465 if(!(flags & ETO_OPAQUE) || !lprect ||
2466 x < rc.left || x + width.x >= rc.right ||
2467 y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
2471 text_box.right = x + width.x;
2472 text_box.top = y - tm.tmAscent;
2473 text_box.bottom = y + tm.tmDescent;
2475 if (flags & ETO_CLIPPED) intersect_rect( &text_box, &text_box, &rc );
2476 if (!is_rect_empty( &text_box ))
2477 physdev->funcs->pExtTextOut( physdev, 0, 0, ETO_OPAQUE, &text_box, NULL, 0, NULL );
2482 if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
2484 HFONT orig_font = dc->hFont, cur_font;
2487 POINT *offsets = NULL;
2490 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2491 for(i = 0; i < count; i++)
2493 WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
2494 if(cur_font != dc->hFont)
2499 offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
2500 offsets[0].x = offsets[0].y = 0;
2505 for(j = 1; j < count; j++)
2507 GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
2508 offsets[j].x = offsets[j - 1].x + abs(INTERNAL_XWSTODS(dc, tmpsz.cx));
2514 for(j = 1; j < count; j++)
2516 offsets[j].x = offsets[j - 1].x + deltas[j].x;
2517 offsets[j].y = offsets[j - 1].y + deltas[j].y;
2523 physdev->funcs->pExtTextOut( physdev, x + offsets[i - span].x,
2524 y + offsets[i - span].y,
2525 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc, glyphs,
2526 span, deltas ? (INT*)(deltas + (i - span)) : NULL);
2529 SelectObject(hdc, cur_font);
2531 glyphs[span++] = glyph;
2535 ret = physdev->funcs->pExtTextOut(physdev, x + (offsets ? offsets[count - span].x : 0),
2536 y + (offsets ? offsets[count - span].y : 0),
2537 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc, glyphs,
2538 span, deltas ? (INT*)(deltas + (count - span)) : NULL);
2539 SelectObject(hdc, orig_font);
2540 HeapFree(GetProcessHeap(), 0, offsets);
2546 if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
2548 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2549 GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
2550 flags |= ETO_GLYPH_INDEX;
2552 ret = physdev->funcs->pExtTextOut( physdev, x, y, (flags & ~ETO_OPAQUE), &rc,
2553 glyphs ? glyphs : reordered_str, count, (INT*)deltas );
2557 HeapFree(GetProcessHeap(), 0, deltas);
2558 if(glyphs != reordered_str)
2559 HeapFree(GetProcessHeap(), 0, glyphs);
2560 if(reordered_str != str)
2561 HeapFree(GetProcessHeap(), 0, reordered_str);
2563 release_dc_ptr( dc );
2565 if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2567 int underlinePos, strikeoutPos;
2568 int underlineWidth, strikeoutWidth;
2569 UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2570 OUTLINETEXTMETRICW* otm = NULL;
2572 HPEN hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2573 HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2575 hbrush = SelectObject(hdc, hbrush);
2580 underlineWidth = tm.tmAscent / 20 + 1;
2581 strikeoutPos = tm.tmAscent / 2;
2582 strikeoutWidth = underlineWidth;
2586 otm = HeapAlloc(GetProcessHeap(), 0, size);
2587 GetOutlineTextMetricsW(hdc, size, otm);
2588 underlinePos = abs( INTERNAL_YWSTODS( dc, otm->otmsUnderscorePosition ));
2589 if (otm->otmsUnderscorePosition < 0) underlinePos = -underlinePos;
2590 underlineWidth = abs( INTERNAL_YWSTODS( dc, otm->otmsUnderscoreSize ));
2591 if (otm->otmsUnderscoreSize < 0) underlineWidth = -underlineWidth;
2592 strikeoutPos = abs( INTERNAL_YWSTODS( dc, otm->otmsStrikeoutPosition ));
2593 if (otm->otmsStrikeoutPosition < 0) strikeoutPos = -strikeoutPos;
2594 strikeoutWidth = abs( INTERNAL_YWSTODS( dc, otm->otmsStrikeoutSize ));
2595 HeapFree(GetProcessHeap(), 0, otm);
2601 pts[0].x = x - (underlinePos + underlineWidth / 2) * sinEsc;
2602 pts[0].y = y - (underlinePos + underlineWidth / 2) * cosEsc;
2603 pts[1].x = x + width.x - (underlinePos + underlineWidth / 2) * sinEsc;
2604 pts[1].y = y + width.y - (underlinePos + underlineWidth / 2) * cosEsc;
2605 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2606 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2607 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2608 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2609 pts[4].x = pts[0].x;
2610 pts[4].y = pts[0].y;
2611 DPtoLP(hdc, pts, 5);
2612 Polygon(hdc, pts, 5);
2617 pts[0].x = x - (strikeoutPos + strikeoutWidth / 2) * sinEsc;
2618 pts[0].y = y - (strikeoutPos + strikeoutWidth / 2) * cosEsc;
2619 pts[1].x = x + width.x - (strikeoutPos + strikeoutWidth / 2) * sinEsc;
2620 pts[1].y = y + width.y - (strikeoutPos + strikeoutWidth / 2) * cosEsc;
2621 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2622 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2623 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2624 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2625 pts[4].x = pts[0].x;
2626 pts[4].y = pts[0].y;
2627 DPtoLP(hdc, pts, 5);
2628 Polygon(hdc, pts, 5);
2631 SelectObject(hdc, hpen);
2632 hbrush = SelectObject(hdc, hbrush);
2633 DeleteObject(hbrush);
2640 /***********************************************************************
2641 * TextOutA (GDI32.@)
2643 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2645 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2649 /***********************************************************************
2650 * TextOutW (GDI32.@)
2652 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2654 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2658 /***********************************************************************
2659 * PolyTextOutA (GDI32.@)
2663 BOOL WINAPI PolyTextOutA( HDC hdc, const POLYTEXTA *pptxt, INT cStrings )
2665 for (; cStrings>0; cStrings--, pptxt++)
2666 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2673 /***********************************************************************
2674 * PolyTextOutW (GDI32.@)
2676 * Draw several Strings
2682 BOOL WINAPI PolyTextOutW( HDC hdc, const POLYTEXTW *pptxt, INT cStrings )
2684 for (; cStrings>0; cStrings--, pptxt++)
2685 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2691 /***********************************************************************
2692 * SetMapperFlags (GDI32.@)
2694 DWORD WINAPI SetMapperFlags( HDC hdc, DWORD flags )
2696 DC *dc = get_dc_ptr( hdc );
2697 DWORD ret = GDI_ERROR;
2701 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetMapperFlags );
2702 flags = physdev->funcs->pSetMapperFlags( physdev, flags );
2703 if (flags != GDI_ERROR)
2705 ret = dc->mapperFlags;
2706 dc->mapperFlags = flags;
2708 release_dc_ptr( dc );
2713 /***********************************************************************
2714 * GetAspectRatioFilterEx (GDI32.@)
2716 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2718 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2723 /***********************************************************************
2724 * GetCharABCWidthsA (GDI32.@)
2726 * See GetCharABCWidthsW.
2728 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2736 str = FONT_GetCharsByRangeA(hdc, firstChar, lastChar, &i);
2740 wstr = FONT_mbtowc(hdc, str, i, &wlen, NULL);
2743 HeapFree(GetProcessHeap(), 0, str);
2747 for(i = 0; i < wlen; i++)
2749 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2757 HeapFree(GetProcessHeap(), 0, str);
2758 HeapFree(GetProcessHeap(), 0, wstr);
2764 /******************************************************************************
2765 * GetCharABCWidthsW [GDI32.@]
2767 * Retrieves widths of characters in range.
2770 * hdc [I] Handle of device context
2771 * firstChar [I] First character in range to query
2772 * lastChar [I] Last character in range to query
2773 * abc [O] Address of character-width structure
2776 * Only works with TrueType fonts
2782 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2785 DC *dc = get_dc_ptr(hdc);
2791 if (!dc) return FALSE;
2795 release_dc_ptr( dc );
2799 /* unlike GetCharABCWidthsFloatW, this one is supposed to fail on non-scalable fonts */
2800 dev = GET_DC_PHYSDEV( dc, pGetTextMetrics );
2801 if (!dev->funcs->pGetTextMetrics( dev, &tm ) || !(tm.tmPitchAndFamily & TMPF_VECTOR))
2803 release_dc_ptr( dc );
2807 dev = GET_DC_PHYSDEV( dc, pGetCharABCWidths );
2808 ret = dev->funcs->pGetCharABCWidths( dev, firstChar, lastChar, abc );
2811 /* convert device units to logical */
2812 for( i = firstChar; i <= lastChar; i++, abc++ ) {
2813 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2814 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2815 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2819 release_dc_ptr( dc );
2824 /******************************************************************************
2825 * GetCharABCWidthsI [GDI32.@]
2827 * Retrieves widths of characters in range.
2830 * hdc [I] Handle of device context
2831 * firstChar [I] First glyphs in range to query
2832 * count [I] Last glyphs in range to query
2833 * pgi [i] Array of glyphs to query
2834 * abc [O] Address of character-width structure
2837 * Only works with TrueType fonts
2843 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2844 LPWORD pgi, LPABC abc)
2846 DC *dc = get_dc_ptr(hdc);
2851 if (!dc) return FALSE;
2855 release_dc_ptr( dc );
2859 dev = GET_DC_PHYSDEV( dc, pGetCharABCWidthsI );
2860 ret = dev->funcs->pGetCharABCWidthsI( dev, firstChar, count, pgi, abc );
2863 /* convert device units to logical */
2864 for( i = 0; i < count; i++, abc++ ) {
2865 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2866 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2867 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2871 release_dc_ptr( dc );
2876 /***********************************************************************
2877 * GetGlyphOutlineA (GDI32.@)
2879 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2880 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2881 LPVOID lpBuffer, const MAT2 *lpmat2 )
2883 if (!lpmat2) return GDI_ERROR;
2885 if(!(fuFormat & GGO_GLYPH_INDEX)) {
2890 cp = GdiGetCodePage(hdc);
2891 if (IsDBCSLeadByteEx(cp, uChar >> 8)) {
2893 mbchs[0] = (uChar & 0xff00) >> 8;
2894 mbchs[1] = (uChar & 0xff);
2897 mbchs[0] = (uChar & 0xff);
2900 MultiByteToWideChar(cp, 0, mbchs, len, (LPWSTR)&uChar, 1);
2903 return GetGlyphOutlineW(hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer,
2907 /***********************************************************************
2908 * GetGlyphOutlineW (GDI32.@)
2910 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2911 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2912 LPVOID lpBuffer, const MAT2 *lpmat2 )
2918 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2919 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2921 if (!lpmat2) return GDI_ERROR;
2923 dc = get_dc_ptr(hdc);
2924 if(!dc) return GDI_ERROR;
2926 dev = GET_DC_PHYSDEV( dc, pGetGlyphOutline );
2927 ret = dev->funcs->pGetGlyphOutline( dev, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2928 release_dc_ptr( dc );
2933 /***********************************************************************
2934 * CreateScalableFontResourceA (GDI32.@)
2936 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2937 LPCSTR lpszResourceFile,
2938 LPCSTR lpszFontFile,
2939 LPCSTR lpszCurrentPath )
2941 LPWSTR lpszResourceFileW = NULL;
2942 LPWSTR lpszFontFileW = NULL;
2943 LPWSTR lpszCurrentPathW = NULL;
2947 if (lpszResourceFile)
2949 len = MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, NULL, 0);
2950 lpszResourceFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2951 MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, lpszResourceFileW, len);
2956 len = MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, NULL, 0);
2957 lpszFontFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2958 MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, lpszFontFileW, len);
2961 if (lpszCurrentPath)
2963 len = MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, NULL, 0);
2964 lpszCurrentPathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2965 MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, lpszCurrentPathW, len);
2968 ret = CreateScalableFontResourceW(fHidden, lpszResourceFileW,
2969 lpszFontFileW, lpszCurrentPathW);
2971 HeapFree(GetProcessHeap(), 0, lpszResourceFileW);
2972 HeapFree(GetProcessHeap(), 0, lpszFontFileW);
2973 HeapFree(GetProcessHeap(), 0, lpszCurrentPathW);
2978 /***********************************************************************
2979 * CreateScalableFontResourceW (GDI32.@)
2981 BOOL WINAPI CreateScalableFontResourceW( DWORD hidden, LPCWSTR resource_file,
2982 LPCWSTR font_file, LPCWSTR font_path )
2984 TRACE("(%d, %s, %s, %s)\n", hidden, debugstr_w(resource_file),
2985 debugstr_w(font_file), debugstr_w(font_path) );
2987 return WineEngCreateScalableFontResource( hidden, resource_file,
2988 font_file, font_path );
2991 /*************************************************************************
2992 * GetKerningPairsA (GDI32.@)
2994 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2995 LPKERNINGPAIR kern_pairA )
2999 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
3000 KERNINGPAIR *kern_pairW;
3002 if (!cPairs && kern_pairA)
3004 SetLastError(ERROR_INVALID_PARAMETER);
3008 cp = GdiGetCodePage(hDC);
3010 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
3011 * to fail on an invalid character for CP_SYMBOL.
3013 cpi.DefaultChar[0] = 0;
3014 if (cp != CP_SYMBOL && !GetCPInfo(cp, &cpi))
3016 FIXME("Can't find codepage %u info\n", cp);
3020 total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
3021 if (!total_kern_pairs) return 0;
3023 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
3024 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
3026 for (i = 0; i < total_kern_pairs; i++)
3030 if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
3033 if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
3036 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
3041 if (kern_pairs_copied >= cPairs) break;
3043 kern_pairA->wFirst = (BYTE)first;
3044 kern_pairA->wSecond = (BYTE)second;
3045 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
3048 kern_pairs_copied++;
3051 HeapFree(GetProcessHeap(), 0, kern_pairW);
3053 return kern_pairs_copied;
3056 /*************************************************************************
3057 * GetKerningPairsW (GDI32.@)
3059 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
3060 LPKERNINGPAIR lpKerningPairs )
3066 TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
3068 if (!cPairs && lpKerningPairs)
3070 SetLastError(ERROR_INVALID_PARAMETER);
3074 dc = get_dc_ptr(hDC);
3077 dev = GET_DC_PHYSDEV( dc, pGetKerningPairs );
3078 ret = dev->funcs->pGetKerningPairs( dev, cPairs, lpKerningPairs );
3079 release_dc_ptr( dc );
3083 /*************************************************************************
3084 * TranslateCharsetInfo [GDI32.@]
3086 * Fills a CHARSETINFO structure for a character set, code page, or
3087 * font. This allows making the correspondence between different labels
3088 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
3089 * of the same encoding.
3091 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
3092 * only one codepage should be set in *lpSrc.
3095 * TRUE on success, FALSE on failure.
3098 BOOL WINAPI TranslateCharsetInfo(
3099 LPDWORD lpSrc, /* [in]
3100 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
3101 if flags == TCI_SRCCHARSET: a character set value
3102 if flags == TCI_SRCCODEPAGE: a code page value
3104 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
3105 DWORD flags /* [in] determines interpretation of lpSrc */)
3109 case TCI_SRCFONTSIG:
3110 while (index < MAXTCIINDEX && !(*lpSrc>>index & 0x0001)) index++;
3112 case TCI_SRCCODEPAGE:
3113 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciACP) index++;
3115 case TCI_SRCCHARSET:
3116 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciCharset) index++;
3121 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
3122 *lpCs = FONT_tci[index];
3126 /*************************************************************************
3127 * GetFontLanguageInfo (GDI32.@)
3129 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
3131 FONTSIGNATURE fontsig;
3132 static const DWORD GCP_DBCS_MASK=0x003F0000,
3133 GCP_DIACRITIC_MASK=0x00000000,
3134 FLI_GLYPHS_MASK=0x00000000,
3135 GCP_GLYPHSHAPE_MASK=0x00000040,
3136 GCP_KASHIDA_MASK=0x00000000,
3137 GCP_LIGATE_MASK=0x00000000,
3138 GCP_USEKERNING_MASK=0x00000000,
3139 GCP_REORDER_MASK=0x00000060;
3143 GetTextCharsetInfo( hdc, &fontsig, 0 );
3144 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
3146 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
3149 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
3150 result|=GCP_DIACRITIC;
3152 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
3155 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
3156 result|=GCP_GLYPHSHAPE;
3158 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
3159 result|=GCP_KASHIDA;
3161 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
3164 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
3165 result|=GCP_USEKERNING;
3167 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
3168 if( GetTextAlign( hdc) & TA_RTLREADING )
3169 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
3170 result|=GCP_REORDER;
3176 /*************************************************************************
3177 * GetFontData [GDI32.@]
3179 * Retrieve data for TrueType font.
3183 * success: Number of bytes returned
3184 * failure: GDI_ERROR
3188 * Calls SetLastError()
3191 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
3192 LPVOID buffer, DWORD length)
3194 DC *dc = get_dc_ptr(hdc);
3198 if(!dc) return GDI_ERROR;
3200 dev = GET_DC_PHYSDEV( dc, pGetFontData );
3201 ret = dev->funcs->pGetFontData( dev, table, offset, buffer, length );
3202 release_dc_ptr( dc );
3206 /*************************************************************************
3207 * GetGlyphIndicesA [GDI32.@]
3209 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
3210 LPWORD pgi, DWORD flags)
3216 TRACE("(%p, %s, %d, %p, 0x%x)\n",
3217 hdc, debugstr_an(lpstr, count), count, pgi, flags);
3219 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
3220 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
3221 HeapFree(GetProcessHeap(), 0, lpstrW);
3226 /*************************************************************************
3227 * GetGlyphIndicesW [GDI32.@]
3229 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
3230 LPWORD pgi, DWORD flags)
3232 DC *dc = get_dc_ptr(hdc);
3236 TRACE("(%p, %s, %d, %p, 0x%x)\n",
3237 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
3239 if(!dc) return GDI_ERROR;
3241 dev = GET_DC_PHYSDEV( dc, pGetGlyphIndices );
3242 ret = dev->funcs->pGetGlyphIndices( dev, lpstr, count, pgi, flags );
3243 release_dc_ptr( dc );
3247 /*************************************************************************
3248 * GetCharacterPlacementA [GDI32.@]
3250 * See GetCharacterPlacementW.
3253 * the web browser control of ie4 calls this with dwFlags=0
3256 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
3257 INT nMaxExtent, GCP_RESULTSA *lpResults,
3262 GCP_RESULTSW resultsW;
3266 TRACE("%s, %d, %d, 0x%08x\n",
3267 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
3269 /* both structs are equal in size */
3270 memcpy(&resultsW, lpResults, sizeof(resultsW));
3272 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
3273 if(lpResults->lpOutString)
3274 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
3276 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
3278 lpResults->nGlyphs = resultsW.nGlyphs;
3279 lpResults->nMaxFit = resultsW.nMaxFit;
3281 if(lpResults->lpOutString) {
3282 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
3283 lpResults->lpOutString, uCount, NULL, NULL );
3286 HeapFree(GetProcessHeap(), 0, lpStringW);
3287 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
3292 /*************************************************************************
3293 * GetCharacterPlacementW [GDI32.@]
3295 * Retrieve information about a string. This includes the width, reordering,
3296 * Glyphing and so on.
3300 * The width and height of the string if successful, 0 if failed.
3304 * All flags except GCP_REORDER are not yet implemented.
3305 * Reordering is not 100% compliant to the Windows BiDi method.
3306 * Caret positioning is not yet implemented for BiDi.
3307 * Classes are not yet implemented.
3311 GetCharacterPlacementW(
3312 HDC hdc, /* [in] Device context for which the rendering is to be done */
3313 LPCWSTR lpString, /* [in] The string for which information is to be returned */
3314 INT uCount, /* [in] Number of WORDS in string. */
3315 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
3316 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
3317 DWORD dwFlags /* [in] Flags specifying how to process the string */
3324 TRACE("%s, %d, %d, 0x%08x\n",
3325 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
3327 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
3328 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
3329 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
3330 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
3331 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
3333 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08x ignored\n", dwFlags);
3334 if(lpResults->lpClass) FIXME("classes not implemented\n");
3335 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
3336 FIXME("Caret positions for complex scripts not implemented\n");
3338 nSet = (UINT)uCount;
3339 if(nSet > lpResults->nGlyphs)
3340 nSet = lpResults->nGlyphs;
3342 /* return number of initialized fields */
3343 lpResults->nGlyphs = nSet;
3345 if((dwFlags&GCP_REORDER)==0 )
3347 /* Treat the case where no special handling was requested in a fastpath way */
3348 /* copy will do if the GCP_REORDER flag is not set */
3349 if(lpResults->lpOutString)
3350 memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
3352 if(lpResults->lpOrder)
3354 for(i = 0; i < nSet; i++)
3355 lpResults->lpOrder[i] = i;
3359 BIDI_Reorder(NULL, lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
3360 nSet, lpResults->lpOrder, NULL, NULL );
3363 /* FIXME: Will use the placement chars */
3364 if (lpResults->lpDx)
3367 for (i = 0; i < nSet; i++)
3369 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
3370 lpResults->lpDx[i]= c;
3374 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
3378 lpResults->lpCaretPos[0] = 0;
3379 for (i = 1; i < nSet; i++)
3380 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
3381 lpResults->lpCaretPos[i] = (pos += size.cx);
3384 if(lpResults->lpGlyphs)
3385 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
3387 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
3388 ret = MAKELONG(size.cx, size.cy);
3393 /*************************************************************************
3394 * GetCharABCWidthsFloatA [GDI32.@]
3396 * See GetCharABCWidthsFloatW.
3398 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3405 str = FONT_GetCharsByRangeA(hdc, first, last, &i);
3409 wstr = FONT_mbtowc( hdc, str, i, &wlen, NULL );
3411 for (i = 0; i < wlen; i++)
3413 if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
3421 HeapFree( GetProcessHeap(), 0, str );
3422 HeapFree( GetProcessHeap(), 0, wstr );
3427 /*************************************************************************
3428 * GetCharABCWidthsFloatW [GDI32.@]
3430 * Retrieves widths of a range of characters.
3433 * hdc [I] Handle to device context.
3434 * first [I] First character in range to query.
3435 * last [I] Last character in range to query.
3436 * abcf [O] Array of LPABCFLOAT structures.
3442 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3448 DC *dc = get_dc_ptr( hdc );
3450 TRACE("%p, %d, %d, %p\n", hdc, first, last, abcf);
3452 if (!dc) return FALSE;
3454 if (!abcf) goto done;
3455 if (!(abc = HeapAlloc( GetProcessHeap(), 0, (last - first + 1) * sizeof(*abc) ))) goto done;
3457 dev = GET_DC_PHYSDEV( dc, pGetCharABCWidths );
3458 ret = dev->funcs->pGetCharABCWidths( dev, first, last, abc );
3461 /* convert device units to logical */
3462 for (i = first; i <= last; i++, abcf++)
3464 abcf->abcfA = abc[i - first].abcA * dc->xformVport2World.eM11;
3465 abcf->abcfB = abc[i - first].abcB * dc->xformVport2World.eM11;
3466 abcf->abcfC = abc[i - first].abcC * dc->xformVport2World.eM11;
3469 HeapFree( GetProcessHeap(), 0, abc );
3472 release_dc_ptr( dc );
3476 /*************************************************************************
3477 * GetCharWidthFloatA [GDI32.@]
3479 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
3480 UINT iLastChar, PFLOAT pxBuffer)
3482 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3486 /*************************************************************************
3487 * GetCharWidthFloatW [GDI32.@]
3489 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
3490 UINT iLastChar, PFLOAT pxBuffer)
3492 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3497 /***********************************************************************
3499 * Font Resource API *
3501 ***********************************************************************/
3503 /***********************************************************************
3504 * AddFontResourceA (GDI32.@)
3506 INT WINAPI AddFontResourceA( LPCSTR str )
3508 return AddFontResourceExA( str, 0, NULL);
3511 /***********************************************************************
3512 * AddFontResourceW (GDI32.@)
3514 INT WINAPI AddFontResourceW( LPCWSTR str )
3516 return AddFontResourceExW(str, 0, NULL);
3520 /***********************************************************************
3521 * AddFontResourceExA (GDI32.@)
3523 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3525 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3526 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3529 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3530 ret = AddFontResourceExW(strW, fl, pdv);
3531 HeapFree(GetProcessHeap(), 0, strW);
3535 static BOOL CALLBACK load_enumed_resource(HMODULE hModule, LPCWSTR type, LPWSTR name, LONG_PTR lParam)
3537 HRSRC rsrc = FindResourceW(hModule, name, type);
3538 HGLOBAL hMem = LoadResource(hModule, rsrc);
3539 LPVOID *pMem = LockResource(hMem);
3540 int *num_total = (int *)lParam;
3543 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type));
3544 if (!AddFontMemResourceEx(pMem, SizeofResource(hModule, rsrc), NULL, &num_in_res))
3546 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule, hMem);
3550 *num_total += num_in_res;
3554 static void *map_file( const WCHAR *filename, LARGE_INTEGER *size )
3556 HANDLE file, mapping;
3559 file = CreateFileW( filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
3560 if (file == INVALID_HANDLE_VALUE) return NULL;
3562 if (!GetFileSizeEx( file, size ) || size->u.HighPart)
3564 CloseHandle( file );
3568 mapping = CreateFileMappingW( file, NULL, PAGE_READONLY, 0, 0, NULL );
3569 CloseHandle( file );
3570 if (!mapping) return NULL;
3572 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 );
3573 CloseHandle( mapping );
3578 static WCHAR *get_scalable_filename( const WCHAR *res )
3581 BYTE *ptr = map_file( res, &size );
3582 const IMAGE_DOS_HEADER *dos;
3583 const IMAGE_OS2_HEADER *ne;
3585 WORD rsrc_off, align, type_id, count;
3586 DWORD res_off, res_len, i;
3589 if (!ptr) return NULL;
3591 if (size.u.LowPart < sizeof( *dos )) goto fail;
3592 dos = (const IMAGE_DOS_HEADER *)ptr;
3593 if (dos->e_magic != IMAGE_DOS_SIGNATURE) goto fail;
3594 if (size.u.LowPart < dos->e_lfanew + sizeof( *ne )) goto fail;
3595 ne = (const IMAGE_OS2_HEADER *)(ptr + dos->e_lfanew);
3596 rsrc_off = dos->e_lfanew + ne->ne_rsrctab;
3597 if (size.u.LowPart < rsrc_off + 10) goto fail;
3598 align = *(WORD *)(ptr + rsrc_off);
3600 type_id = *(WORD *)(ptr + rsrc_off);
3601 while (type_id && type_id != 0x80cc)
3603 count = *(WORD *)(ptr + rsrc_off + 2);
3604 rsrc_off += 8 + count * 12;
3605 if (size.u.LowPart < rsrc_off + 8) goto fail;
3606 type_id = *(WORD *)(ptr + rsrc_off);
3608 if (!type_id) goto fail;
3609 count = *(WORD *)(ptr + rsrc_off + 2);
3610 if (size.u.LowPart < rsrc_off + 8 + count * 12) goto fail;
3612 res_off = *(WORD *)(ptr + rsrc_off + 8) << align;
3613 res_len = *(WORD *)(ptr + rsrc_off + 10) << align;
3614 if (size.u.LowPart < res_off + res_len) goto fail;
3616 for (i = 0; i < res_len; i++)
3617 if (ptr[ res_off + i ] == 0) break;
3618 if (i == res_len) goto fail;
3620 len = MultiByteToWideChar( CP_ACP, 0, (char *)ptr + res_off, -1, NULL, 0 );
3621 name = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
3622 if (name) MultiByteToWideChar( CP_ACP, 0, (char *)ptr + res_off, -1, name, len );
3625 UnmapViewOfFile( ptr );
3629 /***********************************************************************
3630 * AddFontResourceExW (GDI32.@)
3632 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3634 int ret = WineEngAddFontResourceEx(str, fl, pdv);
3639 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3640 HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
3641 if (hModule != NULL)
3643 int num_resources = 0;
3644 LPWSTR rt_font = (LPWSTR)((ULONG_PTR)8); /* we don't want to include winuser.h */
3646 TRACE("WineEngAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3647 wine_dbgstr_w(str));
3648 if (EnumResourceNamesW(hModule, rt_font, load_enumed_resource, (LONG_PTR)&num_resources))
3649 ret = num_resources;
3650 FreeLibrary(hModule);
3652 else if ((filename = get_scalable_filename( str )) != NULL)
3654 ret = WineEngAddFontResourceEx( filename, fl, pdv );
3655 HeapFree( GetProcessHeap(), 0, filename );
3661 /***********************************************************************
3662 * RemoveFontResourceA (GDI32.@)
3664 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3666 return RemoveFontResourceExA(str, 0, 0);
3669 /***********************************************************************
3670 * RemoveFontResourceW (GDI32.@)
3672 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3674 return RemoveFontResourceExW(str, 0, 0);
3677 /***********************************************************************
3678 * AddFontMemResourceEx (GDI32.@)
3680 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3685 if (!pbFont || !cbFont || !pcFonts)
3687 SetLastError(ERROR_INVALID_PARAMETER);
3691 ret = WineEngAddFontMemResourceEx(pbFont, cbFont, pdv, &num_fonts);
3696 *pcFonts = num_fonts;
3700 WARN("page fault while writing to *pcFonts (%p)\n", pcFonts);
3701 RemoveFontMemResourceEx(ret);
3709 /***********************************************************************
3710 * RemoveFontMemResourceEx (GDI32.@)
3712 BOOL WINAPI RemoveFontMemResourceEx( HANDLE fh )
3714 FIXME("(%p) stub\n", fh);
3718 /***********************************************************************
3719 * RemoveFontResourceExA (GDI32.@)
3721 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3723 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3724 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3727 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3728 ret = RemoveFontResourceExW(strW, fl, pdv);
3729 HeapFree(GetProcessHeap(), 0, strW);
3733 /***********************************************************************
3734 * RemoveFontResourceExW (GDI32.@)
3736 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3738 return WineEngRemoveFontResourceEx(str, fl, pdv);
3741 /***********************************************************************
3742 * GetTextCharset (GDI32.@)
3744 UINT WINAPI GetTextCharset(HDC hdc)
3746 /* MSDN docs say this is equivalent */
3747 return GetTextCharsetInfo(hdc, NULL, 0);
3750 /***********************************************************************
3751 * GetTextCharsetInfo (GDI32.@)
3753 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3755 UINT ret = DEFAULT_CHARSET;
3756 DC *dc = get_dc_ptr(hdc);
3761 dev = GET_DC_PHYSDEV( dc, pGetTextCharsetInfo );
3762 ret = dev->funcs->pGetTextCharsetInfo( dev, fs, flags );
3763 release_dc_ptr( dc );
3766 if (ret == DEFAULT_CHARSET && fs)
3767 memset(fs, 0, sizeof(FONTSIGNATURE));
3771 /***********************************************************************
3772 * GdiGetCharDimensions (GDI32.@)
3774 * Gets the average width of the characters in the English alphabet.
3777 * hdc [I] Handle to the device context to measure on.
3778 * lptm [O] Pointer to memory to store the text metrics into.
3779 * height [O] On exit, the maximum height of characters in the English alphabet.
3782 * The average width of characters in the English alphabet.
3785 * This function is used by the dialog manager to get the size of a dialog
3786 * unit. It should also be used by other pieces of code that need to know
3787 * the size of a dialog unit in logical units without having access to the
3788 * window handle of the dialog.
3789 * Windows caches the font metrics from this function, but we don't and
3790 * there doesn't appear to be an immediate advantage to do so.
3793 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3795 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3798 static const WCHAR alphabet[] = {
3799 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3800 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3801 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3803 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3805 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3807 if (height) *height = sz.cy;
3808 return (sz.cx / 26 + 1) / 2;
3811 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3813 FIXME("(%d): stub\n", fEnableEUDC);
3817 /***********************************************************************
3818 * GetCharWidthI (GDI32.@)
3820 * Retrieve widths of characters.
3823 * hdc [I] Handle to a device context.
3824 * first [I] First glyph in range to query.
3825 * count [I] Number of glyph indices to query.
3826 * glyphs [I] Array of glyphs to query.
3827 * buffer [O] Buffer to receive character widths.
3830 * Only works with TrueType fonts.
3836 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3841 TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3843 if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3846 if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3848 HeapFree(GetProcessHeap(), 0, abc);
3852 for (i = 0; i < count; i++)
3853 buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3855 HeapFree(GetProcessHeap(), 0, abc);
3859 /***********************************************************************
3860 * GetFontUnicodeRanges (GDI32.@)
3862 * Retrieve a list of supported Unicode characters in a font.
3865 * hdc [I] Handle to a device context.
3866 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3869 * Success: Number of bytes written to the buffer pointed to by lpgs.
3873 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3877 DC *dc = get_dc_ptr(hdc);
3879 TRACE("(%p, %p)\n", hdc, lpgs);
3883 dev = GET_DC_PHYSDEV( dc, pGetFontUnicodeRanges );
3884 ret = dev->funcs->pGetFontUnicodeRanges( dev, lpgs );
3890 /*************************************************************
3891 * FontIsLinked (GDI32.@)
3893 BOOL WINAPI FontIsLinked(HDC hdc)
3895 DC *dc = get_dc_ptr(hdc);
3899 if (!dc) return FALSE;
3900 dev = GET_DC_PHYSDEV( dc, pFontIsLinked );
3901 ret = dev->funcs->pFontIsLinked( dev );
3903 TRACE("returning %d\n", ret);
3907 /*************************************************************
3908 * GdiRealizationInfo (GDI32.@)
3910 * Returns a structure that contains some font information.
3912 BOOL WINAPI GdiRealizationInfo(HDC hdc, realization_info_t *info)
3914 DC *dc = get_dc_ptr(hdc);
3918 if (!dc) return FALSE;
3919 dev = GET_DC_PHYSDEV( dc, pGdiRealizationInfo );
3920 ret = dev->funcs->pGdiRealizationInfo( dev, info );