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 WINE_DEFAULT_DEBUG_CHANNEL(font);
44 /* Device -> World size conversion */
46 /* Performs a device to world transformation on the specified width (which
47 * is in integer format).
49 static inline INT INTERNAL_XDSTOWS(DC *dc, INT width)
53 /* Perform operation with floating point */
54 floatWidth = (double)width * dc->xformVport2World.eM11;
55 /* Round to integers */
56 return GDI_ROUND(floatWidth);
59 /* Performs a device to world transformation on the specified size (which
60 * is in integer format).
62 static inline INT INTERNAL_YDSTOWS(DC *dc, INT height)
66 /* Perform operation with floating point */
67 floatHeight = (double)height * dc->xformVport2World.eM22;
68 /* Round to integers */
69 return GDI_ROUND(floatHeight);
72 static inline INT INTERNAL_XWSTODS(DC *dc, INT width)
75 pt[0].x = pt[0].y = 0;
78 LPtoDP(dc->hSelf, pt, 2);
79 return pt[1].x - pt[0].x;
82 static inline INT INTERNAL_YWSTODS(DC *dc, INT height)
85 pt[0].x = pt[0].y = 0;
88 LPtoDP(dc->hSelf, pt, 2);
89 return pt[1].y - pt[0].y;
92 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc );
93 static INT FONT_GetObjectA( HGDIOBJ handle, INT count, LPVOID buffer );
94 static INT FONT_GetObjectW( HGDIOBJ handle, INT count, LPVOID buffer );
95 static BOOL FONT_DeleteObject( HGDIOBJ handle );
97 static const struct gdi_obj_funcs font_funcs =
99 FONT_SelectObject, /* pSelectObject */
100 FONT_GetObjectA, /* pGetObjectA */
101 FONT_GetObjectW, /* pGetObjectW */
102 NULL, /* pUnrealizeObject */
103 FONT_DeleteObject /* pDeleteObject */
113 LPLOGFONTW lpLogFontParam;
114 FONTENUMPROCW lpEnumFunc;
122 * For TranslateCharsetInfo
124 #define MAXTCIINDEX 32
125 static const CHARSETINFO FONT_tci[MAXTCIINDEX] = {
127 { ANSI_CHARSET, 1252, {{0,0,0,0},{FS_LATIN1,0}} },
128 { EASTEUROPE_CHARSET, 1250, {{0,0,0,0},{FS_LATIN2,0}} },
129 { RUSSIAN_CHARSET, 1251, {{0,0,0,0},{FS_CYRILLIC,0}} },
130 { GREEK_CHARSET, 1253, {{0,0,0,0},{FS_GREEK,0}} },
131 { TURKISH_CHARSET, 1254, {{0,0,0,0},{FS_TURKISH,0}} },
132 { HEBREW_CHARSET, 1255, {{0,0,0,0},{FS_HEBREW,0}} },
133 { ARABIC_CHARSET, 1256, {{0,0,0,0},{FS_ARABIC,0}} },
134 { BALTIC_CHARSET, 1257, {{0,0,0,0},{FS_BALTIC,0}} },
135 { VIETNAMESE_CHARSET, 1258, {{0,0,0,0},{FS_VIETNAMESE,0}} },
136 /* reserved by ANSI */
137 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
138 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
139 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
140 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
141 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
142 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
143 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
145 { THAI_CHARSET, 874, {{0,0,0,0},{FS_THAI,0}} },
146 { SHIFTJIS_CHARSET, 932, {{0,0,0,0},{FS_JISJAPAN,0}} },
147 { GB2312_CHARSET, 936, {{0,0,0,0},{FS_CHINESESIMP,0}} },
148 { HANGEUL_CHARSET, 949, {{0,0,0,0},{FS_WANSUNG,0}} },
149 { CHINESEBIG5_CHARSET, 950, {{0,0,0,0},{FS_CHINESETRAD,0}} },
150 { JOHAB_CHARSET, 1361, {{0,0,0,0},{FS_JOHAB,0}} },
151 /* reserved for alternate ANSI and OEM */
152 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
153 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
154 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
155 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
156 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
157 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
158 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
159 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
160 /* reserved for system */
161 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
162 { SYMBOL_CHARSET, CP_SYMBOL, {{0,0,0,0},{FS_SYMBOL,0}} }
165 static void FONT_LogFontAToW( const LOGFONTA *fontA, LPLOGFONTW fontW )
167 memcpy(fontW, fontA, sizeof(LOGFONTA) - LF_FACESIZE);
168 MultiByteToWideChar(CP_ACP, 0, fontA->lfFaceName, -1, fontW->lfFaceName,
170 fontW->lfFaceName[LF_FACESIZE-1] = 0;
173 static void FONT_LogFontWToA( const LOGFONTW *fontW, LPLOGFONTA fontA )
175 memcpy(fontA, fontW, sizeof(LOGFONTA) - LF_FACESIZE);
176 WideCharToMultiByte(CP_ACP, 0, fontW->lfFaceName, -1, fontA->lfFaceName,
177 LF_FACESIZE, NULL, NULL);
178 fontA->lfFaceName[LF_FACESIZE-1] = 0;
181 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEXA fontA )
183 FONT_LogFontWToA( &fontW->elfLogFont, &fontA->elfLogFont );
185 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
186 (LPSTR) fontA->elfFullName, LF_FULLFACESIZE, NULL, NULL );
187 fontA->elfFullName[LF_FULLFACESIZE-1] = '\0';
188 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
189 (LPSTR) fontA->elfStyle, LF_FACESIZE, NULL, NULL );
190 fontA->elfStyle[LF_FACESIZE-1] = '\0';
191 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
192 (LPSTR) fontA->elfScript, LF_FACESIZE, NULL, NULL );
193 fontA->elfScript[LF_FACESIZE-1] = '\0';
196 static void FONT_EnumLogFontExAToW( const ENUMLOGFONTEXA *fontA, LPENUMLOGFONTEXW fontW )
198 FONT_LogFontAToW( &fontA->elfLogFont, &fontW->elfLogFont );
200 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfFullName, -1,
201 fontW->elfFullName, LF_FULLFACESIZE );
202 fontW->elfFullName[LF_FULLFACESIZE-1] = '\0';
203 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfStyle, -1,
204 fontW->elfStyle, LF_FACESIZE );
205 fontW->elfStyle[LF_FACESIZE-1] = '\0';
206 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfScript, -1,
207 fontW->elfScript, LF_FACESIZE );
208 fontW->elfScript[LF_FACESIZE-1] = '\0';
211 /***********************************************************************
212 * TEXTMETRIC conversion functions.
214 static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
216 ptmA->tmHeight = ptmW->tmHeight;
217 ptmA->tmAscent = ptmW->tmAscent;
218 ptmA->tmDescent = ptmW->tmDescent;
219 ptmA->tmInternalLeading = ptmW->tmInternalLeading;
220 ptmA->tmExternalLeading = ptmW->tmExternalLeading;
221 ptmA->tmAveCharWidth = ptmW->tmAveCharWidth;
222 ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth;
223 ptmA->tmWeight = ptmW->tmWeight;
224 ptmA->tmOverhang = ptmW->tmOverhang;
225 ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX;
226 ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
227 ptmA->tmFirstChar = min(ptmW->tmFirstChar, 255);
228 if (ptmW->tmCharSet == SYMBOL_CHARSET)
230 ptmA->tmFirstChar = 0x1e;
231 ptmA->tmLastChar = 0xff; /* win9x behaviour - we need the OS2 table data to calculate correctly */
233 else if (ptmW->tmPitchAndFamily & TMPF_TRUETYPE)
235 ptmA->tmFirstChar = ptmW->tmDefaultChar - 1;
236 ptmA->tmLastChar = min(ptmW->tmLastChar, 0xff);
240 ptmA->tmFirstChar = min(ptmW->tmFirstChar, 0xff);
241 ptmA->tmLastChar = min(ptmW->tmLastChar, 0xff);
243 ptmA->tmDefaultChar = ptmW->tmDefaultChar;
244 ptmA->tmBreakChar = ptmW->tmBreakChar;
245 ptmA->tmItalic = ptmW->tmItalic;
246 ptmA->tmUnderlined = ptmW->tmUnderlined;
247 ptmA->tmStruckOut = ptmW->tmStruckOut;
248 ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
249 ptmA->tmCharSet = ptmW->tmCharSet;
253 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW *ptmW, NEWTEXTMETRICEXA *ptmA )
255 FONT_TextMetricWToA((const TEXTMETRICW *)ptmW, (LPTEXTMETRICA)ptmA);
256 ptmA->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
257 ptmA->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
258 ptmA->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
259 ptmA->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
260 memcpy(&ptmA->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
263 static DWORD get_key_value( HKEY key, const WCHAR *name, DWORD *value )
266 DWORD count = sizeof(buf), type, err;
268 err = RegQueryValueExW( key, name, NULL, &type, (BYTE *)buf, &count );
271 if (type == REG_DWORD) memcpy( value, buf, sizeof(*value) );
272 else *value = atoiW( buf );
277 static UINT get_subpixel_orientation( HKEY key )
279 static const WCHAR smoothing_orientation[] = {'F','o','n','t','S','m','o','o','t','h','i','n','g',
280 'O','r','i','e','n','t','a','t','i','o','n',0};
283 /* FIXME: handle vertical orientations even though Windows doesn't */
284 if (get_key_value( key, smoothing_orientation, &orient )) return GGO_GRAY4_BITMAP;
288 case 0: /* FE_FONTSMOOTHINGORIENTATIONBGR */
289 return WINE_GGO_HBGR_BITMAP;
290 case 1: /* FE_FONTSMOOTHINGORIENTATIONRGB */
291 return WINE_GGO_HRGB_BITMAP;
293 return GGO_GRAY4_BITMAP;
296 static UINT get_default_smoothing( HKEY key )
298 static const WCHAR smoothing[] = {'F','o','n','t','S','m','o','o','t','h','i','n','g',0};
299 static const WCHAR smoothing_type[] = {'F','o','n','t','S','m','o','o','t','h','i','n','g','T','y','p','e',0};
302 if (get_key_value( key, smoothing, &enabled )) return 0;
303 if (!enabled) return GGO_BITMAP;
305 if (!get_key_value( key, smoothing_type, &type ) && type == 2 /* FE_FONTSMOOTHINGCLEARTYPE */)
306 return get_subpixel_orientation( key );
308 return GGO_GRAY4_BITMAP;
311 /* compute positions for text rendering, in device coords */
312 static BOOL get_char_positions( DC *dc, const WCHAR *str, INT count, INT *dx, SIZE *size )
317 size->cx = size->cy = 0;
318 if (!count) return TRUE;
320 dev = GET_DC_PHYSDEV( dc, pGetTextMetrics );
321 dev->funcs->pGetTextMetrics( dev, &tm );
323 dev = GET_DC_PHYSDEV( dc, pGetTextExtentExPoint );
324 if (!dev->funcs->pGetTextExtentExPoint( dev, str, count, dx )) return FALSE;
326 if (dc->breakExtra || dc->breakRem)
328 int i, space = 0, rem = dc->breakRem;
330 for (i = 0; i < count; i++)
332 if (str[i] == tm.tmBreakChar)
334 space += dc->breakExtra;
344 size->cx = dx[count - 1];
345 size->cy = tm.tmHeight;
349 /* compute positions for text rendering, in device coords */
350 static BOOL get_char_positions_indices( DC *dc, const WORD *indices, INT count, INT *dx, SIZE *size )
355 size->cx = size->cy = 0;
356 if (!count) return TRUE;
358 dev = GET_DC_PHYSDEV( dc, pGetTextMetrics );
359 dev->funcs->pGetTextMetrics( dev, &tm );
361 dev = GET_DC_PHYSDEV( dc, pGetTextExtentExPointI );
362 if (!dev->funcs->pGetTextExtentExPointI( dev, indices, count, dx )) return FALSE;
364 if (dc->breakExtra || dc->breakRem)
367 int i, space = 0, rem = dc->breakRem;
369 dev = GET_DC_PHYSDEV( dc, pGetGlyphIndices );
370 dev->funcs->pGetGlyphIndices( dev, &tm.tmBreakChar, 1, &space_index, 0 );
372 for (i = 0; i < count; i++)
374 if (indices[i] == space_index)
376 space += dc->breakExtra;
386 size->cx = dx[count - 1];
387 size->cy = tm.tmHeight;
391 /***********************************************************************
392 * GdiGetCodePage (GDI32.@)
394 DWORD WINAPI GdiGetCodePage( HDC hdc )
397 DC *dc = get_dc_ptr( hdc );
401 cp = dc->font_code_page;
402 release_dc_ptr( dc );
407 /***********************************************************************
410 * Returns a Unicode translation of str using the charset of the
411 * currently selected font in hdc. If count is -1 then str is assumed
412 * to be '\0' terminated, otherwise it contains the number of bytes to
413 * convert. If plenW is non-NULL, on return it will point to the
414 * number of WCHARs that have been written. If pCP is non-NULL, on
415 * return it will point to the codepage used in the conversion. The
416 * caller should free the returned LPWSTR from the process heap
419 static LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
425 cp = GdiGetCodePage( hdc );
427 if(count == -1) count = strlen(str);
428 lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
429 strW = HeapAlloc(GetProcessHeap(), 0, lenW*sizeof(WCHAR));
430 MultiByteToWideChar(cp, 0, str, count, strW, lenW);
431 TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW));
432 if(plenW) *plenW = lenW;
437 /***********************************************************************
438 * CreateFontIndirectExA (GDI32.@)
440 HFONT WINAPI CreateFontIndirectExA( const ENUMLOGFONTEXDVA *penumexA )
442 ENUMLOGFONTEXDVW enumexW;
444 if (!penumexA) return 0;
446 FONT_EnumLogFontExAToW( &penumexA->elfEnumLogfontEx, &enumexW.elfEnumLogfontEx );
447 enumexW.elfDesignVector = penumexA->elfDesignVector;
448 return CreateFontIndirectExW( &enumexW );
451 /***********************************************************************
452 * CreateFontIndirectExW (GDI32.@)
454 HFONT WINAPI CreateFontIndirectExW( const ENUMLOGFONTEXDVW *penumex )
460 if (!penumex) return 0;
462 if (penumex->elfEnumLogfontEx.elfFullName[0] ||
463 penumex->elfEnumLogfontEx.elfStyle[0] ||
464 penumex->elfEnumLogfontEx.elfScript[0])
466 FIXME("some fields ignored. fullname=%s, style=%s, script=%s\n",
467 debugstr_w(penumex->elfEnumLogfontEx.elfFullName),
468 debugstr_w(penumex->elfEnumLogfontEx.elfStyle),
469 debugstr_w(penumex->elfEnumLogfontEx.elfScript));
472 plf = &penumex->elfEnumLogfontEx.elfLogFont;
473 if (!(fontPtr = HeapAlloc( GetProcessHeap(), 0, sizeof(*fontPtr) ))) return 0;
475 fontPtr->logfont = *plf;
477 if (!(hFont = alloc_gdi_handle( fontPtr, OBJ_FONT, &font_funcs )))
479 HeapFree( GetProcessHeap(), 0, fontPtr );
483 TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
484 plf->lfHeight, plf->lfWidth,
485 plf->lfEscapement, plf->lfOrientation,
486 plf->lfPitchAndFamily,
487 plf->lfOutPrecision, plf->lfClipPrecision,
488 plf->lfQuality, plf->lfCharSet,
489 debugstr_w(plf->lfFaceName),
490 plf->lfWeight > 400 ? "Bold" : "",
491 plf->lfItalic ? "Italic" : "",
492 plf->lfUnderline ? "Underline" : "", hFont);
497 /***********************************************************************
498 * CreateFontIndirectA (GDI32.@)
500 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *plfA )
506 FONT_LogFontAToW( plfA, &lfW );
507 return CreateFontIndirectW( &lfW );
510 /***********************************************************************
511 * CreateFontIndirectW (GDI32.@)
513 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
515 ENUMLOGFONTEXDVW exdv;
519 exdv.elfEnumLogfontEx.elfLogFont = *plf;
520 exdv.elfEnumLogfontEx.elfFullName[0] = 0;
521 exdv.elfEnumLogfontEx.elfStyle[0] = 0;
522 exdv.elfEnumLogfontEx.elfScript[0] = 0;
523 return CreateFontIndirectExW( &exdv );
526 /*************************************************************************
527 * CreateFontA (GDI32.@)
529 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
530 INT orient, INT weight, DWORD italic,
531 DWORD underline, DWORD strikeout, DWORD charset,
532 DWORD outpres, DWORD clippres, DWORD quality,
533 DWORD pitch, LPCSTR name )
537 logfont.lfHeight = height;
538 logfont.lfWidth = width;
539 logfont.lfEscapement = esc;
540 logfont.lfOrientation = orient;
541 logfont.lfWeight = weight;
542 logfont.lfItalic = italic;
543 logfont.lfUnderline = underline;
544 logfont.lfStrikeOut = strikeout;
545 logfont.lfCharSet = charset;
546 logfont.lfOutPrecision = outpres;
547 logfont.lfClipPrecision = clippres;
548 logfont.lfQuality = quality;
549 logfont.lfPitchAndFamily = pitch;
552 lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
554 logfont.lfFaceName[0] = '\0';
556 return CreateFontIndirectA( &logfont );
559 /*************************************************************************
560 * CreateFontW (GDI32.@)
562 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
563 INT orient, INT weight, DWORD italic,
564 DWORD underline, DWORD strikeout, DWORD charset,
565 DWORD outpres, DWORD clippres, DWORD quality,
566 DWORD pitch, LPCWSTR name )
570 logfont.lfHeight = height;
571 logfont.lfWidth = width;
572 logfont.lfEscapement = esc;
573 logfont.lfOrientation = orient;
574 logfont.lfWeight = weight;
575 logfont.lfItalic = italic;
576 logfont.lfUnderline = underline;
577 logfont.lfStrikeOut = strikeout;
578 logfont.lfCharSet = charset;
579 logfont.lfOutPrecision = outpres;
580 logfont.lfClipPrecision = clippres;
581 logfont.lfQuality = quality;
582 logfont.lfPitchAndFamily = pitch;
585 lstrcpynW(logfont.lfFaceName, name,
586 sizeof(logfont.lfFaceName) / sizeof(WCHAR));
588 logfont.lfFaceName[0] = '\0';
590 return CreateFontIndirectW( &logfont );
593 #define ASSOC_CHARSET_OEM 1
594 #define ASSOC_CHARSET_ANSI 2
595 #define ASSOC_CHARSET_SYMBOL 4
597 static DWORD get_associated_charset_info(void)
599 static DWORD associated_charset = -1;
601 if (associated_charset == -1)
603 static const WCHAR assoc_charset_reg_keyW[] = {'S','y','s','t','e','m','\\',
604 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
605 'C','o','n','t','r','o','l','\\','F','o','n','t','A','s','s','o','c','\\',
606 'A','s','s','o','c','i','a','t','e','d',' ','C','h','a','r','s','e','t','\0'};
607 static const WCHAR ansiW[] = {'A','N','S','I','(','0','0',')','\0'};
608 static const WCHAR oemW[] = {'O','E','M','(','F','F',')','\0'};
609 static const WCHAR symbolW[] = {'S','Y','M','B','O','L','(','0','2',')','\0'};
610 static const WCHAR yesW[] = {'Y','E','S','\0'};
613 DWORD type, data_len;
615 associated_charset = 0;
617 if (RegOpenKeyW(HKEY_LOCAL_MACHINE,
618 assoc_charset_reg_keyW, &hkey) != ERROR_SUCCESS)
621 data_len = sizeof(dataW);
622 if (!RegQueryValueExW(hkey, ansiW, NULL, &type, (LPBYTE)dataW, &data_len) &&
623 type == REG_SZ && !strcmpiW(dataW, yesW))
624 associated_charset |= ASSOC_CHARSET_ANSI;
626 data_len = sizeof(dataW);
627 if (!RegQueryValueExW(hkey, oemW, NULL, &type, (LPBYTE)dataW, &data_len) &&
628 type == REG_SZ && !strcmpiW(dataW, yesW))
629 associated_charset |= ASSOC_CHARSET_OEM;
631 data_len = sizeof(dataW);
632 if (!RegQueryValueExW(hkey, symbolW, NULL, &type, (LPBYTE)dataW, &data_len) &&
633 type == REG_SZ && !strcmpiW(dataW, yesW))
634 associated_charset |= ASSOC_CHARSET_SYMBOL;
638 TRACE("associated_charset = %d\n", associated_charset);
641 return associated_charset;
644 static void update_font_code_page( DC *dc )
647 int charset = GetTextCharsetInfo( dc->hSelf, NULL, 0 );
649 if (charset == ANSI_CHARSET &&
650 get_associated_charset_info() & ASSOC_CHARSET_ANSI)
651 charset = DEFAULT_CHARSET;
653 /* Hmm, nicely designed api this one! */
654 if (TranslateCharsetInfo( ULongToPtr(charset), &csi, TCI_SRCCHARSET) )
655 dc->font_code_page = csi.ciACP;
659 dc->font_code_page = GetOEMCP();
661 case DEFAULT_CHARSET:
662 dc->font_code_page = GetACP();
672 /* FIXME: These have no place here, but because x11drv
673 enumerates fonts with these (made up) charsets some apps
674 might use them and then the FIXME below would become
675 annoying. Now we could pick the intended codepage for
676 each of these, but since it's broken anyway we'll just
677 use CP_ACP and hope it'll go away...
679 dc->font_code_page = CP_ACP;
683 FIXME("Can't find codepage for charset %d\n", charset);
684 dc->font_code_page = CP_ACP;
689 TRACE("charset %d => cp %d\n", charset, dc->font_code_page);
692 /***********************************************************************
695 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc )
698 DC *dc = get_dc_ptr( hdc );
704 if (!GDI_inc_ref_count( handle ))
706 release_dc_ptr( dc );
710 physdev = GET_DC_PHYSDEV( dc, pSelectFont );
711 if (physdev->funcs->pSelectFont( physdev, handle, &aa_flags ))
715 dc->aa_flags = aa_flags ? aa_flags : GGO_BITMAP;
716 update_font_code_page( dc );
717 GDI_dec_ref_count( ret );
719 else GDI_dec_ref_count( handle );
721 release_dc_ptr( dc );
726 /***********************************************************************
729 static INT FONT_GetObjectA( HGDIOBJ handle, INT count, LPVOID buffer )
731 FONTOBJ *font = GDI_GetObjPtr( handle, OBJ_FONT );
737 FONT_LogFontWToA( &font->logfont, &lfA );
738 if (count > sizeof(lfA)) count = sizeof(lfA);
739 memcpy( buffer, &lfA, count );
741 else count = sizeof(lfA);
742 GDI_ReleaseObj( handle );
746 /***********************************************************************
749 static INT FONT_GetObjectW( HGDIOBJ handle, INT count, LPVOID buffer )
751 FONTOBJ *font = GDI_GetObjPtr( handle, OBJ_FONT );
756 if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
757 memcpy( buffer, &font->logfont, count );
759 else count = sizeof(LOGFONTW);
760 GDI_ReleaseObj( handle );
765 /***********************************************************************
768 static BOOL FONT_DeleteObject( HGDIOBJ handle )
772 if (!(obj = free_gdi_handle( handle ))) return FALSE;
773 return HeapFree( GetProcessHeap(), 0, obj );
777 /***********************************************************************
780 HFONT nulldrv_SelectFont( PHYSDEV dev, HFONT font, UINT *aa_flags )
782 static const WCHAR desktopW[] = { 'C','o','n','t','r','o','l',' ','P','a','n','e','l','\\',
783 'D','e','s','k','t','o','p',0 };
787 if (*aa_flags) return 0;
789 GetObjectW( font, sizeof(lf), &lf );
790 switch (lf.lfQuality)
792 case NONANTIALIASED_QUALITY:
793 *aa_flags = GGO_BITMAP;
795 case ANTIALIASED_QUALITY:
796 *aa_flags = GGO_GRAY4_BITMAP;
798 case CLEARTYPE_QUALITY:
799 case CLEARTYPE_NATURAL_QUALITY:
800 if (RegOpenKeyW( HKEY_CURRENT_USER, desktopW, &key )) break;
801 *aa_flags = get_subpixel_orientation( key );
805 if (RegOpenKeyW( HKEY_CURRENT_USER, desktopW, &key )) break;
806 *aa_flags = get_default_smoothing( key );
814 /***********************************************************************
817 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
818 * We have to use other types because of the FONTENUMPROCW definition.
820 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
821 DWORD fType, LPARAM lp )
823 struct font_enum *pfe = (struct font_enum *)lp;
826 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
827 if ((!pfe->lpLogFontParam ||
828 pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
829 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
830 (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
832 /* convert font metrics */
833 ENUMLOGFONTEXA logfont;
834 NEWTEXTMETRICEXA tmA;
838 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
839 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
840 plf = (LOGFONTW *)&logfont.elfLogFont;
841 ptm = (TEXTMETRICW *)&tmA;
843 ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
849 /***********************************************************************
850 * FONT_EnumFontFamiliesEx
852 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf, FONTENUMPROCW efproc,
853 LPARAM lParam, BOOL unicode )
856 DC *dc = get_dc_ptr( hDC );
861 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pEnumFonts );
863 if (plf) TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName), plf->lfCharSet);
864 fe.lpLogFontParam = plf;
865 fe.lpEnumFunc = efproc;
867 fe.unicode = unicode;
870 ret = physdev->funcs->pEnumFonts( physdev, plf, FONT_EnumInstance, (LPARAM)&fe );
871 release_dc_ptr( dc );
873 return ret ? fe.retval : 0;
876 /***********************************************************************
877 * EnumFontFamiliesExW (GDI32.@)
879 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
880 FONTENUMPROCW efproc,
881 LPARAM lParam, DWORD dwFlags )
883 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, TRUE );
886 /***********************************************************************
887 * EnumFontFamiliesExA (GDI32.@)
889 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
890 FONTENUMPROCA efproc,
891 LPARAM lParam, DWORD dwFlags)
897 FONT_LogFontAToW( plf, &lfW );
902 return FONT_EnumFontFamiliesEx( hDC, plfW, (FONTENUMPROCW)efproc, lParam, FALSE );
905 /***********************************************************************
906 * EnumFontFamiliesA (GDI32.@)
908 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
909 FONTENUMPROCA efproc, LPARAM lpData )
915 if (!*lpFamily) return 1;
916 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
917 lf.lfCharSet = DEFAULT_CHARSET;
918 lf.lfPitchAndFamily = 0;
923 return EnumFontFamiliesExA( hDC, plf, efproc, lpData, 0 );
926 /***********************************************************************
927 * EnumFontFamiliesW (GDI32.@)
929 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
930 FONTENUMPROCW efproc, LPARAM lpData )
936 if (!*lpFamily) return 1;
937 lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
938 lf.lfCharSet = DEFAULT_CHARSET;
939 lf.lfPitchAndFamily = 0;
944 return EnumFontFamiliesExW( hDC, plf, efproc, lpData, 0 );
947 /***********************************************************************
948 * EnumFontsA (GDI32.@)
950 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
953 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
956 /***********************************************************************
957 * EnumFontsW (GDI32.@)
959 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
962 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
966 /***********************************************************************
967 * GetTextCharacterExtra (GDI32.@)
969 INT WINAPI GetTextCharacterExtra( HDC hdc )
972 DC *dc = get_dc_ptr( hdc );
973 if (!dc) return 0x80000000;
975 release_dc_ptr( dc );
980 /***********************************************************************
981 * SetTextCharacterExtra (GDI32.@)
983 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
985 INT ret = 0x80000000;
986 DC * dc = get_dc_ptr( hdc );
990 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetTextCharacterExtra );
991 extra = physdev->funcs->pSetTextCharacterExtra( physdev, extra );
992 if (extra != 0x80000000)
995 dc->charExtra = extra;
997 release_dc_ptr( dc );
1003 /***********************************************************************
1004 * SetTextJustification (GDI32.@)
1006 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
1010 DC * dc = get_dc_ptr( hdc );
1012 if (!dc) return FALSE;
1014 physdev = GET_DC_PHYSDEV( dc, pSetTextJustification );
1015 ret = physdev->funcs->pSetTextJustification( physdev, extra, breaks );
1018 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
1019 if (!extra) breaks = 0;
1022 dc->breakExtra = extra / breaks;
1023 dc->breakRem = extra - (breaks * dc->breakExtra);
1031 release_dc_ptr( dc );
1036 /***********************************************************************
1037 * GetTextFaceA (GDI32.@)
1039 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
1041 INT res = GetTextFaceW(hdc, 0, NULL);
1042 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
1043 GetTextFaceW( hdc, res, nameW );
1049 res = WideCharToMultiByte(CP_ACP, 0, nameW, -1, name, count, NULL, NULL);
1053 /* GetTextFaceA does NOT include the nul byte in the return count. */
1060 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
1061 HeapFree( GetProcessHeap(), 0, nameW );
1065 /***********************************************************************
1066 * GetTextFaceW (GDI32.@)
1068 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
1073 DC * dc = get_dc_ptr( hdc );
1076 dev = GET_DC_PHYSDEV( dc, pGetTextFace );
1077 ret = dev->funcs->pGetTextFace( dev, count, name );
1078 release_dc_ptr( dc );
1083 /***********************************************************************
1084 * GetTextExtentPoint32A (GDI32.@)
1086 * See GetTextExtentPoint32W.
1088 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
1095 if (count < 0) return FALSE;
1097 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1101 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
1102 HeapFree( GetProcessHeap(), 0, p );
1105 TRACE("(%p %s %d %p): returning %d x %d\n",
1106 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
1111 /***********************************************************************
1112 * GetTextExtentPoint32W [GDI32.@]
1114 * Computes width/height for a string.
1116 * Computes width and height of the specified string.
1122 BOOL WINAPI GetTextExtentPoint32W(
1123 HDC hdc, /* [in] Handle of device context */
1124 LPCWSTR str, /* [in] Address of text string */
1125 INT count, /* [in] Number of characters in string */
1126 LPSIZE size) /* [out] Address of structure for string size */
1128 return GetTextExtentExPointW(hdc, str, count, 0, NULL, NULL, size);
1131 /***********************************************************************
1132 * GetTextExtentExPointI [GDI32.@]
1134 * Computes width and height of the array of glyph indices.
1137 * hdc [I] Handle of device context.
1138 * indices [I] Glyph index array.
1139 * count [I] Number of glyphs in array.
1140 * max_ext [I] Maximum width in glyphs.
1141 * nfit [O] Maximum number of characters.
1142 * dxs [O] Partial string widths.
1143 * size [O] Returned string size.
1149 BOOL WINAPI GetTextExtentExPointI( HDC hdc, const WORD *indices, INT count, INT max_ext,
1150 LPINT nfit, LPINT dxs, LPSIZE size )
1155 INT buffer[256], *pos = dxs;
1157 if (count < 0) return FALSE;
1159 dc = get_dc_ptr( hdc );
1160 if (!dc) return FALSE;
1165 if (count > 256 && !(pos = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*pos) )))
1167 release_dc_ptr( dc );
1172 ret = get_char_positions_indices( dc, indices, count, pos, size );
1177 for (i = 0; i < count; i++)
1179 unsigned int dx = abs( INTERNAL_XDSTOWS( dc, pos[i] )) + (i + 1) * dc->charExtra;
1180 if (dx > (unsigned int)max_ext) break;
1181 if (dxs) dxs[i] = dx;
1183 if (nfit) *nfit = i;
1186 size->cx = abs( INTERNAL_XDSTOWS( dc, size->cx )) + count * dc->charExtra;
1187 size->cy = abs( INTERNAL_YDSTOWS( dc, size->cy ));
1190 if (pos != buffer && pos != dxs) HeapFree( GetProcessHeap(), 0, pos );
1191 release_dc_ptr( dc );
1193 TRACE("(%p %p %d %p): returning %d x %d\n",
1194 hdc, indices, count, size, size->cx, size->cy );
1198 /***********************************************************************
1199 * GetTextExtentPointI [GDI32.@]
1201 * Computes width and height of the array of glyph indices.
1204 * hdc [I] Handle of device context.
1205 * indices [I] Glyph index array.
1206 * count [I] Number of glyphs in array.
1207 * size [O] Returned string size.
1213 BOOL WINAPI GetTextExtentPointI( HDC hdc, const WORD *indices, INT count, LPSIZE size )
1215 return GetTextExtentExPointI( hdc, indices, count, 0, NULL, NULL, size );
1219 /***********************************************************************
1220 * GetTextExtentPointA (GDI32.@)
1222 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
1225 TRACE("not bug compatible.\n");
1226 return GetTextExtentPoint32A( hdc, str, count, size );
1229 /***********************************************************************
1230 * GetTextExtentPointW (GDI32.@)
1232 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1235 TRACE("not bug compatible.\n");
1236 return GetTextExtentPoint32W( hdc, str, count, size );
1240 /***********************************************************************
1241 * GetTextExtentExPointA (GDI32.@)
1243 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1244 INT maxExt, LPINT lpnFit,
1245 LPINT alpDx, LPSIZE size )
1252 if (count < 0) return FALSE;
1253 if (maxExt < -1) return FALSE;
1257 walpDx = HeapAlloc( GetProcessHeap(), 0, count * sizeof(INT) );
1258 if (!walpDx) return FALSE;
1261 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1262 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
1265 INT n = lpnFit ? *lpnFit : wlen;
1267 for(i = 0, j = 0; i < n; i++, j++)
1269 alpDx[j] = walpDx[i];
1270 if (IsDBCSLeadByte(str[j])) alpDx[++j] = walpDx[i];
1273 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1274 HeapFree( GetProcessHeap(), 0, p );
1275 HeapFree( GetProcessHeap(), 0, walpDx );
1280 /***********************************************************************
1281 * GetTextExtentExPointW (GDI32.@)
1283 * Return the size of the string as it would be if it was output properly by
1286 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count, INT max_ext,
1287 LPINT nfit, LPINT dxs, LPSIZE size )
1292 INT buffer[256], *pos = dxs;
1294 if (count < 0) return FALSE;
1296 dc = get_dc_ptr(hdc);
1297 if (!dc) return FALSE;
1302 if (count > 256 && !(pos = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*pos) )))
1304 release_dc_ptr( dc );
1309 ret = get_char_positions( dc, str, count, pos, size );
1314 for (i = 0; i < count; i++)
1316 unsigned int dx = abs( INTERNAL_XDSTOWS( dc, pos[i] )) + (i + 1) * dc->charExtra;
1317 if (dx > (unsigned int)max_ext) break;
1318 if (dxs) dxs[i] = dx;
1320 if (nfit) *nfit = i;
1323 size->cx = abs( INTERNAL_XDSTOWS( dc, size->cx )) + count * dc->charExtra;
1324 size->cy = abs( INTERNAL_YDSTOWS( dc, size->cy ));
1327 if (pos != buffer && pos != dxs) HeapFree( GetProcessHeap(), 0, pos );
1328 release_dc_ptr( dc );
1330 TRACE("(%p, %s, %d) returning %dx%d\n", hdc, debugstr_wn(str,count), max_ext, size->cx, size->cy );
1334 /***********************************************************************
1335 * GetTextMetricsA (GDI32.@)
1337 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1341 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1342 FONT_TextMetricWToA( &tm32, metrics );
1346 /***********************************************************************
1347 * GetTextMetricsW (GDI32.@)
1349 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1353 DC * dc = get_dc_ptr( hdc );
1354 if (!dc) return FALSE;
1356 physdev = GET_DC_PHYSDEV( dc, pGetTextMetrics );
1357 ret = physdev->funcs->pGetTextMetrics( physdev, metrics );
1361 /* device layer returns values in device units
1362 * therefore we have to convert them to logical */
1364 metrics->tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1365 metrics->tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1367 #define WDPTOLP(x) ((x<0)? \
1368 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1369 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1370 #define HDPTOLP(y) ((y<0)? \
1371 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1372 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1374 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1375 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1376 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1377 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1378 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1379 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1380 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1381 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1385 TRACE("text metrics:\n"
1386 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1387 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1388 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1389 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1390 " PitchAndFamily = %02x\n"
1391 " --------------------\n"
1392 " InternalLeading = %i\n"
1396 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1397 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1398 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1399 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1400 metrics->tmPitchAndFamily,
1401 metrics->tmInternalLeading,
1404 metrics->tmHeight );
1406 release_dc_ptr( dc );
1411 /***********************************************************************
1412 * GetOutlineTextMetricsA (GDI32.@)
1413 * Gets metrics for TrueType fonts.
1416 * If the supplied buffer isn't big enough Windows partially fills it up to
1417 * its given length and returns that length.
1420 * Success: Non-zero or size of required buffer
1423 UINT WINAPI GetOutlineTextMetricsA(
1424 HDC hdc, /* [in] Handle of device context */
1425 UINT cbData, /* [in] Size of metric data array */
1426 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1428 char buf[512], *ptr;
1430 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1431 OUTLINETEXTMETRICA *output = lpOTM;
1434 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1436 if(ret > sizeof(buf))
1437 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1438 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1440 needed = sizeof(OUTLINETEXTMETRICA);
1441 if(lpOTMW->otmpFamilyName)
1442 needed += WideCharToMultiByte(CP_ACP, 0,
1443 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1444 NULL, 0, NULL, NULL);
1445 if(lpOTMW->otmpFaceName)
1446 needed += WideCharToMultiByte(CP_ACP, 0,
1447 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1448 NULL, 0, NULL, NULL);
1449 if(lpOTMW->otmpStyleName)
1450 needed += WideCharToMultiByte(CP_ACP, 0,
1451 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1452 NULL, 0, NULL, NULL);
1453 if(lpOTMW->otmpFullName)
1454 needed += WideCharToMultiByte(CP_ACP, 0,
1455 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1456 NULL, 0, NULL, NULL);
1463 TRACE("needed = %d\n", needed);
1465 /* Since the supplied buffer isn't big enough, we'll alloc one
1466 that is and memcpy the first cbData bytes into the lpOTM at
1468 output = HeapAlloc(GetProcessHeap(), 0, needed);
1470 ret = output->otmSize = min(needed, cbData);
1471 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1472 output->otmFiller = 0;
1473 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1474 output->otmfsSelection = lpOTMW->otmfsSelection;
1475 output->otmfsType = lpOTMW->otmfsType;
1476 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1477 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1478 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1479 output->otmEMSquare = lpOTMW->otmEMSquare;
1480 output->otmAscent = lpOTMW->otmAscent;
1481 output->otmDescent = lpOTMW->otmDescent;
1482 output->otmLineGap = lpOTMW->otmLineGap;
1483 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1484 output->otmsXHeight = lpOTMW->otmsXHeight;
1485 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1486 output->otmMacAscent = lpOTMW->otmMacAscent;
1487 output->otmMacDescent = lpOTMW->otmMacDescent;
1488 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1489 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1490 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1491 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1492 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1493 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1494 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1495 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1496 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1497 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1500 ptr = (char*)(output + 1);
1501 left = needed - sizeof(*output);
1503 if(lpOTMW->otmpFamilyName) {
1504 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1505 len = WideCharToMultiByte(CP_ACP, 0,
1506 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1507 ptr, left, NULL, NULL);
1511 output->otmpFamilyName = 0;
1513 if(lpOTMW->otmpFaceName) {
1514 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1515 len = WideCharToMultiByte(CP_ACP, 0,
1516 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1517 ptr, left, NULL, NULL);
1521 output->otmpFaceName = 0;
1523 if(lpOTMW->otmpStyleName) {
1524 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1525 len = WideCharToMultiByte(CP_ACP, 0,
1526 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1527 ptr, left, NULL, NULL);
1531 output->otmpStyleName = 0;
1533 if(lpOTMW->otmpFullName) {
1534 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1535 len = WideCharToMultiByte(CP_ACP, 0,
1536 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1537 ptr, left, NULL, NULL);
1540 output->otmpFullName = 0;
1544 if(output != lpOTM) {
1545 memcpy(lpOTM, output, cbData);
1546 HeapFree(GetProcessHeap(), 0, output);
1548 /* check if the string offsets really fit into the provided size */
1549 /* FIXME: should we check string length as well? */
1550 /* make sure that we don't read/write beyond the provided buffer */
1551 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(LPSTR))
1553 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1554 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1557 /* make sure that we don't read/write beyond the provided buffer */
1558 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(LPSTR))
1560 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1561 lpOTM->otmpFaceName = 0; /* doesn't fit */
1564 /* make sure that we don't read/write beyond the provided buffer */
1565 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(LPSTR))
1567 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1568 lpOTM->otmpStyleName = 0; /* doesn't fit */
1571 /* make sure that we don't read/write beyond the provided buffer */
1572 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(LPSTR))
1574 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1575 lpOTM->otmpFullName = 0; /* doesn't fit */
1580 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1581 HeapFree(GetProcessHeap(), 0, lpOTMW);
1587 /***********************************************************************
1588 * GetOutlineTextMetricsW [GDI32.@]
1590 UINT WINAPI GetOutlineTextMetricsW(
1591 HDC hdc, /* [in] Handle of device context */
1592 UINT cbData, /* [in] Size of metric data array */
1593 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1595 DC *dc = get_dc_ptr( hdc );
1596 OUTLINETEXTMETRICW *output = lpOTM;
1600 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1603 dev = GET_DC_PHYSDEV( dc, pGetOutlineTextMetrics );
1604 ret = dev->funcs->pGetOutlineTextMetrics( dev, cbData, output );
1606 if (lpOTM && ret > cbData)
1608 output = HeapAlloc(GetProcessHeap(), 0, ret);
1609 ret = dev->funcs->pGetOutlineTextMetrics( dev, ret, output );
1614 output->otmTextMetrics.tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1615 output->otmTextMetrics.tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1617 #define WDPTOLP(x) ((x<0)? \
1618 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1619 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1620 #define HDPTOLP(y) ((y<0)? \
1621 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1622 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1624 output->otmTextMetrics.tmHeight = HDPTOLP(output->otmTextMetrics.tmHeight);
1625 output->otmTextMetrics.tmAscent = HDPTOLP(output->otmTextMetrics.tmAscent);
1626 output->otmTextMetrics.tmDescent = HDPTOLP(output->otmTextMetrics.tmDescent);
1627 output->otmTextMetrics.tmInternalLeading = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1628 output->otmTextMetrics.tmExternalLeading = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1629 output->otmTextMetrics.tmAveCharWidth = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1630 output->otmTextMetrics.tmMaxCharWidth = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1631 output->otmTextMetrics.tmOverhang = WDPTOLP(output->otmTextMetrics.tmOverhang);
1632 output->otmAscent = HDPTOLP(output->otmAscent);
1633 output->otmDescent = HDPTOLP(output->otmDescent);
1634 output->otmLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmLineGap));
1635 output->otmsCapEmHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsCapEmHeight));
1636 output->otmsXHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsXHeight));
1637 output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1638 output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1639 output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1640 output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1641 output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1642 output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1643 output->otmMacLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmMacLineGap));
1644 output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1645 output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1646 output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1647 output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1648 output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1649 output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1650 output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1651 output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1652 output->otmsStrikeoutSize = abs(INTERNAL_YDSTOWS(dc,output->otmsStrikeoutSize));
1653 output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1654 output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1655 output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1660 memcpy(lpOTM, output, cbData);
1661 HeapFree(GetProcessHeap(), 0, output);
1669 static LPSTR FONT_GetCharsByRangeA(HDC hdc, UINT firstChar, UINT lastChar, PINT pByteLen)
1671 INT i, count = lastChar - firstChar + 1;
1679 mbcp = GdiGetCodePage(hdc);
1687 if (lastChar > 0xffff)
1689 if ((firstChar ^ lastChar) > 0xff)
1693 if (lastChar > 0xff)
1699 str = HeapAlloc(GetProcessHeap(), 0, count * 2 + 1);
1703 for(i = 0, c = firstChar; c <= lastChar; i++, c++)
1707 str[i++] = (BYTE)(c >> 8);
1708 if (c <= 0xff && IsDBCSLeadByteEx(mbcp, c))
1709 str[i] = 0x1f; /* FIXME: use default character */
1723 /***********************************************************************
1724 * GetCharWidthW (GDI32.@)
1725 * GetCharWidth32W (GDI32.@)
1727 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1733 DC * dc = get_dc_ptr( hdc );
1735 if (!dc) return FALSE;
1737 dev = GET_DC_PHYSDEV( dc, pGetCharWidth );
1738 ret = dev->funcs->pGetCharWidth( dev, firstChar, lastChar, buffer );
1742 /* convert device units to logical */
1743 for( i = firstChar; i <= lastChar; i++, buffer++ )
1744 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1746 release_dc_ptr( dc );
1751 /***********************************************************************
1752 * GetCharWidthA (GDI32.@)
1753 * GetCharWidth32A (GDI32.@)
1755 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1763 str = FONT_GetCharsByRangeA(hdc, firstChar, lastChar, &i);
1767 wstr = FONT_mbtowc(hdc, str, i, &wlen, NULL);
1769 for(i = 0; i < wlen; i++)
1771 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1779 HeapFree(GetProcessHeap(), 0, str);
1780 HeapFree(GetProcessHeap(), 0, wstr);
1786 /* helper for nulldrv_ExtTextOut */
1787 static DWORD get_glyph_bitmap( HDC hdc, UINT index, UINT flags, UINT aa_flags,
1788 GLYPHMETRICS *metrics, struct gdi_image_bits *image )
1790 static const MAT2 identity = { {0,1}, {0,0}, {0,0}, {0,1} };
1791 UINT indices[3] = {0, 0, 0x20};
1797 if (flags & ETO_GLYPH_INDEX) aa_flags |= GGO_GLYPH_INDEX;
1799 for (i = 0; i < sizeof(indices) / sizeof(indices[0]); i++)
1802 ret = GetGlyphOutlineW( hdc, index, aa_flags, metrics, 0, NULL, &identity );
1803 if (ret != GDI_ERROR) break;
1806 if (ret == GDI_ERROR) return ERROR_NOT_FOUND;
1807 if (!image) return ERROR_SUCCESS;
1811 if (!ret) return ERROR_SUCCESS; /* empty glyph */
1813 stride = get_dib_stride( metrics->gmBlackBoxX, 1 );
1814 size = metrics->gmBlackBoxY * stride;
1816 if (!(image->ptr = HeapAlloc( GetProcessHeap(), 0, size ))) return ERROR_OUTOFMEMORY;
1817 image->is_copy = TRUE;
1818 image->free = free_heap_bits;
1820 ret = GetGlyphOutlineW( hdc, index, aa_flags, metrics, size, image->ptr, &identity );
1821 if (ret == GDI_ERROR)
1823 HeapFree( GetProcessHeap(), 0, image->ptr );
1824 return ERROR_NOT_FOUND;
1826 return ERROR_SUCCESS;
1829 /* helper for nulldrv_ExtTextOut */
1830 static RECT get_total_extents( HDC hdc, INT x, INT y, UINT flags, UINT aa_flags,
1831 LPCWSTR str, UINT count, const INT *dx )
1836 reset_bounds( &bounds );
1837 for (i = 0; i < count; i++)
1839 GLYPHMETRICS metrics;
1841 if (get_glyph_bitmap( hdc, str[i], flags, aa_flags, &metrics, NULL )) continue;
1843 rect.left = x + metrics.gmptGlyphOrigin.x;
1844 rect.top = y - metrics.gmptGlyphOrigin.y;
1845 rect.right = rect.left + metrics.gmBlackBoxX;
1846 rect.bottom = rect.top + metrics.gmBlackBoxY;
1847 add_bounds_rect( &bounds, &rect );
1851 if (flags & ETO_PDY)
1854 y += dx[ i * 2 + 1];
1860 x += metrics.gmCellIncX;
1861 y += metrics.gmCellIncY;
1867 /* helper for nulldrv_ExtTextOut */
1868 static void draw_glyph( HDC hdc, INT origin_x, INT origin_y, const GLYPHMETRICS *metrics,
1869 const struct gdi_image_bits *image, const RECT *clip )
1871 static const BYTE masks[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
1872 UINT i, count, max_count;
1874 BYTE *ptr = image->ptr;
1875 int stride = get_dib_stride( metrics->gmBlackBoxX, 1 );
1877 RECT rect, clipped_rect;
1879 rect.left = origin_x + metrics->gmptGlyphOrigin.x;
1880 rect.top = origin_y - metrics->gmptGlyphOrigin.y;
1881 rect.right = rect.left + metrics->gmBlackBoxX;
1882 rect.bottom = rect.top + metrics->gmBlackBoxY;
1883 if (!clip) clipped_rect = rect;
1884 else if (!intersect_rect( &clipped_rect, &rect, clip )) return;
1886 max_count = (metrics->gmBlackBoxX + 1) * metrics->gmBlackBoxY;
1887 pts = HeapAlloc( GetProcessHeap(), 0, max_count * sizeof(*pts) );
1891 ptr += (clipped_rect.top - rect.top) * stride;
1892 for (y = clipped_rect.top; y < clipped_rect.bottom; y++, ptr += stride)
1894 for (x = clipped_rect.left - rect.left; x < clipped_rect.right - rect.left; x++)
1896 while (x < clipped_rect.right - rect.left && !(ptr[x / 8] & masks[x % 8])) x++;
1897 pts[count].x = rect.left + x;
1898 while (x < clipped_rect.right - rect.left && (ptr[x / 8] & masks[x % 8])) x++;
1899 pts[count + 1].x = rect.left + x;
1900 if (pts[count + 1].x > pts[count].x)
1902 pts[count].y = pts[count + 1].y = y;
1907 assert( count <= max_count );
1908 DPtoLP( hdc, pts, count );
1909 for (i = 0; i < count; i += 2) Polyline( hdc, pts + i, 2 );
1910 HeapFree( GetProcessHeap(), 0, pts );
1913 /***********************************************************************
1914 * nulldrv_ExtTextOut
1916 BOOL nulldrv_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags, const RECT *rect,
1917 LPCWSTR str, UINT count, const INT *dx )
1919 DC *dc = get_nulldrv_dc( dev );
1925 if (flags & ETO_OPAQUE)
1928 HBRUSH brush = CreateSolidBrush( GetNearestColor( dev->hdc, GetBkColor(dev->hdc) ));
1932 orig = SelectObject( dev->hdc, brush );
1933 DPtoLP( dev->hdc, (POINT *)&rc, 2 );
1934 PatBlt( dev->hdc, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, PATCOPY );
1935 SelectObject( dev->hdc, orig );
1936 DeleteObject( brush );
1940 if (!count) return TRUE;
1942 if (dc->aa_flags != GGO_BITMAP)
1944 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1945 BITMAPINFO *info = (BITMAPINFO *)buffer;
1946 struct gdi_image_bits bits;
1947 struct bitblt_coords src, dst;
1949 /* FIXME Subpixel modes */
1950 UINT aa_flags = GGO_GRAY4_BITMAP;
1952 dst_dev = GET_DC_PHYSDEV( dc, pPutImage );
1953 src.visrect = get_total_extents( dev->hdc, x, y, flags, aa_flags, str, count, dx );
1954 if (flags & ETO_CLIPPED) intersect_rect( &src.visrect, &src.visrect, rect );
1955 if (!clip_visrect( dc, &src.visrect, &src.visrect )) return TRUE;
1957 /* FIXME: check for ETO_OPAQUE and avoid GetImage */
1958 src.x = src.visrect.left;
1959 src.y = src.visrect.top;
1960 src.width = src.visrect.right - src.visrect.left;
1961 src.height = src.visrect.bottom - src.visrect.top;
1963 if ((flags & ETO_OPAQUE) && (src.visrect.left >= rect->left) && (src.visrect.top >= rect->top) &&
1964 (src.visrect.right <= rect->right) && (src.visrect.bottom <= rect->bottom))
1966 /* we can avoid the GetImage, just query the needed format */
1967 memset( &info->bmiHeader, 0, sizeof(info->bmiHeader) );
1968 info->bmiHeader.biSize = sizeof(info->bmiHeader);
1969 info->bmiHeader.biWidth = src.width;
1970 info->bmiHeader.biHeight = -src.height;
1971 err = dst_dev->funcs->pPutImage( dst_dev, 0, info, NULL, NULL, NULL, 0 );
1972 if (!err || err == ERROR_BAD_FORMAT)
1974 /* make the source rectangle relative to the source bits */
1976 src.visrect.left = src.visrect.top = 0;
1977 src.visrect.right = src.width;
1978 src.visrect.bottom = src.height;
1980 bits.ptr = HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( info ));
1981 if (!bits.ptr) return ERROR_OUTOFMEMORY;
1982 bits.is_copy = TRUE;
1983 bits.free = free_heap_bits;
1984 err = ERROR_SUCCESS;
1989 PHYSDEV src_dev = GET_DC_PHYSDEV( dc, pGetImage );
1990 err = src_dev->funcs->pGetImage( src_dev, info, &bits, &src );
1991 if (!err && !bits.is_copy)
1993 void *ptr = HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( info ));
1996 if (bits.free) bits.free( &bits );
1997 return ERROR_OUTOFMEMORY;
1999 memcpy( ptr, bits.ptr, get_dib_image_size( info ));
2000 if (bits.free) bits.free( &bits );
2002 bits.is_copy = TRUE;
2003 bits.free = free_heap_bits;
2008 /* make x,y relative to the image bits */
2009 x += src.visrect.left - dst.visrect.left;
2010 y += src.visrect.top - dst.visrect.top;
2011 render_aa_text_bitmapinfo( dev->hdc, info, &bits, &src, x, y, flags,
2012 aa_flags, str, count, dx );
2013 err = dst_dev->funcs->pPutImage( dst_dev, 0, info, &bits, &src, &dst, SRCCOPY );
2014 if (bits.free) bits.free( &bits );
2019 pen = CreatePen( PS_SOLID, 1, GetTextColor(dev->hdc) );
2020 orig = SelectObject( dev->hdc, pen );
2022 for (i = 0; i < count; i++)
2024 GLYPHMETRICS metrics;
2025 struct gdi_image_bits image;
2027 err = get_glyph_bitmap( dev->hdc, str[i], flags, GGO_BITMAP, &metrics, &image );
2030 if (image.ptr) draw_glyph( dev->hdc, x, y, &metrics, &image, (flags & ETO_CLIPPED) ? rect : NULL );
2031 if (image.free) image.free( &image );
2035 if (flags & ETO_PDY)
2038 y += dx[ i * 2 + 1];
2044 x += metrics.gmCellIncX;
2045 y += metrics.gmCellIncY;
2049 SelectObject( dev->hdc, orig );
2050 DeleteObject( pen );
2055 /***********************************************************************
2056 * ExtTextOutA (GDI32.@)
2060 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
2061 const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
2069 if (flags & ETO_GLYPH_INDEX)
2070 return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
2072 p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
2075 unsigned int i = 0, j = 0;
2077 /* allocate enough for a ETO_PDY */
2078 lpDxW = HeapAlloc( GetProcessHeap(), 0, 2*wlen*sizeof(INT));
2080 if(IsDBCSLeadByteEx(codepage, str[i]))
2084 lpDxW[j++] = lpDx[i * 2] + lpDx[(i + 1) * 2];
2085 lpDxW[j++] = lpDx[i * 2 + 1] + lpDx[(i + 1) * 2 + 1];
2088 lpDxW[j++] = lpDx[i] + lpDx[i + 1];
2095 lpDxW[j++] = lpDx[i * 2];
2096 lpDxW[j++] = lpDx[i * 2 + 1];
2099 lpDxW[j++] = lpDx[i];
2105 ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
2107 HeapFree( GetProcessHeap(), 0, p );
2108 HeapFree( GetProcessHeap(), 0, lpDxW );
2113 /***********************************************************************
2114 * ExtTextOutW (GDI32.@)
2116 * Draws text using the currently selected font, background color, and text color.
2120 * x,y [I] coordinates of string
2122 * ETO_GRAYED - undocumented on MSDN
2123 * ETO_OPAQUE - use background color for fill the rectangle
2124 * ETO_CLIPPED - clipping text to the rectangle
2125 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
2126 * than encoded characters. Implies ETO_IGNORELANGUAGE
2127 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
2128 * Affects BiDi ordering
2129 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
2130 * ETO_PDY - unimplemented
2131 * ETO_NUMERICSLATIN - unimplemented always assumed -
2132 * do not translate numbers into locale representations
2133 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
2134 * lprect [I] dimensions for clipping or/and opaquing
2135 * str [I] text string
2136 * count [I] number of symbols in string
2137 * lpDx [I] optional parameter with distance between drawing characters
2143 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
2144 const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
2147 LPWSTR reordered_str = (LPWSTR)str;
2148 WORD *glyphs = NULL;
2149 UINT align = GetTextAlign( hdc );
2150 DWORD layout = GetLayout( hdc );
2154 double cosEsc, sinEsc;
2158 POINT *deltas = NULL, width = {0, 0};
2160 DC * dc = get_dc_ptr( hdc );
2163 static int quietfixme = 0;
2165 if (!dc) return FALSE;
2167 breakRem = dc->breakRem;
2169 if (quietfixme == 0 && flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN))
2171 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN unimplemented\n");
2176 physdev = GET_DC_PHYSDEV( dc, pExtTextOut );
2177 type = GetObjectType(hdc);
2178 if(type == OBJ_METADC || type == OBJ_ENHMETADC)
2180 ret = physdev->funcs->pExtTextOut( physdev, x, y, flags, lprect, str, count, lpDx );
2181 release_dc_ptr( dc );
2185 if (flags & ETO_RTLREADING) align |= TA_RTLREADING;
2186 if (layout & LAYOUT_RTL)
2188 if ((align & TA_CENTER) != TA_CENTER) align ^= TA_RIGHT;
2189 align ^= TA_RTLREADING;
2192 if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && count > 0 )
2195 reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
2197 BIDI_Reorder( hdc, str, count, GCP_REORDER,
2198 (align & TA_RTLREADING) ? WINE_GCPW_FORCE_RTL : WINE_GCPW_FORCE_LTR,
2199 reordered_str, count, NULL, &glyphs, &cGlyphs);
2201 flags |= ETO_IGNORELANGUAGE;
2204 flags |= ETO_GLYPH_INDEX;
2205 if (cGlyphs != count)
2209 else if(flags & ETO_GLYPH_INDEX)
2210 glyphs = reordered_str;
2212 TRACE("%p, %d, %d, %08x, %s, %s, %d, %p)\n", hdc, x, y, flags,
2213 wine_dbgstr_rect(lprect), debugstr_wn(str, count), count, lpDx);
2214 TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
2216 if(align & TA_UPDATECP)
2218 GetCurrentPositionEx( hdc, &pt );
2223 GetTextMetricsW(hdc, &tm);
2224 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
2226 if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
2227 lf.lfEscapement = 0;
2229 if ((dc->GraphicsMode == GM_COMPATIBLE) &&
2230 (dc->vport2WorldValid && dc->xformWorld2Vport.eM11 * dc->xformWorld2Vport.eM22 < 0))
2232 lf.lfEscapement = -lf.lfEscapement;
2235 if(lf.lfEscapement != 0)
2237 cosEsc = cos(lf.lfEscapement * M_PI / 1800);
2238 sinEsc = sin(lf.lfEscapement * M_PI / 1800);
2249 LPtoDP(hdc, (POINT*)&rc, 2);
2251 if (flags & ETO_OPAQUE)
2252 physdev->funcs->pExtTextOut( physdev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL );
2254 else flags &= ~ETO_CLIPPED;
2264 LPtoDP(hdc, &pt, 1);
2268 char_extra = GetTextCharacterExtra(hdc);
2269 if(char_extra || dc->breakExtra || breakRem || lpDx || lf.lfEscapement != 0)
2272 POINT total = {0, 0}, desired[2];
2274 deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
2277 if (flags & ETO_PDY)
2279 for (i = 0; i < count; i++)
2281 deltas[i].x = lpDx[i * 2] + char_extra;
2282 deltas[i].y = -lpDx[i * 2 + 1];
2287 for (i = 0; i < count; i++)
2289 deltas[i].x = lpDx[i] + char_extra;
2296 INT *dx = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*dx) );
2298 if (flags & ETO_GLYPH_INDEX)
2299 GetTextExtentExPointI( hdc, glyphs, count, -1, NULL, dx, &sz );
2301 GetTextExtentExPointW( hdc, reordered_str, count, -1, NULL, dx, &sz );
2303 deltas[0].x = dx[0];
2305 for (i = 1; i < count; i++)
2307 deltas[i].x = dx[i] - dx[i - 1];
2310 HeapFree( GetProcessHeap(), 0, dx );
2313 for(i = 0; i < count; i++)
2315 total.x += deltas[i].x;
2316 total.y += deltas[i].y;
2318 desired[0].x = desired[0].y = 0;
2320 desired[1].x = cosEsc * total.x + sinEsc * total.y;
2321 desired[1].y = -sinEsc * total.x + cosEsc * total.y;
2323 LPtoDP(hdc, desired, 2);
2324 desired[1].x -= desired[0].x;
2325 desired[1].y -= desired[0].y;
2327 if (dc->GraphicsMode == GM_COMPATIBLE)
2329 if (dc->vport2WorldValid && dc->xformWorld2Vport.eM11 < 0)
2330 desired[1].x = -desired[1].x;
2331 if (dc->vport2WorldValid && dc->xformWorld2Vport.eM22 < 0)
2332 desired[1].y = -desired[1].y;
2335 deltas[i].x = desired[1].x - width.x;
2336 deltas[i].y = desired[1].y - width.y;
2346 if(flags & ETO_GLYPH_INDEX)
2347 GetTextExtentPointI(hdc, glyphs, count, &sz);
2349 GetTextExtentPointW(hdc, reordered_str, count, &sz);
2350 desired[0].x = desired[0].y = 0;
2351 desired[1].x = sz.cx;
2353 LPtoDP(hdc, desired, 2);
2354 desired[1].x -= desired[0].x;
2355 desired[1].y -= desired[0].y;
2357 if (dc->GraphicsMode == GM_COMPATIBLE)
2359 if (dc->vport2WorldValid && dc->xformWorld2Vport.eM11 < 0)
2360 desired[1].x = -desired[1].x;
2361 if (dc->vport2WorldValid && dc->xformWorld2Vport.eM22 < 0)
2362 desired[1].y = -desired[1].y;
2367 tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
2368 tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
2369 switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
2372 if (align & TA_UPDATECP)
2376 DPtoLP(hdc, &pt, 1);
2377 MoveToEx(hdc, pt.x, pt.y, NULL);
2389 if (align & TA_UPDATECP)
2393 DPtoLP(hdc, &pt, 1);
2394 MoveToEx(hdc, pt.x, pt.y, NULL);
2399 switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
2402 y += tm.tmAscent * cosEsc;
2403 x += tm.tmAscent * sinEsc;
2407 y -= tm.tmDescent * cosEsc;
2408 x -= tm.tmDescent * sinEsc;
2415 if (GetBkMode(hdc) != TRANSPARENT)
2417 if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
2419 if(!(flags & ETO_OPAQUE) || !lprect ||
2420 x < rc.left || x + width.x >= rc.right ||
2421 y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
2425 text_box.right = x + width.x;
2426 text_box.top = y - tm.tmAscent;
2427 text_box.bottom = y + tm.tmDescent;
2429 if (flags & ETO_CLIPPED) intersect_rect( &text_box, &text_box, &rc );
2430 if (!is_rect_empty( &text_box ))
2431 physdev->funcs->pExtTextOut( physdev, 0, 0, ETO_OPAQUE, &text_box, NULL, 0, NULL );
2436 ret = physdev->funcs->pExtTextOut( physdev, x, y, (flags & ~ETO_OPAQUE), &rc,
2437 glyphs ? glyphs : reordered_str, count, (INT*)deltas );
2440 HeapFree(GetProcessHeap(), 0, deltas);
2441 if(glyphs != reordered_str)
2442 HeapFree(GetProcessHeap(), 0, glyphs);
2443 if(reordered_str != str)
2444 HeapFree(GetProcessHeap(), 0, reordered_str);
2446 release_dc_ptr( dc );
2448 if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2450 int underlinePos, strikeoutPos;
2451 int underlineWidth, strikeoutWidth;
2452 UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2453 OUTLINETEXTMETRICW* otm = NULL;
2455 HPEN hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2456 HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2458 hbrush = SelectObject(hdc, hbrush);
2463 underlineWidth = tm.tmAscent / 20 + 1;
2464 strikeoutPos = tm.tmAscent / 2;
2465 strikeoutWidth = underlineWidth;
2469 otm = HeapAlloc(GetProcessHeap(), 0, size);
2470 GetOutlineTextMetricsW(hdc, size, otm);
2471 underlinePos = abs( INTERNAL_YWSTODS( dc, otm->otmsUnderscorePosition ));
2472 if (otm->otmsUnderscorePosition < 0) underlinePos = -underlinePos;
2473 underlineWidth = abs( INTERNAL_YWSTODS( dc, otm->otmsUnderscoreSize ));
2474 if (otm->otmsUnderscoreSize < 0) underlineWidth = -underlineWidth;
2475 strikeoutPos = abs( INTERNAL_YWSTODS( dc, otm->otmsStrikeoutPosition ));
2476 if (otm->otmsStrikeoutPosition < 0) strikeoutPos = -strikeoutPos;
2477 strikeoutWidth = abs( INTERNAL_YWSTODS( dc, otm->otmsStrikeoutSize ));
2478 HeapFree(GetProcessHeap(), 0, otm);
2484 pts[0].x = x - (underlinePos + underlineWidth / 2) * sinEsc;
2485 pts[0].y = y - (underlinePos + underlineWidth / 2) * cosEsc;
2486 pts[1].x = x + width.x - (underlinePos + underlineWidth / 2) * sinEsc;
2487 pts[1].y = y + width.y - (underlinePos + underlineWidth / 2) * cosEsc;
2488 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2489 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2490 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2491 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2492 pts[4].x = pts[0].x;
2493 pts[4].y = pts[0].y;
2494 DPtoLP(hdc, pts, 5);
2495 Polygon(hdc, pts, 5);
2500 pts[0].x = x - (strikeoutPos + strikeoutWidth / 2) * sinEsc;
2501 pts[0].y = y - (strikeoutPos + strikeoutWidth / 2) * cosEsc;
2502 pts[1].x = x + width.x - (strikeoutPos + strikeoutWidth / 2) * sinEsc;
2503 pts[1].y = y + width.y - (strikeoutPos + strikeoutWidth / 2) * cosEsc;
2504 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2505 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2506 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2507 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2508 pts[4].x = pts[0].x;
2509 pts[4].y = pts[0].y;
2510 DPtoLP(hdc, pts, 5);
2511 Polygon(hdc, pts, 5);
2514 SelectObject(hdc, hpen);
2515 hbrush = SelectObject(hdc, hbrush);
2516 DeleteObject(hbrush);
2523 /***********************************************************************
2524 * TextOutA (GDI32.@)
2526 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2528 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2532 /***********************************************************************
2533 * TextOutW (GDI32.@)
2535 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2537 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2541 /***********************************************************************
2542 * PolyTextOutA (GDI32.@)
2546 BOOL WINAPI PolyTextOutA( HDC hdc, const POLYTEXTA *pptxt, INT cStrings )
2548 for (; cStrings>0; cStrings--, pptxt++)
2549 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2556 /***********************************************************************
2557 * PolyTextOutW (GDI32.@)
2559 * Draw several Strings
2565 BOOL WINAPI PolyTextOutW( HDC hdc, const POLYTEXTW *pptxt, INT cStrings )
2567 for (; cStrings>0; cStrings--, pptxt++)
2568 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2574 /***********************************************************************
2575 * SetMapperFlags (GDI32.@)
2577 DWORD WINAPI SetMapperFlags( HDC hdc, DWORD flags )
2579 DC *dc = get_dc_ptr( hdc );
2580 DWORD ret = GDI_ERROR;
2584 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetMapperFlags );
2585 flags = physdev->funcs->pSetMapperFlags( physdev, flags );
2586 if (flags != GDI_ERROR)
2588 ret = dc->mapperFlags;
2589 dc->mapperFlags = flags;
2591 release_dc_ptr( dc );
2596 /***********************************************************************
2597 * GetAspectRatioFilterEx (GDI32.@)
2599 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2601 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2606 /***********************************************************************
2607 * GetCharABCWidthsA (GDI32.@)
2609 * See GetCharABCWidthsW.
2611 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2619 str = FONT_GetCharsByRangeA(hdc, firstChar, lastChar, &i);
2623 wstr = FONT_mbtowc(hdc, str, i, &wlen, NULL);
2626 HeapFree(GetProcessHeap(), 0, str);
2630 for(i = 0; i < wlen; i++)
2632 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2640 HeapFree(GetProcessHeap(), 0, str);
2641 HeapFree(GetProcessHeap(), 0, wstr);
2647 /******************************************************************************
2648 * GetCharABCWidthsW [GDI32.@]
2650 * Retrieves widths of characters in range.
2653 * hdc [I] Handle of device context
2654 * firstChar [I] First character in range to query
2655 * lastChar [I] Last character in range to query
2656 * abc [O] Address of character-width structure
2659 * Only works with TrueType fonts
2665 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2668 DC *dc = get_dc_ptr(hdc);
2674 if (!dc) return FALSE;
2678 release_dc_ptr( dc );
2682 /* unlike GetCharABCWidthsFloatW, this one is supposed to fail on non-scalable fonts */
2683 dev = GET_DC_PHYSDEV( dc, pGetTextMetrics );
2684 if (!dev->funcs->pGetTextMetrics( dev, &tm ) || !(tm.tmPitchAndFamily & TMPF_VECTOR))
2686 release_dc_ptr( dc );
2690 dev = GET_DC_PHYSDEV( dc, pGetCharABCWidths );
2691 ret = dev->funcs->pGetCharABCWidths( dev, firstChar, lastChar, abc );
2694 /* convert device units to logical */
2695 for( i = firstChar; i <= lastChar; i++, abc++ ) {
2696 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2697 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2698 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2702 release_dc_ptr( dc );
2707 /******************************************************************************
2708 * GetCharABCWidthsI [GDI32.@]
2710 * Retrieves widths of characters in range.
2713 * hdc [I] Handle of device context
2714 * firstChar [I] First glyphs in range to query
2715 * count [I] Last glyphs in range to query
2716 * pgi [i] Array of glyphs to query
2717 * abc [O] Address of character-width structure
2720 * Only works with TrueType fonts
2726 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2727 LPWORD pgi, LPABC abc)
2729 DC *dc = get_dc_ptr(hdc);
2734 if (!dc) return FALSE;
2738 release_dc_ptr( dc );
2742 dev = GET_DC_PHYSDEV( dc, pGetCharABCWidthsI );
2743 ret = dev->funcs->pGetCharABCWidthsI( dev, firstChar, count, pgi, abc );
2746 /* convert device units to logical */
2747 for( i = 0; i < count; i++, abc++ ) {
2748 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2749 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2750 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2754 release_dc_ptr( dc );
2759 /***********************************************************************
2760 * GetGlyphOutlineA (GDI32.@)
2762 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2763 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2764 LPVOID lpBuffer, const MAT2 *lpmat2 )
2766 if (!lpmat2) return GDI_ERROR;
2768 if(!(fuFormat & GGO_GLYPH_INDEX)) {
2773 cp = GdiGetCodePage(hdc);
2774 if (IsDBCSLeadByteEx(cp, uChar >> 8)) {
2776 mbchs[0] = (uChar & 0xff00) >> 8;
2777 mbchs[1] = (uChar & 0xff);
2780 mbchs[0] = (uChar & 0xff);
2783 MultiByteToWideChar(cp, 0, mbchs, len, (LPWSTR)&uChar, 1);
2786 return GetGlyphOutlineW(hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer,
2790 /***********************************************************************
2791 * GetGlyphOutlineW (GDI32.@)
2793 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2794 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2795 LPVOID lpBuffer, const MAT2 *lpmat2 )
2801 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2802 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2804 if (!lpmat2) return GDI_ERROR;
2806 dc = get_dc_ptr(hdc);
2807 if(!dc) return GDI_ERROR;
2809 dev = GET_DC_PHYSDEV( dc, pGetGlyphOutline );
2810 ret = dev->funcs->pGetGlyphOutline( dev, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2811 release_dc_ptr( dc );
2816 /***********************************************************************
2817 * CreateScalableFontResourceA (GDI32.@)
2819 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2820 LPCSTR lpszResourceFile,
2821 LPCSTR lpszFontFile,
2822 LPCSTR lpszCurrentPath )
2824 LPWSTR lpszResourceFileW = NULL;
2825 LPWSTR lpszFontFileW = NULL;
2826 LPWSTR lpszCurrentPathW = NULL;
2830 if (lpszResourceFile)
2832 len = MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, NULL, 0);
2833 lpszResourceFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2834 MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, lpszResourceFileW, len);
2839 len = MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, NULL, 0);
2840 lpszFontFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2841 MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, lpszFontFileW, len);
2844 if (lpszCurrentPath)
2846 len = MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, NULL, 0);
2847 lpszCurrentPathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2848 MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, lpszCurrentPathW, len);
2851 ret = CreateScalableFontResourceW(fHidden, lpszResourceFileW,
2852 lpszFontFileW, lpszCurrentPathW);
2854 HeapFree(GetProcessHeap(), 0, lpszResourceFileW);
2855 HeapFree(GetProcessHeap(), 0, lpszFontFileW);
2856 HeapFree(GetProcessHeap(), 0, lpszCurrentPathW);
2861 /***********************************************************************
2862 * CreateScalableFontResourceW (GDI32.@)
2864 BOOL WINAPI CreateScalableFontResourceW( DWORD hidden, LPCWSTR resource_file,
2865 LPCWSTR font_file, LPCWSTR font_path )
2867 TRACE("(%d, %s, %s, %s)\n", hidden, debugstr_w(resource_file),
2868 debugstr_w(font_file), debugstr_w(font_path) );
2870 return WineEngCreateScalableFontResource( hidden, resource_file,
2871 font_file, font_path );
2874 /*************************************************************************
2875 * GetKerningPairsA (GDI32.@)
2877 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2878 LPKERNINGPAIR kern_pairA )
2882 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2883 KERNINGPAIR *kern_pairW;
2885 if (!cPairs && kern_pairA)
2887 SetLastError(ERROR_INVALID_PARAMETER);
2891 cp = GdiGetCodePage(hDC);
2893 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2894 * to fail on an invalid character for CP_SYMBOL.
2896 cpi.DefaultChar[0] = 0;
2897 if (cp != CP_SYMBOL && !GetCPInfo(cp, &cpi))
2899 FIXME("Can't find codepage %u info\n", cp);
2903 total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2904 if (!total_kern_pairs) return 0;
2906 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2907 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2909 for (i = 0; i < total_kern_pairs; i++)
2913 if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2916 if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2919 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2924 if (kern_pairs_copied >= cPairs) break;
2926 kern_pairA->wFirst = (BYTE)first;
2927 kern_pairA->wSecond = (BYTE)second;
2928 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2931 kern_pairs_copied++;
2934 HeapFree(GetProcessHeap(), 0, kern_pairW);
2936 return kern_pairs_copied;
2939 /*************************************************************************
2940 * GetKerningPairsW (GDI32.@)
2942 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2943 LPKERNINGPAIR lpKerningPairs )
2949 TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2951 if (!cPairs && lpKerningPairs)
2953 SetLastError(ERROR_INVALID_PARAMETER);
2957 dc = get_dc_ptr(hDC);
2960 dev = GET_DC_PHYSDEV( dc, pGetKerningPairs );
2961 ret = dev->funcs->pGetKerningPairs( dev, cPairs, lpKerningPairs );
2962 release_dc_ptr( dc );
2966 /*************************************************************************
2967 * TranslateCharsetInfo [GDI32.@]
2969 * Fills a CHARSETINFO structure for a character set, code page, or
2970 * font. This allows making the correspondence between different labels
2971 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2972 * of the same encoding.
2974 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2975 * only one codepage should be set in *lpSrc.
2978 * TRUE on success, FALSE on failure.
2981 BOOL WINAPI TranslateCharsetInfo(
2982 LPDWORD lpSrc, /* [in]
2983 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2984 if flags == TCI_SRCCHARSET: a character set value
2985 if flags == TCI_SRCCODEPAGE: a code page value
2987 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2988 DWORD flags /* [in] determines interpretation of lpSrc */)
2992 case TCI_SRCFONTSIG:
2993 while (index < MAXTCIINDEX && !(*lpSrc>>index & 0x0001)) index++;
2995 case TCI_SRCCODEPAGE:
2996 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciACP) index++;
2998 case TCI_SRCCHARSET:
2999 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciCharset) index++;
3004 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
3005 *lpCs = FONT_tci[index];
3009 /*************************************************************************
3010 * GetFontLanguageInfo (GDI32.@)
3012 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
3014 FONTSIGNATURE fontsig;
3015 static const DWORD GCP_DBCS_MASK=0x003F0000,
3016 GCP_DIACRITIC_MASK=0x00000000,
3017 FLI_GLYPHS_MASK=0x00000000,
3018 GCP_GLYPHSHAPE_MASK=0x00000040,
3019 GCP_KASHIDA_MASK=0x00000000,
3020 GCP_LIGATE_MASK=0x00000000,
3021 GCP_USEKERNING_MASK=0x00000000,
3022 GCP_REORDER_MASK=0x00000060;
3026 GetTextCharsetInfo( hdc, &fontsig, 0 );
3027 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
3029 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
3032 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
3033 result|=GCP_DIACRITIC;
3035 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
3038 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
3039 result|=GCP_GLYPHSHAPE;
3041 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
3042 result|=GCP_KASHIDA;
3044 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
3047 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
3048 result|=GCP_USEKERNING;
3050 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
3051 if( GetTextAlign( hdc) & TA_RTLREADING )
3052 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
3053 result|=GCP_REORDER;
3059 /*************************************************************************
3060 * GetFontData [GDI32.@]
3062 * Retrieve data for TrueType font.
3066 * success: Number of bytes returned
3067 * failure: GDI_ERROR
3071 * Calls SetLastError()
3074 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
3075 LPVOID buffer, DWORD length)
3077 DC *dc = get_dc_ptr(hdc);
3081 if(!dc) return GDI_ERROR;
3083 dev = GET_DC_PHYSDEV( dc, pGetFontData );
3084 ret = dev->funcs->pGetFontData( dev, table, offset, buffer, length );
3085 release_dc_ptr( dc );
3089 /*************************************************************************
3090 * GetGlyphIndicesA [GDI32.@]
3092 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
3093 LPWORD pgi, DWORD flags)
3099 TRACE("(%p, %s, %d, %p, 0x%x)\n",
3100 hdc, debugstr_an(lpstr, count), count, pgi, flags);
3102 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
3103 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
3104 HeapFree(GetProcessHeap(), 0, lpstrW);
3109 /*************************************************************************
3110 * GetGlyphIndicesW [GDI32.@]
3112 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
3113 LPWORD pgi, DWORD flags)
3115 DC *dc = get_dc_ptr(hdc);
3119 TRACE("(%p, %s, %d, %p, 0x%x)\n",
3120 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
3122 if(!dc) return GDI_ERROR;
3124 dev = GET_DC_PHYSDEV( dc, pGetGlyphIndices );
3125 ret = dev->funcs->pGetGlyphIndices( dev, lpstr, count, pgi, flags );
3126 release_dc_ptr( dc );
3130 /*************************************************************************
3131 * GetCharacterPlacementA [GDI32.@]
3133 * See GetCharacterPlacementW.
3136 * the web browser control of ie4 calls this with dwFlags=0
3139 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
3140 INT nMaxExtent, GCP_RESULTSA *lpResults,
3145 GCP_RESULTSW resultsW;
3149 TRACE("%s, %d, %d, 0x%08x\n",
3150 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
3152 /* both structs are equal in size */
3153 memcpy(&resultsW, lpResults, sizeof(resultsW));
3155 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
3156 if(lpResults->lpOutString)
3157 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
3159 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
3161 lpResults->nGlyphs = resultsW.nGlyphs;
3162 lpResults->nMaxFit = resultsW.nMaxFit;
3164 if(lpResults->lpOutString) {
3165 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
3166 lpResults->lpOutString, uCount, NULL, NULL );
3169 HeapFree(GetProcessHeap(), 0, lpStringW);
3170 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
3175 /*************************************************************************
3176 * GetCharacterPlacementW [GDI32.@]
3178 * Retrieve information about a string. This includes the width, reordering,
3179 * Glyphing and so on.
3183 * The width and height of the string if successful, 0 if failed.
3187 * All flags except GCP_REORDER are not yet implemented.
3188 * Reordering is not 100% compliant to the Windows BiDi method.
3189 * Caret positioning is not yet implemented for BiDi.
3190 * Classes are not yet implemented.
3194 GetCharacterPlacementW(
3195 HDC hdc, /* [in] Device context for which the rendering is to be done */
3196 LPCWSTR lpString, /* [in] The string for which information is to be returned */
3197 INT uCount, /* [in] Number of WORDS in string. */
3198 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
3199 GCP_RESULTSW *lpResults, /* [in/out] A pointer to a GCP_RESULTSW struct */
3200 DWORD dwFlags /* [in] Flags specifying how to process the string */
3207 TRACE("%s, %d, %d, 0x%08x\n",
3208 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
3210 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
3211 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
3212 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
3213 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
3214 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
3216 if(dwFlags&(~GCP_REORDER))
3217 FIXME("flags 0x%08x ignored\n", dwFlags);
3218 if(lpResults->lpClass)
3219 FIXME("classes not implemented\n");
3220 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
3221 FIXME("Caret positions for complex scripts not implemented\n");
3223 nSet = (UINT)uCount;
3224 if(nSet > lpResults->nGlyphs)
3225 nSet = lpResults->nGlyphs;
3227 /* return number of initialized fields */
3228 lpResults->nGlyphs = nSet;
3230 if((dwFlags&GCP_REORDER)==0 )
3232 /* Treat the case where no special handling was requested in a fastpath way */
3233 /* copy will do if the GCP_REORDER flag is not set */
3234 if(lpResults->lpOutString)
3235 memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
3237 if(lpResults->lpOrder)
3239 for(i = 0; i < nSet; i++)
3240 lpResults->lpOrder[i] = i;
3245 BIDI_Reorder(NULL, lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
3246 nSet, lpResults->lpOrder, NULL, NULL );
3249 /* FIXME: Will use the placement chars */
3250 if (lpResults->lpDx)
3253 for (i = 0; i < nSet; i++)
3255 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
3256 lpResults->lpDx[i]= c;
3260 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
3264 lpResults->lpCaretPos[0] = 0;
3265 for (i = 1; i < nSet; i++)
3266 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
3267 lpResults->lpCaretPos[i] = (pos += size.cx);
3270 if(lpResults->lpGlyphs)
3271 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
3273 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
3274 ret = MAKELONG(size.cx, size.cy);
3279 /*************************************************************************
3280 * GetCharABCWidthsFloatA [GDI32.@]
3282 * See GetCharABCWidthsFloatW.
3284 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3291 str = FONT_GetCharsByRangeA(hdc, first, last, &i);
3295 wstr = FONT_mbtowc( hdc, str, i, &wlen, NULL );
3297 for (i = 0; i < wlen; i++)
3299 if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
3307 HeapFree( GetProcessHeap(), 0, str );
3308 HeapFree( GetProcessHeap(), 0, wstr );
3313 /*************************************************************************
3314 * GetCharABCWidthsFloatW [GDI32.@]
3316 * Retrieves widths of a range of characters.
3319 * hdc [I] Handle to device context.
3320 * first [I] First character in range to query.
3321 * last [I] Last character in range to query.
3322 * abcf [O] Array of LPABCFLOAT structures.
3328 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3334 DC *dc = get_dc_ptr( hdc );
3336 TRACE("%p, %d, %d, %p\n", hdc, first, last, abcf);
3338 if (!dc) return FALSE;
3340 if (!abcf) goto done;
3341 if (!(abc = HeapAlloc( GetProcessHeap(), 0, (last - first + 1) * sizeof(*abc) ))) goto done;
3343 dev = GET_DC_PHYSDEV( dc, pGetCharABCWidths );
3344 ret = dev->funcs->pGetCharABCWidths( dev, first, last, abc );
3347 /* convert device units to logical */
3348 for (i = first; i <= last; i++, abcf++)
3350 abcf->abcfA = abc[i - first].abcA * dc->xformVport2World.eM11;
3351 abcf->abcfB = abc[i - first].abcB * dc->xformVport2World.eM11;
3352 abcf->abcfC = abc[i - first].abcC * dc->xformVport2World.eM11;
3355 HeapFree( GetProcessHeap(), 0, abc );
3358 release_dc_ptr( dc );
3362 /*************************************************************************
3363 * GetCharWidthFloatA [GDI32.@]
3365 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
3366 UINT iLastChar, PFLOAT pxBuffer)
3368 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3372 /*************************************************************************
3373 * GetCharWidthFloatW [GDI32.@]
3375 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
3376 UINT iLastChar, PFLOAT pxBuffer)
3378 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3383 /***********************************************************************
3385 * Font Resource API *
3387 ***********************************************************************/
3389 /***********************************************************************
3390 * AddFontResourceA (GDI32.@)
3392 INT WINAPI AddFontResourceA( LPCSTR str )
3394 return AddFontResourceExA( str, 0, NULL);
3397 /***********************************************************************
3398 * AddFontResourceW (GDI32.@)
3400 INT WINAPI AddFontResourceW( LPCWSTR str )
3402 return AddFontResourceExW(str, 0, NULL);
3406 /***********************************************************************
3407 * AddFontResourceExA (GDI32.@)
3409 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3411 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3412 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3415 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3416 ret = AddFontResourceExW(strW, fl, pdv);
3417 HeapFree(GetProcessHeap(), 0, strW);
3421 static BOOL CALLBACK load_enumed_resource(HMODULE hModule, LPCWSTR type, LPWSTR name, LONG_PTR lParam)
3423 HRSRC rsrc = FindResourceW(hModule, name, type);
3424 HGLOBAL hMem = LoadResource(hModule, rsrc);
3425 LPVOID *pMem = LockResource(hMem);
3426 int *num_total = (int *)lParam;
3429 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type));
3430 if (!AddFontMemResourceEx(pMem, SizeofResource(hModule, rsrc), NULL, &num_in_res))
3432 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule, hMem);
3436 *num_total += num_in_res;
3440 static void *map_file( const WCHAR *filename, LARGE_INTEGER *size )
3442 HANDLE file, mapping;
3445 file = CreateFileW( filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
3446 if (file == INVALID_HANDLE_VALUE) return NULL;
3448 if (!GetFileSizeEx( file, size ) || size->u.HighPart)
3450 CloseHandle( file );
3454 mapping = CreateFileMappingW( file, NULL, PAGE_READONLY, 0, 0, NULL );
3455 CloseHandle( file );
3456 if (!mapping) return NULL;
3458 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 );
3459 CloseHandle( mapping );
3464 static void *find_resource( BYTE *ptr, WORD type, DWORD rsrc_off, DWORD size, DWORD *len )
3466 WORD align, type_id, count;
3469 if (size < rsrc_off + 10) return NULL;
3470 align = *(WORD *)(ptr + rsrc_off);
3472 type_id = *(WORD *)(ptr + rsrc_off);
3473 while (type_id && type_id != type)
3475 count = *(WORD *)(ptr + rsrc_off + 2);
3476 rsrc_off += 8 + count * 12;
3477 if (size < rsrc_off + 8) return NULL;
3478 type_id = *(WORD *)(ptr + rsrc_off);
3480 if (!type_id) return NULL;
3481 count = *(WORD *)(ptr + rsrc_off + 2);
3482 if (size < rsrc_off + 8 + count * 12) return NULL;
3483 res_off = *(WORD *)(ptr + rsrc_off + 8) << align;
3484 *len = *(WORD *)(ptr + rsrc_off + 10) << align;
3485 if (size < res_off + *len) return NULL;
3486 return ptr + res_off;
3489 static WCHAR *get_scalable_filename( const WCHAR *res, BOOL *hidden )
3492 BYTE *ptr = map_file( res, &size );
3493 const IMAGE_DOS_HEADER *dos;
3494 const IMAGE_OS2_HEADER *ne;
3500 if (!ptr) return NULL;
3502 if (size.u.LowPart < sizeof( *dos )) goto fail;
3503 dos = (const IMAGE_DOS_HEADER *)ptr;
3504 if (dos->e_magic != IMAGE_DOS_SIGNATURE) goto fail;
3505 if (size.u.LowPart < dos->e_lfanew + sizeof( *ne )) goto fail;
3506 ne = (const IMAGE_OS2_HEADER *)(ptr + dos->e_lfanew);
3508 fontdir = find_resource( ptr, 0x8007, dos->e_lfanew + ne->ne_rsrctab, size.u.LowPart, &len );
3509 if (!fontdir) goto fail;
3510 *hidden = (fontdir[35] & 0x80) != 0; /* fontdir->dfType */
3512 data = find_resource( ptr, 0x80cc, dos->e_lfanew + ne->ne_rsrctab, size.u.LowPart, &len );
3513 if (!data) goto fail;
3514 if (!memchr( data, 0, len )) goto fail;
3516 len = MultiByteToWideChar( CP_ACP, 0, data, -1, NULL, 0 );
3517 name = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
3518 if (name) MultiByteToWideChar( CP_ACP, 0, data, -1, name, len );
3521 UnmapViewOfFile( ptr );
3525 /***********************************************************************
3526 * AddFontResourceExW (GDI32.@)
3528 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3530 int ret = WineEngAddFontResourceEx(str, fl, pdv);
3536 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3537 HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
3538 if (hModule != NULL)
3540 int num_resources = 0;
3541 LPWSTR rt_font = (LPWSTR)((ULONG_PTR)8); /* we don't want to include winuser.h */
3543 TRACE("WineEngAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3544 wine_dbgstr_w(str));
3545 if (EnumResourceNamesW(hModule, rt_font, load_enumed_resource, (LONG_PTR)&num_resources))
3546 ret = num_resources;
3547 FreeLibrary(hModule);
3549 else if ((filename = get_scalable_filename( str, &hidden )) != NULL)
3551 if (hidden) fl |= FR_PRIVATE | FR_NOT_ENUM;
3552 ret = WineEngAddFontResourceEx( filename, fl, pdv );
3553 HeapFree( GetProcessHeap(), 0, filename );
3559 /***********************************************************************
3560 * RemoveFontResourceA (GDI32.@)
3562 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3564 return RemoveFontResourceExA(str, 0, 0);
3567 /***********************************************************************
3568 * RemoveFontResourceW (GDI32.@)
3570 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3572 return RemoveFontResourceExW(str, 0, 0);
3575 /***********************************************************************
3576 * AddFontMemResourceEx (GDI32.@)
3578 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3583 if (!pbFont || !cbFont || !pcFonts)
3585 SetLastError(ERROR_INVALID_PARAMETER);
3589 ret = WineEngAddFontMemResourceEx(pbFont, cbFont, pdv, &num_fonts);
3594 *pcFonts = num_fonts;
3598 WARN("page fault while writing to *pcFonts (%p)\n", pcFonts);
3599 RemoveFontMemResourceEx(ret);
3607 /***********************************************************************
3608 * RemoveFontMemResourceEx (GDI32.@)
3610 BOOL WINAPI RemoveFontMemResourceEx( HANDLE fh )
3612 FIXME("(%p) stub\n", fh);
3616 /***********************************************************************
3617 * RemoveFontResourceExA (GDI32.@)
3619 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3621 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3622 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3625 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3626 ret = RemoveFontResourceExW(strW, fl, pdv);
3627 HeapFree(GetProcessHeap(), 0, strW);
3631 /***********************************************************************
3632 * RemoveFontResourceExW (GDI32.@)
3634 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3636 int ret = WineEngRemoveFontResourceEx( str, fl, pdv );
3642 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3643 HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
3644 if (hModule != NULL)
3646 WARN("Can't unload resources from PE file %s\n", wine_dbgstr_w(str));
3647 FreeLibrary(hModule);
3649 else if ((filename = get_scalable_filename( str, &hidden )) != NULL)
3651 if (hidden) fl |= FR_PRIVATE | FR_NOT_ENUM;
3652 ret = WineEngRemoveFontResourceEx( filename, fl, pdv );
3653 HeapFree( GetProcessHeap(), 0, filename );
3659 /***********************************************************************
3660 * GetFontResourceInfoW (GDI32.@)
3662 BOOL WINAPI GetFontResourceInfoW( LPCWSTR str, LPDWORD size, PVOID buffer, DWORD type )
3664 FIXME("%s %p(%d) %p %d\n", debugstr_w(str), size, size ? *size : 0, buffer, type);
3668 /***********************************************************************
3669 * GetTextCharset (GDI32.@)
3671 UINT WINAPI GetTextCharset(HDC hdc)
3673 /* MSDN docs say this is equivalent */
3674 return GetTextCharsetInfo(hdc, NULL, 0);
3677 /***********************************************************************
3678 * GetTextCharsetInfo (GDI32.@)
3680 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3682 UINT ret = DEFAULT_CHARSET;
3683 DC *dc = get_dc_ptr(hdc);
3688 dev = GET_DC_PHYSDEV( dc, pGetTextCharsetInfo );
3689 ret = dev->funcs->pGetTextCharsetInfo( dev, fs, flags );
3690 release_dc_ptr( dc );
3693 if (ret == DEFAULT_CHARSET && fs)
3694 memset(fs, 0, sizeof(FONTSIGNATURE));
3698 /***********************************************************************
3699 * GdiGetCharDimensions (GDI32.@)
3701 * Gets the average width of the characters in the English alphabet.
3704 * hdc [I] Handle to the device context to measure on.
3705 * lptm [O] Pointer to memory to store the text metrics into.
3706 * height [O] On exit, the maximum height of characters in the English alphabet.
3709 * The average width of characters in the English alphabet.
3712 * This function is used by the dialog manager to get the size of a dialog
3713 * unit. It should also be used by other pieces of code that need to know
3714 * the size of a dialog unit in logical units without having access to the
3715 * window handle of the dialog.
3716 * Windows caches the font metrics from this function, but we don't and
3717 * there doesn't appear to be an immediate advantage to do so.
3720 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3722 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3725 static const WCHAR alphabet[] = {
3726 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3727 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3728 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3730 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3732 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3734 if (height) *height = sz.cy;
3735 return (sz.cx / 26 + 1) / 2;
3738 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3740 FIXME("(%d): stub\n", fEnableEUDC);
3744 /***********************************************************************
3745 * GetCharWidthI (GDI32.@)
3747 * Retrieve widths of characters.
3750 * hdc [I] Handle to a device context.
3751 * first [I] First glyph in range to query.
3752 * count [I] Number of glyph indices to query.
3753 * glyphs [I] Array of glyphs to query.
3754 * buffer [O] Buffer to receive character widths.
3757 * Only works with TrueType fonts.
3763 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3768 TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3770 if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3773 if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3775 HeapFree(GetProcessHeap(), 0, abc);
3779 for (i = 0; i < count; i++)
3780 buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3782 HeapFree(GetProcessHeap(), 0, abc);
3786 /***********************************************************************
3787 * GetFontUnicodeRanges (GDI32.@)
3789 * Retrieve a list of supported Unicode characters in a font.
3792 * hdc [I] Handle to a device context.
3793 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3796 * Success: Number of bytes written to the buffer pointed to by lpgs.
3800 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3804 DC *dc = get_dc_ptr(hdc);
3806 TRACE("(%p, %p)\n", hdc, lpgs);
3810 dev = GET_DC_PHYSDEV( dc, pGetFontUnicodeRanges );
3811 ret = dev->funcs->pGetFontUnicodeRanges( dev, lpgs );
3817 /*************************************************************
3818 * FontIsLinked (GDI32.@)
3820 BOOL WINAPI FontIsLinked(HDC hdc)
3822 DC *dc = get_dc_ptr(hdc);
3826 if (!dc) return FALSE;
3827 dev = GET_DC_PHYSDEV( dc, pFontIsLinked );
3828 ret = dev->funcs->pFontIsLinked( dev );
3830 TRACE("returning %d\n", ret);
3834 /*************************************************************
3835 * GdiRealizationInfo (GDI32.@)
3837 * Returns a structure that contains some font information.
3839 BOOL WINAPI GdiRealizationInfo(HDC hdc, realization_info_t *info)
3841 DC *dc = get_dc_ptr(hdc);
3845 if (!dc) return FALSE;
3846 dev = GET_DC_PHYSDEV( dc, pGdiRealizationInfo );
3847 ret = dev->funcs->pGdiRealizationInfo( dev, info );