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"
36 #include "gdi_private.h"
37 #include "wine/exception.h"
38 #include "wine/unicode.h"
39 #include "wine/debug.h"
41 #ifdef WORDS_BIGENDIAN
42 #define get_be_word(x) (x)
44 #define get_be_word(x) RtlUshortByteSwap(x)
47 WINE_DEFAULT_DEBUG_CHANNEL(font
);
49 /* Device -> World size conversion */
51 /* Performs a device to world transformation on the specified width (which
52 * is in integer format).
54 static inline INT
INTERNAL_XDSTOWS(DC
*dc
, INT width
)
58 /* Perform operation with floating point */
59 floatWidth
= (double)width
* dc
->xformVport2World
.eM11
;
60 /* Round to integers */
61 return GDI_ROUND(floatWidth
);
64 /* Performs a device to world transformation on the specified size (which
65 * is in integer format).
67 static inline INT
INTERNAL_YDSTOWS(DC
*dc
, INT height
)
71 /* Perform operation with floating point */
72 floatHeight
= (double)height
* dc
->xformVport2World
.eM22
;
73 /* Round to integers */
74 return GDI_ROUND(floatHeight
);
77 static inline INT
INTERNAL_XWSTODS(DC
*dc
, INT width
)
80 pt
[0].x
= pt
[0].y
= 0;
83 LPtoDP(dc
->hSelf
, pt
, 2);
84 return pt
[1].x
- pt
[0].x
;
87 static inline INT
INTERNAL_YWSTODS(DC
*dc
, INT height
)
90 pt
[0].x
= pt
[0].y
= 0;
93 LPtoDP(dc
->hSelf
, pt
, 2);
94 return pt
[1].y
- pt
[0].y
;
97 static HGDIOBJ
FONT_SelectObject( HGDIOBJ handle
, HDC hdc
);
98 static INT
FONT_GetObjectA( HGDIOBJ handle
, INT count
, LPVOID buffer
);
99 static INT
FONT_GetObjectW( HGDIOBJ handle
, INT count
, LPVOID buffer
);
100 static BOOL
FONT_DeleteObject( HGDIOBJ handle
);
102 static const struct gdi_obj_funcs font_funcs
=
104 FONT_SelectObject
, /* pSelectObject */
105 FONT_GetObjectA
, /* pGetObjectA */
106 FONT_GetObjectW
, /* pGetObjectW */
107 NULL
, /* pUnrealizeObject */
108 FONT_DeleteObject
/* pDeleteObject */
119 LPLOGFONTW lpLogFontParam
;
120 FONTENUMPROCW lpEnumFunc
;
127 * For TranslateCharsetInfo
129 #define MAXTCIINDEX 32
130 static const CHARSETINFO FONT_tci
[MAXTCIINDEX
] = {
132 { ANSI_CHARSET
, 1252, {{0,0,0,0},{FS_LATIN1
,0}} },
133 { EASTEUROPE_CHARSET
, 1250, {{0,0,0,0},{FS_LATIN2
,0}} },
134 { RUSSIAN_CHARSET
, 1251, {{0,0,0,0},{FS_CYRILLIC
,0}} },
135 { GREEK_CHARSET
, 1253, {{0,0,0,0},{FS_GREEK
,0}} },
136 { TURKISH_CHARSET
, 1254, {{0,0,0,0},{FS_TURKISH
,0}} },
137 { HEBREW_CHARSET
, 1255, {{0,0,0,0},{FS_HEBREW
,0}} },
138 { ARABIC_CHARSET
, 1256, {{0,0,0,0},{FS_ARABIC
,0}} },
139 { BALTIC_CHARSET
, 1257, {{0,0,0,0},{FS_BALTIC
,0}} },
140 { VIETNAMESE_CHARSET
, 1258, {{0,0,0,0},{FS_VIETNAMESE
,0}} },
141 /* reserved by ANSI */
142 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
143 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
144 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
145 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
146 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
147 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
148 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
150 { THAI_CHARSET
, 874, {{0,0,0,0},{FS_THAI
,0}} },
151 { SHIFTJIS_CHARSET
, 932, {{0,0,0,0},{FS_JISJAPAN
,0}} },
152 { GB2312_CHARSET
, 936, {{0,0,0,0},{FS_CHINESESIMP
,0}} },
153 { HANGEUL_CHARSET
, 949, {{0,0,0,0},{FS_WANSUNG
,0}} },
154 { CHINESEBIG5_CHARSET
, 950, {{0,0,0,0},{FS_CHINESETRAD
,0}} },
155 { JOHAB_CHARSET
, 1361, {{0,0,0,0},{FS_JOHAB
,0}} },
156 /* reserved for alternate ANSI and OEM */
157 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
158 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
159 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
160 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
161 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
162 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
163 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
164 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
165 /* reserved for system */
166 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
167 { SYMBOL_CHARSET
, CP_SYMBOL
, {{0,0,0,0},{FS_SYMBOL
,0}} }
170 static void FONT_LogFontAToW( const LOGFONTA
*fontA
, LPLOGFONTW fontW
)
172 memcpy(fontW
, fontA
, sizeof(LOGFONTA
) - LF_FACESIZE
);
173 MultiByteToWideChar(CP_ACP
, 0, fontA
->lfFaceName
, -1, fontW
->lfFaceName
,
175 fontW
->lfFaceName
[LF_FACESIZE
-1] = 0;
178 static void FONT_LogFontWToA( const LOGFONTW
*fontW
, LPLOGFONTA fontA
)
180 memcpy(fontA
, fontW
, sizeof(LOGFONTA
) - LF_FACESIZE
);
181 WideCharToMultiByte(CP_ACP
, 0, fontW
->lfFaceName
, -1, fontA
->lfFaceName
,
182 LF_FACESIZE
, NULL
, NULL
);
183 fontA
->lfFaceName
[LF_FACESIZE
-1] = 0;
186 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW
*fontW
, LPENUMLOGFONTEXA fontA
)
188 FONT_LogFontWToA( &fontW
->elfLogFont
, &fontA
->elfLogFont
);
190 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfFullName
, -1,
191 (LPSTR
) fontA
->elfFullName
, LF_FULLFACESIZE
, NULL
, NULL
);
192 fontA
->elfFullName
[LF_FULLFACESIZE
-1] = '\0';
193 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfStyle
, -1,
194 (LPSTR
) fontA
->elfStyle
, LF_FACESIZE
, NULL
, NULL
);
195 fontA
->elfStyle
[LF_FACESIZE
-1] = '\0';
196 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfScript
, -1,
197 (LPSTR
) fontA
->elfScript
, LF_FACESIZE
, NULL
, NULL
);
198 fontA
->elfScript
[LF_FACESIZE
-1] = '\0';
201 static void FONT_EnumLogFontExAToW( const ENUMLOGFONTEXA
*fontA
, LPENUMLOGFONTEXW fontW
)
203 FONT_LogFontAToW( &fontA
->elfLogFont
, &fontW
->elfLogFont
);
205 MultiByteToWideChar( CP_ACP
, 0, (LPCSTR
)fontA
->elfFullName
, -1,
206 fontW
->elfFullName
, LF_FULLFACESIZE
);
207 fontW
->elfFullName
[LF_FULLFACESIZE
-1] = '\0';
208 MultiByteToWideChar( CP_ACP
, 0, (LPCSTR
)fontA
->elfStyle
, -1,
209 fontW
->elfStyle
, LF_FACESIZE
);
210 fontW
->elfStyle
[LF_FACESIZE
-1] = '\0';
211 MultiByteToWideChar( CP_ACP
, 0, (LPCSTR
)fontA
->elfScript
, -1,
212 fontW
->elfScript
, LF_FACESIZE
);
213 fontW
->elfScript
[LF_FACESIZE
-1] = '\0';
216 /***********************************************************************
217 * TEXTMETRIC conversion functions.
219 static void FONT_TextMetricWToA(const TEXTMETRICW
*ptmW
, LPTEXTMETRICA ptmA
)
221 ptmA
->tmHeight
= ptmW
->tmHeight
;
222 ptmA
->tmAscent
= ptmW
->tmAscent
;
223 ptmA
->tmDescent
= ptmW
->tmDescent
;
224 ptmA
->tmInternalLeading
= ptmW
->tmInternalLeading
;
225 ptmA
->tmExternalLeading
= ptmW
->tmExternalLeading
;
226 ptmA
->tmAveCharWidth
= ptmW
->tmAveCharWidth
;
227 ptmA
->tmMaxCharWidth
= ptmW
->tmMaxCharWidth
;
228 ptmA
->tmWeight
= ptmW
->tmWeight
;
229 ptmA
->tmOverhang
= ptmW
->tmOverhang
;
230 ptmA
->tmDigitizedAspectX
= ptmW
->tmDigitizedAspectX
;
231 ptmA
->tmDigitizedAspectY
= ptmW
->tmDigitizedAspectY
;
232 ptmA
->tmFirstChar
= min(ptmW
->tmFirstChar
, 255);
233 if (ptmW
->tmCharSet
== SYMBOL_CHARSET
)
235 ptmA
->tmFirstChar
= 0x1e;
236 ptmA
->tmLastChar
= 0xff; /* win9x behaviour - we need the OS2 table data to calculate correctly */
238 else if (ptmW
->tmPitchAndFamily
& TMPF_TRUETYPE
)
240 ptmA
->tmFirstChar
= ptmW
->tmDefaultChar
- 1;
241 ptmA
->tmLastChar
= min(ptmW
->tmLastChar
, 0xff);
245 ptmA
->tmFirstChar
= min(ptmW
->tmFirstChar
, 0xff);
246 ptmA
->tmLastChar
= min(ptmW
->tmLastChar
, 0xff);
248 ptmA
->tmDefaultChar
= ptmW
->tmDefaultChar
;
249 ptmA
->tmBreakChar
= ptmW
->tmBreakChar
;
250 ptmA
->tmItalic
= ptmW
->tmItalic
;
251 ptmA
->tmUnderlined
= ptmW
->tmUnderlined
;
252 ptmA
->tmStruckOut
= ptmW
->tmStruckOut
;
253 ptmA
->tmPitchAndFamily
= ptmW
->tmPitchAndFamily
;
254 ptmA
->tmCharSet
= ptmW
->tmCharSet
;
258 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW
*ptmW
, NEWTEXTMETRICEXA
*ptmA
)
260 FONT_TextMetricWToA((const TEXTMETRICW
*)ptmW
, (LPTEXTMETRICA
)ptmA
);
261 ptmA
->ntmTm
.ntmFlags
= ptmW
->ntmTm
.ntmFlags
;
262 ptmA
->ntmTm
.ntmSizeEM
= ptmW
->ntmTm
.ntmSizeEM
;
263 ptmA
->ntmTm
.ntmCellHeight
= ptmW
->ntmTm
.ntmCellHeight
;
264 ptmA
->ntmTm
.ntmAvgWidth
= ptmW
->ntmTm
.ntmAvgWidth
;
265 memcpy(&ptmA
->ntmFontSig
, &ptmW
->ntmFontSig
, sizeof(FONTSIGNATURE
));
268 static DWORD
get_font_ppem( HDC hdc
)
272 DC
*dc
= get_dc_ptr( hdc
);
274 if (!dc
) return GDI_ERROR
;
276 GetTextMetricsW( hdc
, &tm
);
277 ppem
= abs( INTERNAL_YWSTODS( dc
, tm
.tmAscent
+ tm
.tmDescent
- tm
.tmInternalLeading
) );
278 release_dc_ptr( dc
);
282 #define GASP_GRIDFIT 0x01
283 #define GASP_DOGRAY 0x02
285 static BOOL
get_gasp_flags( HDC hdc
, WORD
*flags
)
287 DWORD size
, gasp_tag
= 0x70736167;
288 WORD buf
[16]; /* Enough for seven ranges before we need to alloc */
289 WORD
*alloced
= NULL
, *ptr
= buf
;
290 WORD num_recs
, version
;
291 DWORD ppem
= get_font_ppem( hdc
);
295 if (ppem
== GDI_ERROR
) return FALSE
;
297 size
= GetFontData( hdc
, gasp_tag
, 0, NULL
, 0 );
298 if (size
== GDI_ERROR
) return FALSE
;
299 if (size
< 4 * sizeof(WORD
)) return FALSE
;
300 if (size
> sizeof(buf
))
302 ptr
= alloced
= HeapAlloc( GetProcessHeap(), 0, size
);
303 if (!ptr
) return FALSE
;
306 GetFontData( hdc
, gasp_tag
, 0, ptr
, size
);
308 version
= get_be_word( *ptr
++ );
309 num_recs
= get_be_word( *ptr
++ );
311 if (version
> 1 || size
< (num_recs
* 2 + 2) * sizeof(WORD
))
313 FIXME( "Unsupported gasp table: ver %d size %d recs %d\n", version
, size
, num_recs
);
319 *flags
= get_be_word( *(ptr
+ 1) );
320 if (ppem
<= get_be_word( *ptr
)) break;
323 TRACE( "got flags %04x for ppem %d\n", *flags
, ppem
);
327 HeapFree( GetProcessHeap(), 0, alloced
);
331 UINT
get_font_aa_flags( HDC hdc
)
336 if (GetObjectType( hdc
) == OBJ_MEMDC
)
339 GetObjectW( GetCurrentObject( hdc
, OBJ_BITMAP
), sizeof(bm
), &bm
);
340 if (bm
.bmBitsPixel
<= 8) return GGO_BITMAP
;
342 else if (GetDeviceCaps( hdc
, BITSPIXEL
) <= 8) return GGO_BITMAP
;
344 GetObjectW( GetCurrentObject( hdc
, OBJ_FONT
), sizeof(lf
), &lf
);
345 if (lf
.lfQuality
== NONANTIALIASED_QUALITY
) return GGO_BITMAP
;
347 if (get_gasp_flags( hdc
, &gasp_flags
) && !(gasp_flags
& GASP_DOGRAY
))
350 /* FIXME, check user prefs */
351 return GGO_GRAY4_BITMAP
;
354 /***********************************************************************
355 * GdiGetCodePage (GDI32.@)
357 DWORD WINAPI
GdiGetCodePage( HDC hdc
)
360 DC
*dc
= get_dc_ptr( hdc
);
364 cp
= dc
->font_code_page
;
365 release_dc_ptr( dc
);
370 /***********************************************************************
373 * Returns a Unicode translation of str using the charset of the
374 * currently selected font in hdc. If count is -1 then str is assumed
375 * to be '\0' terminated, otherwise it contains the number of bytes to
376 * convert. If plenW is non-NULL, on return it will point to the
377 * number of WCHARs that have been written. If pCP is non-NULL, on
378 * return it will point to the codepage used in the conversion. The
379 * caller should free the returned LPWSTR from the process heap
382 static LPWSTR
FONT_mbtowc(HDC hdc
, LPCSTR str
, INT count
, INT
*plenW
, UINT
*pCP
)
388 cp
= GdiGetCodePage( hdc
);
390 if(count
== -1) count
= strlen(str
);
391 lenW
= MultiByteToWideChar(cp
, 0, str
, count
, NULL
, 0);
392 strW
= HeapAlloc(GetProcessHeap(), 0, lenW
*sizeof(WCHAR
));
393 MultiByteToWideChar(cp
, 0, str
, count
, strW
, lenW
);
394 TRACE("mapped %s -> %s\n", debugstr_an(str
, count
), debugstr_wn(strW
, lenW
));
395 if(plenW
) *plenW
= lenW
;
400 /***********************************************************************
401 * CreateFontIndirectExA (GDI32.@)
403 HFONT WINAPI
CreateFontIndirectExA( const ENUMLOGFONTEXDVA
*penumexA
)
405 ENUMLOGFONTEXDVW enumexW
;
407 if (!penumexA
) return 0;
409 FONT_EnumLogFontExAToW( &penumexA
->elfEnumLogfontEx
, &enumexW
.elfEnumLogfontEx
);
410 enumexW
.elfDesignVector
= penumexA
->elfDesignVector
;
411 return CreateFontIndirectExW( &enumexW
);
414 /***********************************************************************
415 * CreateFontIndirectExW (GDI32.@)
417 HFONT WINAPI
CreateFontIndirectExW( const ENUMLOGFONTEXDVW
*penumex
)
423 if (!penumex
) return 0;
425 if (penumex
->elfEnumLogfontEx
.elfFullName
[0] ||
426 penumex
->elfEnumLogfontEx
.elfStyle
[0] ||
427 penumex
->elfEnumLogfontEx
.elfScript
[0])
429 FIXME("some fields ignored. fullname=%s, style=%s, script=%s\n",
430 debugstr_w(penumex
->elfEnumLogfontEx
.elfFullName
),
431 debugstr_w(penumex
->elfEnumLogfontEx
.elfStyle
),
432 debugstr_w(penumex
->elfEnumLogfontEx
.elfScript
));
435 plf
= &penumex
->elfEnumLogfontEx
.elfLogFont
;
436 if (!(fontPtr
= HeapAlloc( GetProcessHeap(), 0, sizeof(*fontPtr
) ))) return 0;
438 fontPtr
->logfont
= *plf
;
440 if (plf
->lfEscapement
!= plf
->lfOrientation
)
442 /* this should really depend on whether GM_ADVANCED is set */
443 fontPtr
->logfont
.lfOrientation
= fontPtr
->logfont
.lfEscapement
;
444 WARN("orientation angle %f set to "
445 "escapement angle %f for new font %p\n",
446 plf
->lfOrientation
/10., plf
->lfEscapement
/10., fontPtr
);
449 if (!(hFont
= alloc_gdi_handle( &fontPtr
->header
, OBJ_FONT
, &font_funcs
)))
451 HeapFree( GetProcessHeap(), 0, fontPtr
);
455 TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
456 plf
->lfHeight
, plf
->lfWidth
,
457 plf
->lfEscapement
, plf
->lfOrientation
,
458 plf
->lfPitchAndFamily
,
459 plf
->lfOutPrecision
, plf
->lfClipPrecision
,
460 plf
->lfQuality
, plf
->lfCharSet
,
461 debugstr_w(plf
->lfFaceName
),
462 plf
->lfWeight
> 400 ? "Bold" : "",
463 plf
->lfItalic
? "Italic" : "",
464 plf
->lfUnderline
? "Underline" : "", hFont
);
469 /***********************************************************************
470 * CreateFontIndirectA (GDI32.@)
472 HFONT WINAPI
CreateFontIndirectA( const LOGFONTA
*plfA
)
478 FONT_LogFontAToW( plfA
, &lfW
);
479 return CreateFontIndirectW( &lfW
);
482 /***********************************************************************
483 * CreateFontIndirectW (GDI32.@)
485 HFONT WINAPI
CreateFontIndirectW( const LOGFONTW
*plf
)
487 ENUMLOGFONTEXDVW exdv
;
491 exdv
.elfEnumLogfontEx
.elfLogFont
= *plf
;
492 exdv
.elfEnumLogfontEx
.elfFullName
[0] = 0;
493 exdv
.elfEnumLogfontEx
.elfStyle
[0] = 0;
494 exdv
.elfEnumLogfontEx
.elfScript
[0] = 0;
495 return CreateFontIndirectExW( &exdv
);
498 /*************************************************************************
499 * CreateFontA (GDI32.@)
501 HFONT WINAPI
CreateFontA( INT height
, INT width
, INT esc
,
502 INT orient
, INT weight
, DWORD italic
,
503 DWORD underline
, DWORD strikeout
, DWORD charset
,
504 DWORD outpres
, DWORD clippres
, DWORD quality
,
505 DWORD pitch
, LPCSTR name
)
509 logfont
.lfHeight
= height
;
510 logfont
.lfWidth
= width
;
511 logfont
.lfEscapement
= esc
;
512 logfont
.lfOrientation
= orient
;
513 logfont
.lfWeight
= weight
;
514 logfont
.lfItalic
= italic
;
515 logfont
.lfUnderline
= underline
;
516 logfont
.lfStrikeOut
= strikeout
;
517 logfont
.lfCharSet
= charset
;
518 logfont
.lfOutPrecision
= outpres
;
519 logfont
.lfClipPrecision
= clippres
;
520 logfont
.lfQuality
= quality
;
521 logfont
.lfPitchAndFamily
= pitch
;
524 lstrcpynA(logfont
.lfFaceName
,name
,sizeof(logfont
.lfFaceName
));
526 logfont
.lfFaceName
[0] = '\0';
528 return CreateFontIndirectA( &logfont
);
531 /*************************************************************************
532 * CreateFontW (GDI32.@)
534 HFONT WINAPI
CreateFontW( INT height
, INT width
, INT esc
,
535 INT orient
, INT weight
, DWORD italic
,
536 DWORD underline
, DWORD strikeout
, DWORD charset
,
537 DWORD outpres
, DWORD clippres
, DWORD quality
,
538 DWORD pitch
, LPCWSTR name
)
542 logfont
.lfHeight
= height
;
543 logfont
.lfWidth
= width
;
544 logfont
.lfEscapement
= esc
;
545 logfont
.lfOrientation
= orient
;
546 logfont
.lfWeight
= weight
;
547 logfont
.lfItalic
= italic
;
548 logfont
.lfUnderline
= underline
;
549 logfont
.lfStrikeOut
= strikeout
;
550 logfont
.lfCharSet
= charset
;
551 logfont
.lfOutPrecision
= outpres
;
552 logfont
.lfClipPrecision
= clippres
;
553 logfont
.lfQuality
= quality
;
554 logfont
.lfPitchAndFamily
= pitch
;
557 lstrcpynW(logfont
.lfFaceName
, name
,
558 sizeof(logfont
.lfFaceName
) / sizeof(WCHAR
));
560 logfont
.lfFaceName
[0] = '\0';
562 return CreateFontIndirectW( &logfont
);
565 static void update_font_code_page( DC
*dc
)
568 int charset
= GetTextCharsetInfo( dc
->hSelf
, NULL
, 0 );
570 /* Hmm, nicely designed api this one! */
571 if (TranslateCharsetInfo( ULongToPtr(charset
), &csi
, TCI_SRCCHARSET
) )
572 dc
->font_code_page
= csi
.ciACP
;
576 dc
->font_code_page
= GetOEMCP();
578 case DEFAULT_CHARSET
:
579 dc
->font_code_page
= GetACP();
589 /* FIXME: These have no place here, but because x11drv
590 enumerates fonts with these (made up) charsets some apps
591 might use them and then the FIXME below would become
592 annoying. Now we could pick the intended codepage for
593 each of these, but since it's broken anyway we'll just
594 use CP_ACP and hope it'll go away...
596 dc
->font_code_page
= CP_ACP
;
600 FIXME("Can't find codepage for charset %d\n", charset
);
601 dc
->font_code_page
= CP_ACP
;
606 TRACE("charset %d => cp %d\n", charset
, dc
->font_code_page
);
609 /***********************************************************************
612 static HGDIOBJ
FONT_SelectObject( HGDIOBJ handle
, HDC hdc
)
615 DC
*dc
= get_dc_ptr( hdc
);
620 if (!GDI_inc_ref_count( handle
))
622 release_dc_ptr( dc
);
626 physdev
= GET_DC_PHYSDEV( dc
, pSelectFont
);
627 if (physdev
->funcs
->pSelectFont( physdev
, handle
))
631 update_font_code_page( dc
);
632 GDI_dec_ref_count( ret
);
634 else GDI_dec_ref_count( handle
);
636 release_dc_ptr( dc
);
641 /***********************************************************************
644 static INT
FONT_GetObjectA( HGDIOBJ handle
, INT count
, LPVOID buffer
)
646 FONTOBJ
*font
= GDI_GetObjPtr( handle
, OBJ_FONT
);
652 FONT_LogFontWToA( &font
->logfont
, &lfA
);
653 if (count
> sizeof(lfA
)) count
= sizeof(lfA
);
654 memcpy( buffer
, &lfA
, count
);
656 else count
= sizeof(lfA
);
657 GDI_ReleaseObj( handle
);
661 /***********************************************************************
664 static INT
FONT_GetObjectW( HGDIOBJ handle
, INT count
, LPVOID buffer
)
666 FONTOBJ
*font
= GDI_GetObjPtr( handle
, OBJ_FONT
);
671 if (count
> sizeof(LOGFONTW
)) count
= sizeof(LOGFONTW
);
672 memcpy( buffer
, &font
->logfont
, count
);
674 else count
= sizeof(LOGFONTW
);
675 GDI_ReleaseObj( handle
);
680 /***********************************************************************
683 static BOOL
FONT_DeleteObject( HGDIOBJ handle
)
687 WineEngDestroyFontInstance( handle
);
689 if (!(obj
= free_gdi_handle( handle
))) return FALSE
;
690 return HeapFree( GetProcessHeap(), 0, obj
);
694 /***********************************************************************
697 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
698 * We have to use other types because of the FONTENUMPROCW definition.
700 static INT CALLBACK
FONT_EnumInstance( const LOGFONTW
*plf
, const TEXTMETRICW
*ptm
,
701 DWORD fType
, LPARAM lp
)
703 struct font_enum
*pfe
= (struct font_enum
*)lp
;
706 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
707 if ((!pfe
->lpLogFontParam
||
708 pfe
->lpLogFontParam
->lfCharSet
== DEFAULT_CHARSET
||
709 pfe
->lpLogFontParam
->lfCharSet
== plf
->lfCharSet
) &&
710 (!(fType
& RASTER_FONTTYPE
) || GetDeviceCaps(pfe
->hdc
, TEXTCAPS
) & TC_RA_ABLE
) )
712 /* convert font metrics */
713 ENUMLOGFONTEXA logfont
;
714 NEWTEXTMETRICEXA tmA
;
718 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW
*)plf
, &logfont
);
719 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW
*)ptm
, &tmA
);
720 plf
= (LOGFONTW
*)&logfont
.elfLogFont
;
721 ptm
= (TEXTMETRICW
*)&tmA
;
723 ret
= pfe
->lpEnumFunc( plf
, ptm
, fType
, pfe
->lpData
);
728 /***********************************************************************
729 * FONT_EnumFontFamiliesEx
731 static INT
FONT_EnumFontFamiliesEx( HDC hDC
, LPLOGFONTW plf
, FONTENUMPROCW efproc
,
732 LPARAM lParam
, BOOL unicode
)
735 DC
*dc
= get_dc_ptr( hDC
);
740 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pEnumFonts
);
742 if (plf
) TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf
->lfFaceName
), plf
->lfCharSet
);
743 fe
.lpLogFontParam
= plf
;
744 fe
.lpEnumFunc
= efproc
;
746 fe
.unicode
= unicode
;
748 ret
= physdev
->funcs
->pEnumFonts( physdev
, plf
, FONT_EnumInstance
, (LPARAM
)&fe
);
749 release_dc_ptr( dc
);
754 /***********************************************************************
755 * EnumFontFamiliesExW (GDI32.@)
757 INT WINAPI
EnumFontFamiliesExW( HDC hDC
, LPLOGFONTW plf
,
758 FONTENUMPROCW efproc
,
759 LPARAM lParam
, DWORD dwFlags
)
761 return FONT_EnumFontFamiliesEx( hDC
, plf
, efproc
, lParam
, TRUE
);
764 /***********************************************************************
765 * EnumFontFamiliesExA (GDI32.@)
767 INT WINAPI
EnumFontFamiliesExA( HDC hDC
, LPLOGFONTA plf
,
768 FONTENUMPROCA efproc
,
769 LPARAM lParam
, DWORD dwFlags
)
775 FONT_LogFontAToW( plf
, &lfW
);
780 return FONT_EnumFontFamiliesEx( hDC
, plfW
, (FONTENUMPROCW
)efproc
, lParam
, FALSE
);
783 /***********************************************************************
784 * EnumFontFamiliesA (GDI32.@)
786 INT WINAPI
EnumFontFamiliesA( HDC hDC
, LPCSTR lpFamily
,
787 FONTENUMPROCA efproc
, LPARAM lpData
)
793 if (!*lpFamily
) return 1;
794 lstrcpynA( lf
.lfFaceName
, lpFamily
, LF_FACESIZE
);
795 lf
.lfCharSet
= DEFAULT_CHARSET
;
796 lf
.lfPitchAndFamily
= 0;
801 return EnumFontFamiliesExA( hDC
, plf
, efproc
, lpData
, 0 );
804 /***********************************************************************
805 * EnumFontFamiliesW (GDI32.@)
807 INT WINAPI
EnumFontFamiliesW( HDC hDC
, LPCWSTR lpFamily
,
808 FONTENUMPROCW efproc
, LPARAM lpData
)
814 if (!*lpFamily
) return 1;
815 lstrcpynW( lf
.lfFaceName
, lpFamily
, LF_FACESIZE
);
816 lf
.lfCharSet
= DEFAULT_CHARSET
;
817 lf
.lfPitchAndFamily
= 0;
822 return EnumFontFamiliesExW( hDC
, plf
, efproc
, lpData
, 0 );
825 /***********************************************************************
826 * EnumFontsA (GDI32.@)
828 INT WINAPI
EnumFontsA( HDC hDC
, LPCSTR lpName
, FONTENUMPROCA efproc
,
831 return EnumFontFamiliesA( hDC
, lpName
, efproc
, lpData
);
834 /***********************************************************************
835 * EnumFontsW (GDI32.@)
837 INT WINAPI
EnumFontsW( HDC hDC
, LPCWSTR lpName
, FONTENUMPROCW efproc
,
840 return EnumFontFamiliesW( hDC
, lpName
, efproc
, lpData
);
844 /***********************************************************************
845 * GetTextCharacterExtra (GDI32.@)
847 INT WINAPI
GetTextCharacterExtra( HDC hdc
)
850 DC
*dc
= get_dc_ptr( hdc
);
851 if (!dc
) return 0x80000000;
853 release_dc_ptr( dc
);
858 /***********************************************************************
859 * SetTextCharacterExtra (GDI32.@)
861 INT WINAPI
SetTextCharacterExtra( HDC hdc
, INT extra
)
863 INT ret
= 0x80000000;
864 DC
* dc
= get_dc_ptr( hdc
);
868 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetTextCharacterExtra
);
869 extra
= physdev
->funcs
->pSetTextCharacterExtra( physdev
, extra
);
870 if (extra
!= 0x80000000)
873 dc
->charExtra
= extra
;
875 release_dc_ptr( dc
);
881 /***********************************************************************
882 * SetTextJustification (GDI32.@)
884 BOOL WINAPI
SetTextJustification( HDC hdc
, INT extra
, INT breaks
)
888 DC
* dc
= get_dc_ptr( hdc
);
890 if (!dc
) return FALSE
;
892 physdev
= GET_DC_PHYSDEV( dc
, pSetTextJustification
);
893 ret
= physdev
->funcs
->pSetTextJustification( physdev
, extra
, breaks
);
896 extra
= abs((extra
* dc
->vportExtX
+ dc
->wndExtX
/ 2) / dc
->wndExtX
);
897 if (!extra
) breaks
= 0;
900 dc
->breakExtra
= extra
/ breaks
;
901 dc
->breakRem
= extra
- (breaks
* dc
->breakExtra
);
909 release_dc_ptr( dc
);
914 /***********************************************************************
915 * GetTextFaceA (GDI32.@)
917 INT WINAPI
GetTextFaceA( HDC hdc
, INT count
, LPSTR name
)
919 INT res
= GetTextFaceW(hdc
, 0, NULL
);
920 LPWSTR nameW
= HeapAlloc( GetProcessHeap(), 0, res
* 2 );
921 GetTextFaceW( hdc
, res
, nameW
);
927 res
= WideCharToMultiByte(CP_ACP
, 0, nameW
, -1, name
, count
, NULL
, NULL
);
931 /* GetTextFaceA does NOT include the nul byte in the return count. */
938 res
= WideCharToMultiByte( CP_ACP
, 0, nameW
, -1, NULL
, 0, NULL
, NULL
);
939 HeapFree( GetProcessHeap(), 0, nameW
);
943 /***********************************************************************
944 * GetTextFaceW (GDI32.@)
946 INT WINAPI
GetTextFaceW( HDC hdc
, INT count
, LPWSTR name
)
951 DC
* dc
= get_dc_ptr( hdc
);
954 dev
= GET_DC_PHYSDEV( dc
, pGetTextFace
);
955 ret
= dev
->funcs
->pGetTextFace( dev
, count
, name
);
956 release_dc_ptr( dc
);
961 /***********************************************************************
962 * GetTextExtentPoint32A (GDI32.@)
964 * See GetTextExtentPoint32W.
966 BOOL WINAPI
GetTextExtentPoint32A( HDC hdc
, LPCSTR str
, INT count
,
973 if (count
< 0) return FALSE
;
975 p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
979 ret
= GetTextExtentPoint32W( hdc
, p
, wlen
, size
);
980 HeapFree( GetProcessHeap(), 0, p
);
983 TRACE("(%p %s %d %p): returning %d x %d\n",
984 hdc
, debugstr_an (str
, count
), count
, size
, size
->cx
, size
->cy
);
989 /***********************************************************************
990 * GetTextExtentPoint32W [GDI32.@]
992 * Computes width/height for a string.
994 * Computes width and height of the specified string.
1000 BOOL WINAPI
GetTextExtentPoint32W(
1001 HDC hdc
, /* [in] Handle of device context */
1002 LPCWSTR str
, /* [in] Address of text string */
1003 INT count
, /* [in] Number of characters in string */
1004 LPSIZE size
) /* [out] Address of structure for string size */
1006 return GetTextExtentExPointW(hdc
, str
, count
, 0, NULL
, NULL
, size
);
1009 /***********************************************************************
1010 * GetTextExtentExPointI [GDI32.@]
1012 * Computes width and height of the array of glyph indices.
1015 * hdc [I] Handle of device context.
1016 * indices [I] Glyph index array.
1017 * count [I] Number of glyphs in array.
1018 * max_ext [I] Maximum width in glyphs.
1019 * nfit [O] Maximum number of characters.
1020 * dxs [O] Partial string widths.
1021 * size [O] Returned string size.
1027 BOOL WINAPI
GetTextExtentExPointI( HDC hdc
, const WORD
*indices
, INT count
, INT max_ext
,
1028 LPINT nfit
, LPINT dxs
, LPSIZE size
)
1034 if (count
< 0) return FALSE
;
1036 dc
= get_dc_ptr( hdc
);
1037 if (!dc
) return FALSE
;
1039 dev
= GET_DC_PHYSDEV( dc
, pGetTextExtentExPointI
);
1040 ret
= dev
->funcs
->pGetTextExtentExPointI( dev
, indices
, count
, max_ext
, nfit
, dxs
, size
);
1041 size
->cx
= abs(INTERNAL_XDSTOWS(dc
, size
->cx
));
1042 size
->cy
= abs(INTERNAL_YDSTOWS(dc
, size
->cy
));
1043 size
->cx
+= count
* dc
->charExtra
;
1044 release_dc_ptr( dc
);
1046 TRACE("(%p %p %d %p): returning %d x %d\n",
1047 hdc
, indices
, count
, size
, size
->cx
, size
->cy
);
1051 /***********************************************************************
1052 * GetTextExtentPointI [GDI32.@]
1054 * Computes width and height of the array of glyph indices.
1057 * hdc [I] Handle of device context.
1058 * indices [I] Glyph index array.
1059 * count [I] Number of glyphs in array.
1060 * size [O] Returned string size.
1066 BOOL WINAPI
GetTextExtentPointI( HDC hdc
, const WORD
*indices
, INT count
, LPSIZE size
)
1068 return GetTextExtentExPointI( hdc
, indices
, count
, 0, NULL
, NULL
, size
);
1072 /***********************************************************************
1073 * GetTextExtentPointA (GDI32.@)
1075 BOOL WINAPI
GetTextExtentPointA( HDC hdc
, LPCSTR str
, INT count
,
1078 TRACE("not bug compatible.\n");
1079 return GetTextExtentPoint32A( hdc
, str
, count
, size
);
1082 /***********************************************************************
1083 * GetTextExtentPointW (GDI32.@)
1085 BOOL WINAPI
GetTextExtentPointW( HDC hdc
, LPCWSTR str
, INT count
,
1088 TRACE("not bug compatible.\n");
1089 return GetTextExtentPoint32W( hdc
, str
, count
, size
);
1093 /***********************************************************************
1094 * GetTextExtentExPointA (GDI32.@)
1096 BOOL WINAPI
GetTextExtentExPointA( HDC hdc
, LPCSTR str
, INT count
,
1097 INT maxExt
, LPINT lpnFit
,
1098 LPINT alpDx
, LPSIZE size
)
1105 if (count
< 0) return FALSE
;
1109 walpDx
= HeapAlloc( GetProcessHeap(), 0, count
* sizeof(INT
) );
1110 if (!walpDx
) return FALSE
;
1113 p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
1114 ret
= GetTextExtentExPointW( hdc
, p
, wlen
, maxExt
, lpnFit
, walpDx
, size
);
1117 INT n
= lpnFit
? *lpnFit
: wlen
;
1119 for(i
= 0, j
= 0; i
< n
; i
++, j
++)
1121 alpDx
[j
] = walpDx
[i
];
1122 if (IsDBCSLeadByte(str
[j
])) alpDx
[++j
] = walpDx
[i
];
1125 if (lpnFit
) *lpnFit
= WideCharToMultiByte(CP_ACP
,0,p
,*lpnFit
,NULL
,0,NULL
,NULL
);
1126 HeapFree( GetProcessHeap(), 0, p
);
1127 HeapFree( GetProcessHeap(), 0, walpDx
);
1132 /***********************************************************************
1133 * GetTextExtentExPointW (GDI32.@)
1135 * Return the size of the string as it would be if it was output properly by
1138 * This should include
1139 * - Intercharacter spacing
1140 * - justification spacing (not yet done)
1141 * - kerning? see below
1143 * Kerning. Since kerning would be carried out by the rendering code it should
1144 * be done by the driver. However they don't support it yet. Also I am not
1145 * yet persuaded that (certainly under Win95) any kerning is actually done.
1147 * str: According to MSDN this should be null-terminated. That is not true; a
1148 * null will not terminate it early.
1149 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1150 * than count. I have seen it be either the size of the full string or
1151 * 1 less than the size of the full string. I have not seen it bear any
1152 * resemblance to the portion that would fit.
1153 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1154 * trailing intercharacter spacing and any trailing justification.
1157 * Currently we do this by measuring each character etc. We should do it by
1158 * passing the request to the driver, perhaps by extending the
1159 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1160 * thinking about kerning issues and rounding issues in the justification.
1163 BOOL WINAPI
GetTextExtentExPointW( HDC hdc
, LPCWSTR str
, INT count
,
1164 INT maxExt
, LPINT lpnFit
,
1165 LPINT alpDx
, LPSIZE size
)
1174 TRACE("(%p, %s, %d)\n",hdc
,debugstr_wn(str
,count
),maxExt
);
1176 if (count
< 0) return FALSE
;
1178 dc
= get_dc_ptr(hdc
);
1179 if (!dc
) return FALSE
;
1181 GetTextMetricsW(hdc
, &tm
);
1183 /* If we need to calculate nFit, then we need the partial extents even if
1184 the user hasn't provided us with an array. */
1187 dxs
= alpDx
? alpDx
: HeapAlloc(GetProcessHeap(), 0, count
* sizeof alpDx
[0]);
1191 SetLastError(ERROR_OUTOFMEMORY
);
1198 dev
= GET_DC_PHYSDEV( dc
, pGetTextExtentExPoint
);
1199 ret
= dev
->funcs
->pGetTextExtentExPoint(dev
, str
, count
, 0, NULL
, dxs
, size
);
1201 /* Perform device size to world size transformations. */
1204 INT extra
= dc
->charExtra
,
1205 breakExtra
= dc
->breakExtra
,
1206 breakRem
= dc
->breakRem
,
1211 for (i
= 0; i
< count
; ++i
)
1213 dxs
[i
] = abs(INTERNAL_XDSTOWS(dc
, dxs
[i
]));
1214 dxs
[i
] += (i
+1) * extra
;
1215 if (count
> 1 && (breakExtra
|| breakRem
) && str
[i
] == tm
.tmBreakChar
)
1217 dxs
[i
] += breakExtra
;
1224 if (dxs
[i
] <= maxExt
)
1227 breakRem
= dc
->breakRem
;
1229 size
->cx
= abs(INTERNAL_XDSTOWS(dc
, size
->cx
));
1230 size
->cy
= abs(INTERNAL_YDSTOWS(dc
, size
->cy
));
1232 if (!dxs
&& count
> 1 && (breakExtra
|| breakRem
))
1234 for (i
= 0; i
< count
; i
++)
1236 if (str
[i
] == tm
.tmBreakChar
)
1238 size
->cx
+= breakExtra
;
1253 HeapFree(GetProcessHeap(), 0, dxs
);
1255 release_dc_ptr( dc
);
1257 TRACE("returning %d %d x %d\n",nFit
,size
->cx
,size
->cy
);
1261 /***********************************************************************
1262 * GetTextMetricsA (GDI32.@)
1264 BOOL WINAPI
GetTextMetricsA( HDC hdc
, TEXTMETRICA
*metrics
)
1268 if (!GetTextMetricsW( hdc
, &tm32
)) return FALSE
;
1269 FONT_TextMetricWToA( &tm32
, metrics
);
1273 /***********************************************************************
1274 * GetTextMetricsW (GDI32.@)
1276 BOOL WINAPI
GetTextMetricsW( HDC hdc
, TEXTMETRICW
*metrics
)
1280 DC
* dc
= get_dc_ptr( hdc
);
1281 if (!dc
) return FALSE
;
1283 physdev
= GET_DC_PHYSDEV( dc
, pGetTextMetrics
);
1284 ret
= physdev
->funcs
->pGetTextMetrics( physdev
, metrics
);
1288 /* device layer returns values in device units
1289 * therefore we have to convert them to logical */
1291 metrics
->tmDigitizedAspectX
= GetDeviceCaps(hdc
, LOGPIXELSX
);
1292 metrics
->tmDigitizedAspectY
= GetDeviceCaps(hdc
, LOGPIXELSY
);
1294 #define WDPTOLP(x) ((x<0)? \
1295 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1296 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1297 #define HDPTOLP(y) ((y<0)? \
1298 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1299 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1301 metrics
->tmHeight
= HDPTOLP(metrics
->tmHeight
);
1302 metrics
->tmAscent
= HDPTOLP(metrics
->tmAscent
);
1303 metrics
->tmDescent
= HDPTOLP(metrics
->tmDescent
);
1304 metrics
->tmInternalLeading
= HDPTOLP(metrics
->tmInternalLeading
);
1305 metrics
->tmExternalLeading
= HDPTOLP(metrics
->tmExternalLeading
);
1306 metrics
->tmAveCharWidth
= WDPTOLP(metrics
->tmAveCharWidth
);
1307 metrics
->tmMaxCharWidth
= WDPTOLP(metrics
->tmMaxCharWidth
);
1308 metrics
->tmOverhang
= WDPTOLP(metrics
->tmOverhang
);
1312 TRACE("text metrics:\n"
1313 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1314 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1315 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1316 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1317 " PitchAndFamily = %02x\n"
1318 " --------------------\n"
1319 " InternalLeading = %i\n"
1323 metrics
->tmWeight
, metrics
->tmFirstChar
, metrics
->tmAveCharWidth
,
1324 metrics
->tmItalic
, metrics
->tmLastChar
, metrics
->tmMaxCharWidth
,
1325 metrics
->tmUnderlined
, metrics
->tmDefaultChar
, metrics
->tmOverhang
,
1326 metrics
->tmStruckOut
, metrics
->tmBreakChar
, metrics
->tmCharSet
,
1327 metrics
->tmPitchAndFamily
,
1328 metrics
->tmInternalLeading
,
1331 metrics
->tmHeight
);
1333 release_dc_ptr( dc
);
1338 /***********************************************************************
1339 * GetOutlineTextMetricsA (GDI32.@)
1340 * Gets metrics for TrueType fonts.
1343 * If the supplied buffer isn't big enough Windows partially fills it up to
1344 * its given length and returns that length.
1347 * Success: Non-zero or size of required buffer
1350 UINT WINAPI
GetOutlineTextMetricsA(
1351 HDC hdc
, /* [in] Handle of device context */
1352 UINT cbData
, /* [in] Size of metric data array */
1353 LPOUTLINETEXTMETRICA lpOTM
) /* [out] Address of metric data array */
1355 char buf
[512], *ptr
;
1357 OUTLINETEXTMETRICW
*lpOTMW
= (OUTLINETEXTMETRICW
*)buf
;
1358 OUTLINETEXTMETRICA
*output
= lpOTM
;
1361 if((ret
= GetOutlineTextMetricsW(hdc
, 0, NULL
)) == 0)
1363 if(ret
> sizeof(buf
))
1364 lpOTMW
= HeapAlloc(GetProcessHeap(), 0, ret
);
1365 GetOutlineTextMetricsW(hdc
, ret
, lpOTMW
);
1367 needed
= sizeof(OUTLINETEXTMETRICA
);
1368 if(lpOTMW
->otmpFamilyName
)
1369 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1370 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFamilyName
), -1,
1371 NULL
, 0, NULL
, NULL
);
1372 if(lpOTMW
->otmpFaceName
)
1373 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1374 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFaceName
), -1,
1375 NULL
, 0, NULL
, NULL
);
1376 if(lpOTMW
->otmpStyleName
)
1377 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1378 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpStyleName
), -1,
1379 NULL
, 0, NULL
, NULL
);
1380 if(lpOTMW
->otmpFullName
)
1381 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1382 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFullName
), -1,
1383 NULL
, 0, NULL
, NULL
);
1390 TRACE("needed = %d\n", needed
);
1392 /* Since the supplied buffer isn't big enough, we'll alloc one
1393 that is and memcpy the first cbData bytes into the lpOTM at
1395 output
= HeapAlloc(GetProcessHeap(), 0, needed
);
1397 ret
= output
->otmSize
= min(needed
, cbData
);
1398 FONT_TextMetricWToA( &lpOTMW
->otmTextMetrics
, &output
->otmTextMetrics
);
1399 output
->otmFiller
= 0;
1400 output
->otmPanoseNumber
= lpOTMW
->otmPanoseNumber
;
1401 output
->otmfsSelection
= lpOTMW
->otmfsSelection
;
1402 output
->otmfsType
= lpOTMW
->otmfsType
;
1403 output
->otmsCharSlopeRise
= lpOTMW
->otmsCharSlopeRise
;
1404 output
->otmsCharSlopeRun
= lpOTMW
->otmsCharSlopeRun
;
1405 output
->otmItalicAngle
= lpOTMW
->otmItalicAngle
;
1406 output
->otmEMSquare
= lpOTMW
->otmEMSquare
;
1407 output
->otmAscent
= lpOTMW
->otmAscent
;
1408 output
->otmDescent
= lpOTMW
->otmDescent
;
1409 output
->otmLineGap
= lpOTMW
->otmLineGap
;
1410 output
->otmsCapEmHeight
= lpOTMW
->otmsCapEmHeight
;
1411 output
->otmsXHeight
= lpOTMW
->otmsXHeight
;
1412 output
->otmrcFontBox
= lpOTMW
->otmrcFontBox
;
1413 output
->otmMacAscent
= lpOTMW
->otmMacAscent
;
1414 output
->otmMacDescent
= lpOTMW
->otmMacDescent
;
1415 output
->otmMacLineGap
= lpOTMW
->otmMacLineGap
;
1416 output
->otmusMinimumPPEM
= lpOTMW
->otmusMinimumPPEM
;
1417 output
->otmptSubscriptSize
= lpOTMW
->otmptSubscriptSize
;
1418 output
->otmptSubscriptOffset
= lpOTMW
->otmptSubscriptOffset
;
1419 output
->otmptSuperscriptSize
= lpOTMW
->otmptSuperscriptSize
;
1420 output
->otmptSuperscriptOffset
= lpOTMW
->otmptSuperscriptOffset
;
1421 output
->otmsStrikeoutSize
= lpOTMW
->otmsStrikeoutSize
;
1422 output
->otmsStrikeoutPosition
= lpOTMW
->otmsStrikeoutPosition
;
1423 output
->otmsUnderscoreSize
= lpOTMW
->otmsUnderscoreSize
;
1424 output
->otmsUnderscorePosition
= lpOTMW
->otmsUnderscorePosition
;
1427 ptr
= (char*)(output
+ 1);
1428 left
= needed
- sizeof(*output
);
1430 if(lpOTMW
->otmpFamilyName
) {
1431 output
->otmpFamilyName
= (LPSTR
)(ptr
- (char*)output
);
1432 len
= WideCharToMultiByte(CP_ACP
, 0,
1433 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFamilyName
), -1,
1434 ptr
, left
, NULL
, NULL
);
1438 output
->otmpFamilyName
= 0;
1440 if(lpOTMW
->otmpFaceName
) {
1441 output
->otmpFaceName
= (LPSTR
)(ptr
- (char*)output
);
1442 len
= WideCharToMultiByte(CP_ACP
, 0,
1443 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFaceName
), -1,
1444 ptr
, left
, NULL
, NULL
);
1448 output
->otmpFaceName
= 0;
1450 if(lpOTMW
->otmpStyleName
) {
1451 output
->otmpStyleName
= (LPSTR
)(ptr
- (char*)output
);
1452 len
= WideCharToMultiByte(CP_ACP
, 0,
1453 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpStyleName
), -1,
1454 ptr
, left
, NULL
, NULL
);
1458 output
->otmpStyleName
= 0;
1460 if(lpOTMW
->otmpFullName
) {
1461 output
->otmpFullName
= (LPSTR
)(ptr
- (char*)output
);
1462 len
= WideCharToMultiByte(CP_ACP
, 0,
1463 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFullName
), -1,
1464 ptr
, left
, NULL
, NULL
);
1467 output
->otmpFullName
= 0;
1471 if(output
!= lpOTM
) {
1472 memcpy(lpOTM
, output
, cbData
);
1473 HeapFree(GetProcessHeap(), 0, output
);
1475 /* check if the string offsets really fit into the provided size */
1476 /* FIXME: should we check string length as well? */
1477 /* make sure that we don't read/write beyond the provided buffer */
1478 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFamilyName
) + sizeof(LPSTR
))
1480 if ((UINT_PTR
)lpOTM
->otmpFamilyName
>= lpOTM
->otmSize
)
1481 lpOTM
->otmpFamilyName
= 0; /* doesn't fit */
1484 /* make sure that we don't read/write beyond the provided buffer */
1485 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFaceName
) + sizeof(LPSTR
))
1487 if ((UINT_PTR
)lpOTM
->otmpFaceName
>= lpOTM
->otmSize
)
1488 lpOTM
->otmpFaceName
= 0; /* doesn't fit */
1491 /* make sure that we don't read/write beyond the provided buffer */
1492 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpStyleName
) + sizeof(LPSTR
))
1494 if ((UINT_PTR
)lpOTM
->otmpStyleName
>= lpOTM
->otmSize
)
1495 lpOTM
->otmpStyleName
= 0; /* doesn't fit */
1498 /* make sure that we don't read/write beyond the provided buffer */
1499 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFullName
) + sizeof(LPSTR
))
1501 if ((UINT_PTR
)lpOTM
->otmpFullName
>= lpOTM
->otmSize
)
1502 lpOTM
->otmpFullName
= 0; /* doesn't fit */
1507 if(lpOTMW
!= (OUTLINETEXTMETRICW
*)buf
)
1508 HeapFree(GetProcessHeap(), 0, lpOTMW
);
1514 /***********************************************************************
1515 * GetOutlineTextMetricsW [GDI32.@]
1517 UINT WINAPI
GetOutlineTextMetricsW(
1518 HDC hdc
, /* [in] Handle of device context */
1519 UINT cbData
, /* [in] Size of metric data array */
1520 LPOUTLINETEXTMETRICW lpOTM
) /* [out] Address of metric data array */
1522 DC
*dc
= get_dc_ptr( hdc
);
1523 OUTLINETEXTMETRICW
*output
= lpOTM
;
1527 TRACE("(%p,%d,%p)\n", hdc
, cbData
, lpOTM
);
1530 dev
= GET_DC_PHYSDEV( dc
, pGetOutlineTextMetrics
);
1531 ret
= dev
->funcs
->pGetOutlineTextMetrics( dev
, cbData
, output
);
1533 if (lpOTM
&& ret
> cbData
)
1535 output
= HeapAlloc(GetProcessHeap(), 0, ret
);
1536 ret
= dev
->funcs
->pGetOutlineTextMetrics( dev
, ret
, output
);
1541 output
->otmTextMetrics
.tmDigitizedAspectX
= GetDeviceCaps(hdc
, LOGPIXELSX
);
1542 output
->otmTextMetrics
.tmDigitizedAspectY
= GetDeviceCaps(hdc
, LOGPIXELSY
);
1544 #define WDPTOLP(x) ((x<0)? \
1545 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1546 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1547 #define HDPTOLP(y) ((y<0)? \
1548 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1549 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1551 output
->otmTextMetrics
.tmHeight
= HDPTOLP(output
->otmTextMetrics
.tmHeight
);
1552 output
->otmTextMetrics
.tmAscent
= HDPTOLP(output
->otmTextMetrics
.tmAscent
);
1553 output
->otmTextMetrics
.tmDescent
= HDPTOLP(output
->otmTextMetrics
.tmDescent
);
1554 output
->otmTextMetrics
.tmInternalLeading
= HDPTOLP(output
->otmTextMetrics
.tmInternalLeading
);
1555 output
->otmTextMetrics
.tmExternalLeading
= HDPTOLP(output
->otmTextMetrics
.tmExternalLeading
);
1556 output
->otmTextMetrics
.tmAveCharWidth
= WDPTOLP(output
->otmTextMetrics
.tmAveCharWidth
);
1557 output
->otmTextMetrics
.tmMaxCharWidth
= WDPTOLP(output
->otmTextMetrics
.tmMaxCharWidth
);
1558 output
->otmTextMetrics
.tmOverhang
= WDPTOLP(output
->otmTextMetrics
.tmOverhang
);
1559 output
->otmAscent
= HDPTOLP(output
->otmAscent
);
1560 output
->otmDescent
= HDPTOLP(output
->otmDescent
);
1561 output
->otmLineGap
= abs(INTERNAL_YDSTOWS(dc
,output
->otmLineGap
));
1562 output
->otmsCapEmHeight
= abs(INTERNAL_YDSTOWS(dc
,output
->otmsCapEmHeight
));
1563 output
->otmsXHeight
= abs(INTERNAL_YDSTOWS(dc
,output
->otmsXHeight
));
1564 output
->otmrcFontBox
.top
= HDPTOLP(output
->otmrcFontBox
.top
);
1565 output
->otmrcFontBox
.bottom
= HDPTOLP(output
->otmrcFontBox
.bottom
);
1566 output
->otmrcFontBox
.left
= WDPTOLP(output
->otmrcFontBox
.left
);
1567 output
->otmrcFontBox
.right
= WDPTOLP(output
->otmrcFontBox
.right
);
1568 output
->otmMacAscent
= HDPTOLP(output
->otmMacAscent
);
1569 output
->otmMacDescent
= HDPTOLP(output
->otmMacDescent
);
1570 output
->otmMacLineGap
= abs(INTERNAL_YDSTOWS(dc
,output
->otmMacLineGap
));
1571 output
->otmptSubscriptSize
.x
= WDPTOLP(output
->otmptSubscriptSize
.x
);
1572 output
->otmptSubscriptSize
.y
= HDPTOLP(output
->otmptSubscriptSize
.y
);
1573 output
->otmptSubscriptOffset
.x
= WDPTOLP(output
->otmptSubscriptOffset
.x
);
1574 output
->otmptSubscriptOffset
.y
= HDPTOLP(output
->otmptSubscriptOffset
.y
);
1575 output
->otmptSuperscriptSize
.x
= WDPTOLP(output
->otmptSuperscriptSize
.x
);
1576 output
->otmptSuperscriptSize
.y
= HDPTOLP(output
->otmptSuperscriptSize
.y
);
1577 output
->otmptSuperscriptOffset
.x
= WDPTOLP(output
->otmptSuperscriptOffset
.x
);
1578 output
->otmptSuperscriptOffset
.y
= HDPTOLP(output
->otmptSuperscriptOffset
.y
);
1579 output
->otmsStrikeoutSize
= abs(INTERNAL_YDSTOWS(dc
,output
->otmsStrikeoutSize
));
1580 output
->otmsStrikeoutPosition
= HDPTOLP(output
->otmsStrikeoutPosition
);
1581 output
->otmsUnderscoreSize
= HDPTOLP(output
->otmsUnderscoreSize
);
1582 output
->otmsUnderscorePosition
= HDPTOLP(output
->otmsUnderscorePosition
);
1587 memcpy(lpOTM
, output
, cbData
);
1588 HeapFree(GetProcessHeap(), 0, output
);
1596 static LPSTR
FONT_GetCharsByRangeA(HDC hdc
, UINT firstChar
, UINT lastChar
, PINT pByteLen
)
1598 INT i
, count
= lastChar
- firstChar
+ 1;
1606 mbcp
= GdiGetCodePage(hdc
);
1614 if (lastChar
> 0xffff)
1616 if ((firstChar
^ lastChar
) > 0xff)
1620 if (lastChar
> 0xff)
1626 str
= HeapAlloc(GetProcessHeap(), 0, count
* 2 + 1);
1630 for(i
= 0, c
= firstChar
; c
<= lastChar
; i
++, c
++)
1634 str
[i
++] = (BYTE
)(c
>> 8);
1635 if (c
<= 0xff && IsDBCSLeadByteEx(mbcp
, c
))
1636 str
[i
] = 0x1f; /* FIXME: use default character */
1650 /***********************************************************************
1651 * GetCharWidthW (GDI32.@)
1652 * GetCharWidth32W (GDI32.@)
1654 BOOL WINAPI
GetCharWidth32W( HDC hdc
, UINT firstChar
, UINT lastChar
,
1660 DC
* dc
= get_dc_ptr( hdc
);
1662 if (!dc
) return FALSE
;
1664 dev
= GET_DC_PHYSDEV( dc
, pGetCharWidth
);
1665 ret
= dev
->funcs
->pGetCharWidth( dev
, firstChar
, lastChar
, buffer
);
1669 /* convert device units to logical */
1670 for( i
= firstChar
; i
<= lastChar
; i
++, buffer
++ )
1671 *buffer
= INTERNAL_XDSTOWS(dc
, *buffer
);
1673 release_dc_ptr( dc
);
1678 /***********************************************************************
1679 * GetCharWidthA (GDI32.@)
1680 * GetCharWidth32A (GDI32.@)
1682 BOOL WINAPI
GetCharWidth32A( HDC hdc
, UINT firstChar
, UINT lastChar
,
1690 str
= FONT_GetCharsByRangeA(hdc
, firstChar
, lastChar
, &i
);
1694 wstr
= FONT_mbtowc(hdc
, str
, i
, &wlen
, NULL
);
1696 for(i
= 0; i
< wlen
; i
++)
1698 if(!GetCharWidth32W(hdc
, wstr
[i
], wstr
[i
], buffer
))
1706 HeapFree(GetProcessHeap(), 0, str
);
1707 HeapFree(GetProcessHeap(), 0, wstr
);
1713 /* helper for nulldrv_ExtTextOut */
1714 static DWORD
get_glyph_bitmap( HDC hdc
, UINT index
, UINT aa_flags
,
1715 GLYPHMETRICS
*metrics
, struct gdi_image_bits
*image
)
1717 UINT ggo_flags
= aa_flags
| GGO_GLYPH_INDEX
;
1718 static const MAT2 identity
= { {0,1}, {0,0}, {0,0}, {0,1} };
1719 UINT indices
[3] = {0, 0, 0x20};
1726 for (i
= 0; i
< sizeof(indices
) / sizeof(indices
[0]); i
++)
1729 ret
= GetGlyphOutlineW( hdc
, index
, ggo_flags
, metrics
, 0, NULL
, &identity
);
1730 if (ret
!= GDI_ERROR
) break;
1733 if (ret
== GDI_ERROR
) return ERROR_NOT_FOUND
;
1734 if (!image
) return ERROR_SUCCESS
;
1738 if (!ret
) return ERROR_SUCCESS
; /* empty glyph */
1740 stride
= get_dib_stride( metrics
->gmBlackBoxX
, 1 );
1741 size
= metrics
->gmBlackBoxY
* stride
;
1743 if (!(image
->ptr
= HeapAlloc( GetProcessHeap(), 0, size
))) return ERROR_OUTOFMEMORY
;
1744 image
->is_copy
= TRUE
;
1745 image
->free
= free_heap_bits
;
1747 ret
= GetGlyphOutlineW( hdc
, index
, ggo_flags
, metrics
, size
, image
->ptr
, &identity
);
1748 if (ret
== GDI_ERROR
)
1750 HeapFree( GetProcessHeap(), 0, image
->ptr
);
1751 return ERROR_NOT_FOUND
;
1753 return ERROR_SUCCESS
;
1756 /* helper for nulldrv_ExtTextOut */
1757 static RECT
get_total_extents( HDC hdc
, INT x
, INT y
, UINT flags
, UINT aa_flags
,
1758 LPCWSTR str
, UINT count
, const INT
*dx
)
1763 rect
.left
= rect
.top
= INT_MAX
;
1764 rect
.right
= rect
.bottom
= INT_MIN
;
1765 for (i
= 0; i
< count
; i
++)
1767 GLYPHMETRICS metrics
;
1769 if (get_glyph_bitmap( hdc
, (UINT
)str
[i
], aa_flags
, &metrics
, NULL
)) continue;
1771 rect
.left
= min( rect
.left
, x
+ metrics
.gmptGlyphOrigin
.x
);
1772 rect
.top
= min( rect
.top
, y
- metrics
.gmptGlyphOrigin
.y
);
1773 rect
.right
= max( rect
.right
, x
+ metrics
.gmptGlyphOrigin
.x
+ (int)metrics
.gmBlackBoxX
);
1774 rect
.bottom
= max( rect
.bottom
, y
- metrics
.gmptGlyphOrigin
.y
+ (int)metrics
.gmBlackBoxY
);
1778 if (flags
& ETO_PDY
)
1781 y
+= dx
[ i
* 2 + 1];
1787 x
+= metrics
.gmCellIncX
;
1788 y
+= metrics
.gmCellIncY
;
1794 /* helper for nulldrv_ExtTextOut */
1795 static void draw_glyph( HDC hdc
, INT origin_x
, INT origin_y
, const GLYPHMETRICS
*metrics
,
1796 const struct gdi_image_bits
*image
, const RECT
*clip
)
1798 static const BYTE masks
[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
1799 UINT x
, y
, i
, count
;
1800 BYTE
*ptr
= image
->ptr
;
1801 int stride
= get_dib_stride( metrics
->gmBlackBoxX
, 1 );
1803 RECT rect
, clipped_rect
;
1805 rect
.left
= origin_x
+ metrics
->gmptGlyphOrigin
.x
;
1806 rect
.top
= origin_y
- metrics
->gmptGlyphOrigin
.y
;
1807 rect
.right
= rect
.left
+ metrics
->gmBlackBoxX
;
1808 rect
.bottom
= rect
.top
+ metrics
->gmBlackBoxY
;
1809 if (!clip
) clipped_rect
= rect
;
1810 else if (!intersect_rect( &clipped_rect
, &rect
, clip
)) return;
1812 pts
= HeapAlloc( GetProcessHeap(), 0,
1813 max(2,metrics
->gmBlackBoxX
) * metrics
->gmBlackBoxY
* sizeof(*pts
) );
1817 ptr
+= (clipped_rect
.top
- rect
.top
) * stride
;
1818 for (y
= clipped_rect
.top
; y
< clipped_rect
.bottom
; y
++, ptr
+= stride
)
1820 for (x
= clipped_rect
.left
- rect
.left
; x
< clipped_rect
.right
- rect
.left
; x
++)
1822 while (x
< clipped_rect
.right
- rect
.left
&& !(ptr
[x
/ 8] & masks
[x
% 8])) x
++;
1823 pts
[count
].x
= rect
.left
+ x
;
1824 while (x
< clipped_rect
.right
- rect
.left
&& (ptr
[x
/ 8] & masks
[x
% 8])) x
++;
1825 pts
[count
+ 1].x
= rect
.left
+ x
;
1826 if (pts
[count
+ 1].x
> pts
[count
].x
)
1828 pts
[count
].y
= pts
[count
+ 1].y
= y
;
1833 DPtoLP( hdc
, pts
, count
);
1834 for (i
= 0; i
< count
; i
+= 2) Polyline( hdc
, pts
+ i
, 2 );
1835 HeapFree( GetProcessHeap(), 0, pts
);
1838 /***********************************************************************
1839 * nulldrv_ExtTextOut
1841 BOOL
nulldrv_ExtTextOut( PHYSDEV dev
, INT x
, INT y
, UINT flags
, const RECT
*rect
,
1842 LPCWSTR str
, UINT count
, const INT
*dx
)
1844 DC
*dc
= get_nulldrv_dc( dev
);
1850 if (flags
& ETO_OPAQUE
)
1853 HBRUSH brush
= CreateSolidBrush( GetNearestColor( dev
->hdc
, GetBkColor(dev
->hdc
) ));
1857 orig
= SelectObject( dev
->hdc
, brush
);
1858 DPtoLP( dev
->hdc
, (POINT
*)&rc
, 2 );
1859 PatBlt( dev
->hdc
, rc
.left
, rc
.top
, rc
.right
- rc
.left
, rc
.bottom
- rc
.top
, PATCOPY
);
1860 SelectObject( dev
->hdc
, orig
);
1861 DeleteObject( brush
);
1865 if (!count
) return TRUE
;
1867 aa_flags
= get_font_aa_flags( dev
->hdc
);
1869 if (aa_flags
!= GGO_BITMAP
)
1871 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1872 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
1873 struct gdi_image_bits bits
;
1874 struct bitblt_coords src
, dst
;
1877 dst_dev
= GET_DC_PHYSDEV( dc
, pPutImage
);
1878 src
.visrect
= get_total_extents( dev
->hdc
, x
, y
, flags
, aa_flags
, str
, count
, dx
);
1879 if (flags
& ETO_CLIPPED
) intersect_rect( &src
.visrect
, &src
.visrect
, rect
);
1880 if (!clip_visrect( dc
, &src
.visrect
, &src
.visrect
)) return TRUE
;
1882 /* FIXME: check for ETO_OPAQUE and avoid GetImage */
1883 src
.x
= src
.visrect
.left
;
1884 src
.y
= src
.visrect
.top
;
1885 src
.width
= src
.visrect
.right
- src
.visrect
.left
;
1886 src
.height
= src
.visrect
.bottom
- src
.visrect
.top
;
1888 if ((flags
& ETO_OPAQUE
) && (src
.visrect
.left
>= rect
->left
) && (src
.visrect
.top
>= rect
->top
) &&
1889 (src
.visrect
.right
<= rect
->right
) && (src
.visrect
.bottom
<= rect
->bottom
))
1891 /* we can avoid the GetImage, just query the needed format */
1892 memset( &info
->bmiHeader
, 0, sizeof(info
->bmiHeader
) );
1893 info
->bmiHeader
.biSize
= sizeof(info
->bmiHeader
);
1894 info
->bmiHeader
.biWidth
= src
.width
;
1895 info
->bmiHeader
.biHeight
= -src
.height
;
1896 err
= dst_dev
->funcs
->pPutImage( dst_dev
, 0, 0, info
, NULL
, NULL
, NULL
, 0 );
1897 if (!err
|| err
== ERROR_BAD_FORMAT
)
1899 /* make the source rectangle relative to the source bits */
1901 src
.visrect
.left
= src
.visrect
.top
= 0;
1902 src
.visrect
.right
= src
.width
;
1903 src
.visrect
.bottom
= src
.height
;
1905 bits
.ptr
= HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( info
));
1906 if (!bits
.ptr
) return ERROR_OUTOFMEMORY
;
1907 bits
.is_copy
= TRUE
;
1908 bits
.free
= free_heap_bits
;
1909 err
= ERROR_SUCCESS
;
1914 PHYSDEV src_dev
= GET_DC_PHYSDEV( dc
, pGetImage
);
1915 err
= src_dev
->funcs
->pGetImage( src_dev
, 0, info
, &bits
, &src
);
1916 if (!err
&& !bits
.is_copy
)
1918 void *ptr
= HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( info
));
1921 if (bits
.free
) bits
.free( &bits
);
1922 return ERROR_OUTOFMEMORY
;
1924 memcpy( ptr
, bits
.ptr
, get_dib_image_size( info
));
1925 if (bits
.free
) bits
.free( &bits
);
1927 bits
.is_copy
= TRUE
;
1928 bits
.free
= free_heap_bits
;
1933 /* make x,y relative to the image bits */
1934 x
+= src
.visrect
.left
- dst
.visrect
.left
;
1935 y
+= src
.visrect
.top
- dst
.visrect
.top
;
1936 render_aa_text_bitmapinfo( dev
->hdc
, info
, &bits
, &src
, x
, y
, flags
,
1937 aa_flags
, str
, count
, dx
);
1938 err
= dst_dev
->funcs
->pPutImage( dst_dev
, 0, 0, info
, &bits
, &src
, &dst
, SRCCOPY
);
1939 if (bits
.free
) bits
.free( &bits
);
1944 pen
= CreatePen( PS_SOLID
, 1, GetTextColor(dev
->hdc
) );
1945 orig
= SelectObject( dev
->hdc
, pen
);
1947 for (i
= 0; i
< count
; i
++)
1949 GLYPHMETRICS metrics
;
1950 struct gdi_image_bits image
;
1952 err
= get_glyph_bitmap( dev
->hdc
, (UINT
)str
[i
], GGO_BITMAP
, &metrics
, &image
);
1955 if (image
.ptr
) draw_glyph( dev
->hdc
, x
, y
, &metrics
, &image
, (flags
& ETO_CLIPPED
) ? rect
: NULL
);
1956 if (image
.free
) image
.free( &image
);
1960 if (flags
& ETO_PDY
)
1963 y
+= dx
[ i
* 2 + 1];
1969 x
+= metrics
.gmCellIncX
;
1970 y
+= metrics
.gmCellIncY
;
1974 SelectObject( dev
->hdc
, orig
);
1975 DeleteObject( pen
);
1980 /***********************************************************************
1981 * ExtTextOutA (GDI32.@)
1985 BOOL WINAPI
ExtTextOutA( HDC hdc
, INT x
, INT y
, UINT flags
,
1986 const RECT
*lprect
, LPCSTR str
, UINT count
, const INT
*lpDx
)
1994 if (flags
& ETO_GLYPH_INDEX
)
1995 return ExtTextOutW( hdc
, x
, y
, flags
, lprect
, (LPCWSTR
)str
, count
, lpDx
);
1997 p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, &codepage
);
2000 unsigned int i
= 0, j
= 0;
2002 /* allocate enough for a ETO_PDY */
2003 lpDxW
= HeapAlloc( GetProcessHeap(), 0, 2*wlen
*sizeof(INT
));
2005 if(IsDBCSLeadByteEx(codepage
, str
[i
]))
2009 lpDxW
[j
++] = lpDx
[i
* 2] + lpDx
[(i
+ 1) * 2];
2010 lpDxW
[j
++] = lpDx
[i
* 2 + 1] + lpDx
[(i
+ 1) * 2 + 1];
2013 lpDxW
[j
++] = lpDx
[i
] + lpDx
[i
+ 1];
2020 lpDxW
[j
++] = lpDx
[i
* 2];
2021 lpDxW
[j
++] = lpDx
[i
* 2 + 1];
2024 lpDxW
[j
++] = lpDx
[i
];
2030 ret
= ExtTextOutW( hdc
, x
, y
, flags
, lprect
, p
, wlen
, lpDxW
);
2032 HeapFree( GetProcessHeap(), 0, p
);
2033 HeapFree( GetProcessHeap(), 0, lpDxW
);
2038 /***********************************************************************
2039 * ExtTextOutW (GDI32.@)
2041 * Draws text using the currently selected font, background color, and text color.
2045 * x,y [I] coordinates of string
2047 * ETO_GRAYED - undocumented on MSDN
2048 * ETO_OPAQUE - use background color for fill the rectangle
2049 * ETO_CLIPPED - clipping text to the rectangle
2050 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
2051 * than encoded characters. Implies ETO_IGNORELANGUAGE
2052 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
2053 * Affects BiDi ordering
2054 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
2055 * ETO_PDY - unimplemented
2056 * ETO_NUMERICSLATIN - unimplemented always assumed -
2057 * do not translate numbers into locale representations
2058 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
2059 * lprect [I] dimensions for clipping or/and opaquing
2060 * str [I] text string
2061 * count [I] number of symbols in string
2062 * lpDx [I] optional parameter with distance between drawing characters
2068 BOOL WINAPI
ExtTextOutW( HDC hdc
, INT x
, INT y
, UINT flags
,
2069 const RECT
*lprect
, LPCWSTR str
, UINT count
, const INT
*lpDx
)
2072 LPWSTR reordered_str
= (LPWSTR
)str
;
2073 WORD
*glyphs
= NULL
;
2074 UINT align
= GetTextAlign( hdc
);
2075 DWORD layout
= GetLayout( hdc
);
2079 double cosEsc
, sinEsc
;
2083 BOOL done_extents
= FALSE
;
2084 POINT
*deltas
= NULL
, width
= {0, 0};
2086 DC
* dc
= get_dc_ptr( hdc
);
2089 static int quietfixme
= 0;
2091 if (!dc
) return FALSE
;
2093 breakRem
= dc
->breakRem
;
2095 if (quietfixme
== 0 && flags
& (ETO_NUMERICSLOCAL
| ETO_NUMERICSLATIN
))
2097 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN unimplemented\n");
2102 physdev
= GET_DC_PHYSDEV( dc
, pExtTextOut
);
2103 type
= GetObjectType(hdc
);
2104 if(type
== OBJ_METADC
|| type
== OBJ_ENHMETADC
)
2106 ret
= physdev
->funcs
->pExtTextOut( physdev
, x
, y
, flags
, lprect
, str
, count
, lpDx
);
2107 release_dc_ptr( dc
);
2112 flags
&= ~ETO_CLIPPED
;
2114 if (flags
& ETO_RTLREADING
) align
|= TA_RTLREADING
;
2115 if (layout
& LAYOUT_RTL
)
2117 if ((align
& TA_CENTER
) != TA_CENTER
) align
^= TA_RIGHT
;
2118 align
^= TA_RTLREADING
;
2121 if( !(flags
& (ETO_GLYPH_INDEX
| ETO_IGNORELANGUAGE
)) && count
> 0 )
2124 reordered_str
= HeapAlloc(GetProcessHeap(), 0, count
*sizeof(WCHAR
));
2126 BIDI_Reorder( hdc
, str
, count
, GCP_REORDER
,
2127 (align
& TA_RTLREADING
) ? WINE_GCPW_FORCE_RTL
: WINE_GCPW_FORCE_LTR
,
2128 reordered_str
, count
, NULL
, &glyphs
, &cGlyphs
);
2130 flags
|= ETO_IGNORELANGUAGE
;
2133 flags
|= ETO_GLYPH_INDEX
;
2134 if (cGlyphs
!= count
)
2138 else if(flags
& ETO_GLYPH_INDEX
)
2139 glyphs
= reordered_str
;
2141 TRACE("%p, %d, %d, %08x, %s, %s, %d, %p)\n", hdc
, x
, y
, flags
,
2142 wine_dbgstr_rect(lprect
), debugstr_wn(str
, count
), count
, lpDx
);
2143 TRACE("align = %x bkmode = %x mapmode = %x\n", align
, GetBkMode(hdc
), GetMapMode(hdc
));
2145 if(align
& TA_UPDATECP
)
2147 GetCurrentPositionEx( hdc
, &pt
);
2152 GetTextMetricsW(hdc
, &tm
);
2153 GetObjectW(GetCurrentObject(hdc
, OBJ_FONT
), sizeof(lf
), &lf
);
2155 if(!(tm
.tmPitchAndFamily
& TMPF_VECTOR
)) /* Non-scalable fonts shouldn't be rotated */
2156 lf
.lfEscapement
= 0;
2158 if(lf
.lfEscapement
!= 0)
2160 cosEsc
= cos(lf
.lfEscapement
* M_PI
/ 1800);
2161 sinEsc
= sin(lf
.lfEscapement
* M_PI
/ 1800);
2169 if(flags
& (ETO_CLIPPED
| ETO_OPAQUE
))
2173 if(flags
& ETO_GLYPH_INDEX
)
2174 GetTextExtentPointI(hdc
, glyphs
, count
, &sz
);
2176 GetTextExtentPointW(hdc
, reordered_str
, count
, &sz
);
2178 done_extents
= TRUE
;
2181 rc
.right
= x
+ sz
.cx
;
2182 rc
.bottom
= y
+ sz
.cy
;
2189 LPtoDP(hdc
, (POINT
*)&rc
, 2);
2191 if(rc
.left
> rc
.right
) {INT tmp
= rc
.left
; rc
.left
= rc
.right
; rc
.right
= tmp
;}
2192 if(rc
.top
> rc
.bottom
) {INT tmp
= rc
.top
; rc
.top
= rc
.bottom
; rc
.bottom
= tmp
;}
2195 if (flags
& ETO_OPAQUE
)
2196 physdev
->funcs
->pExtTextOut( physdev
, 0, 0, ETO_OPAQUE
, &rc
, NULL
, 0, NULL
);
2206 LPtoDP(hdc
, &pt
, 1);
2210 char_extra
= GetTextCharacterExtra(hdc
);
2211 if(char_extra
|| dc
->breakExtra
|| breakRem
|| lpDx
|| lf
.lfEscapement
!= 0)
2215 POINT total
= {0, 0}, desired
[2];
2217 deltas
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(*deltas
));
2218 for(i
= 0; i
< count
; i
++)
2224 deltas
[i
].x
= lpDx
[i
* 2] + char_extra
;
2225 deltas
[i
].y
= -lpDx
[i
* 2 + 1];
2229 deltas
[i
].x
= lpDx
[i
] + char_extra
;
2236 if(flags
& ETO_GLYPH_INDEX
)
2237 GetTextExtentPointI(hdc
, glyphs
+ i
, 1, &tmpsz
);
2239 GetTextExtentPointW(hdc
, reordered_str
+ i
, 1, &tmpsz
);
2241 deltas
[i
].x
= tmpsz
.cx
;
2245 if (!(flags
& ETO_GLYPH_INDEX
) && (dc
->breakExtra
|| breakRem
) && reordered_str
[i
] == tm
.tmBreakChar
)
2247 deltas
[i
].x
= deltas
[i
].x
+ dc
->breakExtra
;
2254 total
.x
+= deltas
[i
].x
;
2255 total
.y
+= deltas
[i
].y
;
2257 desired
[0].x
= desired
[0].y
= 0;
2259 desired
[1].x
= cosEsc
* total
.x
+ sinEsc
* total
.y
;
2260 desired
[1].y
= -sinEsc
* total
.x
+ cosEsc
* total
.y
;
2262 LPtoDP(hdc
, desired
, 2);
2263 desired
[1].x
-= desired
[0].x
;
2264 desired
[1].y
-= desired
[0].y
;
2265 if (layout
& LAYOUT_RTL
) desired
[1].x
= -desired
[1].x
;
2267 deltas
[i
].x
= desired
[1].x
- width
.x
;
2268 deltas
[i
].y
= desired
[1].y
- width
.y
;
2278 if(flags
& ETO_GLYPH_INDEX
)
2279 GetTextExtentPointI(hdc
, glyphs
, count
, &sz
);
2281 GetTextExtentPointW(hdc
, reordered_str
, count
, &sz
);
2282 done_extents
= TRUE
;
2284 width
.x
= abs(INTERNAL_XWSTODS(dc
, sz
.cx
));
2288 tm
.tmAscent
= abs(INTERNAL_YWSTODS(dc
, tm
.tmAscent
));
2289 tm
.tmDescent
= abs(INTERNAL_YWSTODS(dc
, tm
.tmDescent
));
2290 switch( align
& (TA_LEFT
| TA_RIGHT
| TA_CENTER
) )
2293 if (align
& TA_UPDATECP
)
2297 DPtoLP(hdc
, &pt
, 1);
2298 MoveToEx(hdc
, pt
.x
, pt
.y
, NULL
);
2310 if (align
& TA_UPDATECP
)
2314 DPtoLP(hdc
, &pt
, 1);
2315 MoveToEx(hdc
, pt
.x
, pt
.y
, NULL
);
2320 switch( align
& (TA_TOP
| TA_BOTTOM
| TA_BASELINE
) )
2323 y
+= tm
.tmAscent
* cosEsc
;
2324 x
+= tm
.tmAscent
* sinEsc
;
2328 y
-= tm
.tmDescent
* cosEsc
;
2329 x
-= tm
.tmDescent
* sinEsc
;
2336 if (GetBkMode(hdc
) != TRANSPARENT
)
2338 if(!((flags
& ETO_CLIPPED
) && (flags
& ETO_OPAQUE
)))
2340 if(!(flags
& ETO_OPAQUE
) || x
< rc
.left
|| x
+ width
.x
>= rc
.right
||
2341 y
- tm
.tmAscent
< rc
.top
|| y
+ tm
.tmDescent
>= rc
.bottom
)
2345 rc
.right
= x
+ width
.x
;
2346 rc
.top
= y
- tm
.tmAscent
;
2347 rc
.bottom
= y
+ tm
.tmDescent
;
2349 if(flags
& ETO_CLIPPED
)
2351 rc
.left
= max(lprect
->left
, rc
.left
);
2352 rc
.right
= min(lprect
->right
, rc
.right
);
2353 rc
.top
= max(lprect
->top
, rc
.top
);
2354 rc
.bottom
= min(lprect
->bottom
, rc
.bottom
);
2356 if(rc
.left
< rc
.right
&& rc
.top
< rc
.bottom
)
2357 physdev
->funcs
->pExtTextOut( physdev
, 0, 0, ETO_OPAQUE
, &rc
, NULL
, 0, NULL
);
2362 if(FontIsLinked(hdc
) && !(flags
& ETO_GLYPH_INDEX
))
2364 HFONT orig_font
= dc
->hFont
, cur_font
;
2367 POINT
*offsets
= NULL
;
2370 glyphs
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(WORD
));
2371 for(i
= 0; i
< count
; i
++)
2373 WineEngGetLinkedHFont(dc
, reordered_str
[i
], &cur_font
, &glyph
);
2374 if(cur_font
!= dc
->hFont
)
2379 offsets
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(*deltas
));
2380 offsets
[0].x
= offsets
[0].y
= 0;
2385 for(j
= 1; j
< count
; j
++)
2387 GetTextExtentPointW(hdc
, reordered_str
+ j
- 1, 1, &tmpsz
);
2388 offsets
[j
].x
= offsets
[j
- 1].x
+ abs(INTERNAL_XWSTODS(dc
, tmpsz
.cx
));
2394 for(j
= 1; j
< count
; j
++)
2396 offsets
[j
].x
= offsets
[j
- 1].x
+ deltas
[j
].x
;
2397 offsets
[j
].y
= offsets
[j
- 1].y
+ deltas
[j
].y
;
2403 physdev
->funcs
->pExtTextOut( physdev
, x
+ offsets
[i
- span
].x
,
2404 y
+ offsets
[i
- span
].y
,
2405 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
, glyphs
,
2406 span
, deltas
? (INT
*)(deltas
+ (i
- span
)) : NULL
);
2409 SelectObject(hdc
, cur_font
);
2411 glyphs
[span
++] = glyph
;
2415 ret
= physdev
->funcs
->pExtTextOut(physdev
, x
+ (offsets
? offsets
[count
- span
].x
: 0),
2416 y
+ (offsets
? offsets
[count
- span
].y
: 0),
2417 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
, glyphs
,
2418 span
, deltas
? (INT
*)(deltas
+ (count
- span
)) : NULL
);
2419 SelectObject(hdc
, orig_font
);
2420 HeapFree(GetProcessHeap(), 0, offsets
);
2426 if(!(flags
& ETO_GLYPH_INDEX
) && dc
->gdiFont
)
2428 glyphs
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(WORD
));
2429 GetGlyphIndicesW(hdc
, reordered_str
, count
, glyphs
, 0);
2430 flags
|= ETO_GLYPH_INDEX
;
2432 ret
= physdev
->funcs
->pExtTextOut( physdev
, x
, y
, (flags
& ~ETO_OPAQUE
), &rc
,
2433 glyphs
? glyphs
: reordered_str
, count
, (INT
*)deltas
);
2437 HeapFree(GetProcessHeap(), 0, deltas
);
2438 if(glyphs
!= reordered_str
)
2439 HeapFree(GetProcessHeap(), 0, glyphs
);
2440 if(reordered_str
!= str
)
2441 HeapFree(GetProcessHeap(), 0, reordered_str
);
2443 release_dc_ptr( dc
);
2445 if (ret
&& (lf
.lfUnderline
|| lf
.lfStrikeOut
))
2447 int underlinePos
, strikeoutPos
;
2448 int underlineWidth
, strikeoutWidth
;
2449 UINT size
= GetOutlineTextMetricsW(hdc
, 0, NULL
);
2450 OUTLINETEXTMETRICW
* otm
= NULL
;
2452 HPEN hpen
= SelectObject(hdc
, GetStockObject(NULL_PEN
));
2453 HBRUSH hbrush
= CreateSolidBrush(GetTextColor(hdc
));
2455 hbrush
= SelectObject(hdc
, hbrush
);
2460 underlineWidth
= tm
.tmAscent
/ 20 + 1;
2461 strikeoutPos
= tm
.tmAscent
/ 2;
2462 strikeoutWidth
= underlineWidth
;
2466 otm
= HeapAlloc(GetProcessHeap(), 0, size
);
2467 GetOutlineTextMetricsW(hdc
, size
, otm
);
2468 underlinePos
= abs( INTERNAL_YWSTODS( dc
, otm
->otmsUnderscorePosition
));
2469 if (otm
->otmsUnderscorePosition
< 0) underlinePos
= -underlinePos
;
2470 underlineWidth
= abs( INTERNAL_YWSTODS( dc
, otm
->otmsUnderscoreSize
));
2471 if (otm
->otmsUnderscoreSize
< 0) underlineWidth
= -underlineWidth
;
2472 strikeoutPos
= abs( INTERNAL_YWSTODS( dc
, otm
->otmsStrikeoutPosition
));
2473 if (otm
->otmsStrikeoutPosition
< 0) strikeoutPos
= -strikeoutPos
;
2474 strikeoutWidth
= abs( INTERNAL_YWSTODS( dc
, otm
->otmsStrikeoutSize
));
2475 HeapFree(GetProcessHeap(), 0, otm
);
2481 pts
[0].x
= x
- (underlinePos
+ underlineWidth
/ 2) * sinEsc
;
2482 pts
[0].y
= y
- (underlinePos
+ underlineWidth
/ 2) * cosEsc
;
2483 pts
[1].x
= x
+ width
.x
- (underlinePos
+ underlineWidth
/ 2) * sinEsc
;
2484 pts
[1].y
= y
+ width
.y
- (underlinePos
+ underlineWidth
/ 2) * cosEsc
;
2485 pts
[2].x
= pts
[1].x
+ underlineWidth
* sinEsc
;
2486 pts
[2].y
= pts
[1].y
+ underlineWidth
* cosEsc
;
2487 pts
[3].x
= pts
[0].x
+ underlineWidth
* sinEsc
;
2488 pts
[3].y
= pts
[0].y
+ underlineWidth
* cosEsc
;
2489 pts
[4].x
= pts
[0].x
;
2490 pts
[4].y
= pts
[0].y
;
2491 DPtoLP(hdc
, pts
, 5);
2492 Polygon(hdc
, pts
, 5);
2497 pts
[0].x
= x
- (strikeoutPos
+ strikeoutWidth
/ 2) * sinEsc
;
2498 pts
[0].y
= y
- (strikeoutPos
+ strikeoutWidth
/ 2) * cosEsc
;
2499 pts
[1].x
= x
+ width
.x
- (strikeoutPos
+ strikeoutWidth
/ 2) * sinEsc
;
2500 pts
[1].y
= y
+ width
.y
- (strikeoutPos
+ strikeoutWidth
/ 2) * cosEsc
;
2501 pts
[2].x
= pts
[1].x
+ strikeoutWidth
* sinEsc
;
2502 pts
[2].y
= pts
[1].y
+ strikeoutWidth
* cosEsc
;
2503 pts
[3].x
= pts
[0].x
+ strikeoutWidth
* sinEsc
;
2504 pts
[3].y
= pts
[0].y
+ strikeoutWidth
* cosEsc
;
2505 pts
[4].x
= pts
[0].x
;
2506 pts
[4].y
= pts
[0].y
;
2507 DPtoLP(hdc
, pts
, 5);
2508 Polygon(hdc
, pts
, 5);
2511 SelectObject(hdc
, hpen
);
2512 hbrush
= SelectObject(hdc
, hbrush
);
2513 DeleteObject(hbrush
);
2520 /***********************************************************************
2521 * TextOutA (GDI32.@)
2523 BOOL WINAPI
TextOutA( HDC hdc
, INT x
, INT y
, LPCSTR str
, INT count
)
2525 return ExtTextOutA( hdc
, x
, y
, 0, NULL
, str
, count
, NULL
);
2529 /***********************************************************************
2530 * TextOutW (GDI32.@)
2532 BOOL WINAPI
TextOutW(HDC hdc
, INT x
, INT y
, LPCWSTR str
, INT count
)
2534 return ExtTextOutW( hdc
, x
, y
, 0, NULL
, str
, count
, NULL
);
2538 /***********************************************************************
2539 * PolyTextOutA (GDI32.@)
2543 BOOL WINAPI
PolyTextOutA( HDC hdc
, const POLYTEXTA
*pptxt
, INT cStrings
)
2545 for (; cStrings
>0; cStrings
--, pptxt
++)
2546 if (!ExtTextOutA( hdc
, pptxt
->x
, pptxt
->y
, pptxt
->uiFlags
, &pptxt
->rcl
, pptxt
->lpstr
, pptxt
->n
, pptxt
->pdx
))
2553 /***********************************************************************
2554 * PolyTextOutW (GDI32.@)
2556 * Draw several Strings
2562 BOOL WINAPI
PolyTextOutW( HDC hdc
, const POLYTEXTW
*pptxt
, INT cStrings
)
2564 for (; cStrings
>0; cStrings
--, pptxt
++)
2565 if (!ExtTextOutW( hdc
, pptxt
->x
, pptxt
->y
, pptxt
->uiFlags
, &pptxt
->rcl
, pptxt
->lpstr
, pptxt
->n
, pptxt
->pdx
))
2571 /***********************************************************************
2572 * SetMapperFlags (GDI32.@)
2574 DWORD WINAPI
SetMapperFlags( HDC hdc
, DWORD flags
)
2576 DC
*dc
= get_dc_ptr( hdc
);
2577 DWORD ret
= GDI_ERROR
;
2581 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetMapperFlags
);
2582 flags
= physdev
->funcs
->pSetMapperFlags( physdev
, flags
);
2583 if (flags
!= GDI_ERROR
)
2585 ret
= dc
->mapperFlags
;
2586 dc
->mapperFlags
= flags
;
2588 release_dc_ptr( dc
);
2593 /***********************************************************************
2594 * GetAspectRatioFilterEx (GDI32.@)
2596 BOOL WINAPI
GetAspectRatioFilterEx( HDC hdc
, LPSIZE pAspectRatio
)
2598 FIXME("(%p, %p): -- Empty Stub !\n", hdc
, pAspectRatio
);
2603 /***********************************************************************
2604 * GetCharABCWidthsA (GDI32.@)
2606 * See GetCharABCWidthsW.
2608 BOOL WINAPI
GetCharABCWidthsA(HDC hdc
, UINT firstChar
, UINT lastChar
,
2616 str
= FONT_GetCharsByRangeA(hdc
, firstChar
, lastChar
, &i
);
2620 wstr
= FONT_mbtowc(hdc
, str
, i
, &wlen
, NULL
);
2623 HeapFree(GetProcessHeap(), 0, str
);
2627 for(i
= 0; i
< wlen
; i
++)
2629 if(!GetCharABCWidthsW(hdc
, wstr
[i
], wstr
[i
], abc
))
2637 HeapFree(GetProcessHeap(), 0, str
);
2638 HeapFree(GetProcessHeap(), 0, wstr
);
2644 /******************************************************************************
2645 * GetCharABCWidthsW [GDI32.@]
2647 * Retrieves widths of characters in range.
2650 * hdc [I] Handle of device context
2651 * firstChar [I] First character in range to query
2652 * lastChar [I] Last character in range to query
2653 * abc [O] Address of character-width structure
2656 * Only works with TrueType fonts
2662 BOOL WINAPI
GetCharABCWidthsW( HDC hdc
, UINT firstChar
, UINT lastChar
,
2665 DC
*dc
= get_dc_ptr(hdc
);
2671 if (!dc
) return FALSE
;
2675 release_dc_ptr( dc
);
2679 /* unlike GetCharABCWidthsFloatW, this one is supposed to fail on non-TrueType fonts */
2680 dev
= GET_DC_PHYSDEV( dc
, pGetTextMetrics
);
2681 if (!dev
->funcs
->pGetTextMetrics( dev
, &tm
) || !(tm
.tmPitchAndFamily
& TMPF_TRUETYPE
))
2683 release_dc_ptr( dc
);
2687 dev
= GET_DC_PHYSDEV( dc
, pGetCharABCWidths
);
2688 ret
= dev
->funcs
->pGetCharABCWidths( dev
, firstChar
, lastChar
, abc
);
2691 /* convert device units to logical */
2692 for( i
= firstChar
; i
<= lastChar
; i
++, abc
++ ) {
2693 abc
->abcA
= INTERNAL_XDSTOWS(dc
, abc
->abcA
);
2694 abc
->abcB
= INTERNAL_XDSTOWS(dc
, abc
->abcB
);
2695 abc
->abcC
= INTERNAL_XDSTOWS(dc
, abc
->abcC
);
2699 release_dc_ptr( dc
);
2704 /******************************************************************************
2705 * GetCharABCWidthsI [GDI32.@]
2707 * Retrieves widths of characters in range.
2710 * hdc [I] Handle of device context
2711 * firstChar [I] First glyphs in range to query
2712 * count [I] Last glyphs in range to query
2713 * pgi [i] Array of glyphs to query
2714 * abc [O] Address of character-width structure
2717 * Only works with TrueType fonts
2723 BOOL WINAPI
GetCharABCWidthsI( HDC hdc
, UINT firstChar
, UINT count
,
2724 LPWORD pgi
, LPABC abc
)
2726 DC
*dc
= get_dc_ptr(hdc
);
2731 if (!dc
) return FALSE
;
2735 release_dc_ptr( dc
);
2739 dev
= GET_DC_PHYSDEV( dc
, pGetCharABCWidthsI
);
2740 ret
= dev
->funcs
->pGetCharABCWidthsI( dev
, firstChar
, count
, pgi
, abc
);
2743 /* convert device units to logical */
2744 for( i
= 0; i
< count
; i
++, abc
++ ) {
2745 abc
->abcA
= INTERNAL_XDSTOWS(dc
, abc
->abcA
);
2746 abc
->abcB
= INTERNAL_XDSTOWS(dc
, abc
->abcB
);
2747 abc
->abcC
= INTERNAL_XDSTOWS(dc
, abc
->abcC
);
2751 release_dc_ptr( dc
);
2756 /***********************************************************************
2757 * GetGlyphOutlineA (GDI32.@)
2759 DWORD WINAPI
GetGlyphOutlineA( HDC hdc
, UINT uChar
, UINT fuFormat
,
2760 LPGLYPHMETRICS lpgm
, DWORD cbBuffer
,
2761 LPVOID lpBuffer
, const MAT2
*lpmat2
)
2763 if (!lpmat2
) return GDI_ERROR
;
2765 if(!(fuFormat
& GGO_GLYPH_INDEX
)) {
2770 cp
= GdiGetCodePage(hdc
);
2771 if (IsDBCSLeadByteEx(cp
, uChar
>> 8)) {
2773 mbchs
[0] = (uChar
& 0xff00) >> 8;
2774 mbchs
[1] = (uChar
& 0xff);
2777 mbchs
[0] = (uChar
& 0xff);
2780 MultiByteToWideChar(cp
, 0, mbchs
, len
, (LPWSTR
)&uChar
, 1);
2783 return GetGlyphOutlineW(hdc
, uChar
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
,
2787 /***********************************************************************
2788 * GetGlyphOutlineW (GDI32.@)
2790 DWORD WINAPI
GetGlyphOutlineW( HDC hdc
, UINT uChar
, UINT fuFormat
,
2791 LPGLYPHMETRICS lpgm
, DWORD cbBuffer
,
2792 LPVOID lpBuffer
, const MAT2
*lpmat2
)
2798 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2799 hdc
, uChar
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
, lpmat2
);
2801 if (!lpmat2
) return GDI_ERROR
;
2803 dc
= get_dc_ptr(hdc
);
2804 if(!dc
) return GDI_ERROR
;
2806 dev
= GET_DC_PHYSDEV( dc
, pGetGlyphOutline
);
2807 ret
= dev
->funcs
->pGetGlyphOutline( dev
, uChar
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
, lpmat2
);
2808 release_dc_ptr( dc
);
2813 /***********************************************************************
2814 * CreateScalableFontResourceA (GDI32.@)
2816 BOOL WINAPI
CreateScalableFontResourceA( DWORD fHidden
,
2817 LPCSTR lpszResourceFile
,
2818 LPCSTR lpszFontFile
,
2819 LPCSTR lpszCurrentPath
)
2821 LPWSTR lpszResourceFileW
= NULL
;
2822 LPWSTR lpszFontFileW
= NULL
;
2823 LPWSTR lpszCurrentPathW
= NULL
;
2827 if (lpszResourceFile
)
2829 len
= MultiByteToWideChar(CP_ACP
, 0, lpszResourceFile
, -1, NULL
, 0);
2830 lpszResourceFileW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2831 MultiByteToWideChar(CP_ACP
, 0, lpszResourceFile
, -1, lpszResourceFileW
, len
);
2836 len
= MultiByteToWideChar(CP_ACP
, 0, lpszFontFile
, -1, NULL
, 0);
2837 lpszFontFileW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2838 MultiByteToWideChar(CP_ACP
, 0, lpszFontFile
, -1, lpszFontFileW
, len
);
2841 if (lpszCurrentPath
)
2843 len
= MultiByteToWideChar(CP_ACP
, 0, lpszCurrentPath
, -1, NULL
, 0);
2844 lpszCurrentPathW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2845 MultiByteToWideChar(CP_ACP
, 0, lpszCurrentPath
, -1, lpszCurrentPathW
, len
);
2848 ret
= CreateScalableFontResourceW(fHidden
, lpszResourceFileW
,
2849 lpszFontFileW
, lpszCurrentPathW
);
2851 HeapFree(GetProcessHeap(), 0, lpszResourceFileW
);
2852 HeapFree(GetProcessHeap(), 0, lpszFontFileW
);
2853 HeapFree(GetProcessHeap(), 0, lpszCurrentPathW
);
2858 /***********************************************************************
2859 * CreateScalableFontResourceW (GDI32.@)
2861 BOOL WINAPI
CreateScalableFontResourceW( DWORD fHidden
,
2862 LPCWSTR lpszResourceFile
,
2863 LPCWSTR lpszFontFile
,
2864 LPCWSTR lpszCurrentPath
)
2867 FIXME("(%d,%s,%s,%s): stub\n",
2868 fHidden
, debugstr_w(lpszResourceFile
), debugstr_w(lpszFontFile
),
2869 debugstr_w(lpszCurrentPath
) );
2871 /* fHidden=1 - only visible for the calling app, read-only, not
2872 * enumerated with EnumFonts/EnumFontFamilies
2873 * lpszCurrentPath can be NULL
2876 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2877 if ((f
= CreateFileW(lpszResourceFile
, 0, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, 0)) != INVALID_HANDLE_VALUE
) {
2879 SetLastError(ERROR_FILE_EXISTS
);
2882 return FALSE
; /* create failed */
2885 /*************************************************************************
2886 * GetKerningPairsA (GDI32.@)
2888 DWORD WINAPI
GetKerningPairsA( HDC hDC
, DWORD cPairs
,
2889 LPKERNINGPAIR kern_pairA
)
2893 DWORD i
, total_kern_pairs
, kern_pairs_copied
= 0;
2894 KERNINGPAIR
*kern_pairW
;
2896 if (!cPairs
&& kern_pairA
)
2898 SetLastError(ERROR_INVALID_PARAMETER
);
2902 cp
= GdiGetCodePage(hDC
);
2904 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2905 * to fail on an invalid character for CP_SYMBOL.
2907 cpi
.DefaultChar
[0] = 0;
2908 if (cp
!= CP_SYMBOL
&& !GetCPInfo(cp
, &cpi
))
2910 FIXME("Can't find codepage %u info\n", cp
);
2914 total_kern_pairs
= GetKerningPairsW(hDC
, 0, NULL
);
2915 if (!total_kern_pairs
) return 0;
2917 kern_pairW
= HeapAlloc(GetProcessHeap(), 0, total_kern_pairs
* sizeof(*kern_pairW
));
2918 GetKerningPairsW(hDC
, total_kern_pairs
, kern_pairW
);
2920 for (i
= 0; i
< total_kern_pairs
; i
++)
2924 if (!WideCharToMultiByte(cp
, 0, &kern_pairW
[i
].wFirst
, 1, &first
, 1, NULL
, NULL
))
2927 if (!WideCharToMultiByte(cp
, 0, &kern_pairW
[i
].wSecond
, 1, &second
, 1, NULL
, NULL
))
2930 if (first
== cpi
.DefaultChar
[0] || second
== cpi
.DefaultChar
[0])
2935 if (kern_pairs_copied
>= cPairs
) break;
2937 kern_pairA
->wFirst
= (BYTE
)first
;
2938 kern_pairA
->wSecond
= (BYTE
)second
;
2939 kern_pairA
->iKernAmount
= kern_pairW
[i
].iKernAmount
;
2942 kern_pairs_copied
++;
2945 HeapFree(GetProcessHeap(), 0, kern_pairW
);
2947 return kern_pairs_copied
;
2950 /*************************************************************************
2951 * GetKerningPairsW (GDI32.@)
2953 DWORD WINAPI
GetKerningPairsW( HDC hDC
, DWORD cPairs
,
2954 LPKERNINGPAIR lpKerningPairs
)
2960 TRACE("(%p,%d,%p)\n", hDC
, cPairs
, lpKerningPairs
);
2962 if (!cPairs
&& lpKerningPairs
)
2964 SetLastError(ERROR_INVALID_PARAMETER
);
2968 dc
= get_dc_ptr(hDC
);
2971 dev
= GET_DC_PHYSDEV( dc
, pGetKerningPairs
);
2972 ret
= dev
->funcs
->pGetKerningPairs( dev
, cPairs
, lpKerningPairs
);
2973 release_dc_ptr( dc
);
2977 /*************************************************************************
2978 * TranslateCharsetInfo [GDI32.@]
2980 * Fills a CHARSETINFO structure for a character set, code page, or
2981 * font. This allows making the correspondence between different labels
2982 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2983 * of the same encoding.
2985 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2986 * only one codepage should be set in *lpSrc.
2989 * TRUE on success, FALSE on failure.
2992 BOOL WINAPI
TranslateCharsetInfo(
2993 LPDWORD lpSrc
, /* [in]
2994 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2995 if flags == TCI_SRCCHARSET: a character set value
2996 if flags == TCI_SRCCODEPAGE: a code page value
2998 LPCHARSETINFO lpCs
, /* [out] structure to receive charset information */
2999 DWORD flags
/* [in] determines interpretation of lpSrc */)
3003 case TCI_SRCFONTSIG
:
3004 while (index
< MAXTCIINDEX
&& !(*lpSrc
>>index
& 0x0001)) index
++;
3006 case TCI_SRCCODEPAGE
:
3007 while (index
< MAXTCIINDEX
&& PtrToUlong(lpSrc
) != FONT_tci
[index
].ciACP
) index
++;
3009 case TCI_SRCCHARSET
:
3010 while (index
< MAXTCIINDEX
&& PtrToUlong(lpSrc
) != FONT_tci
[index
].ciCharset
) index
++;
3015 if (index
>= MAXTCIINDEX
|| FONT_tci
[index
].ciCharset
== DEFAULT_CHARSET
) return FALSE
;
3016 *lpCs
= FONT_tci
[index
];
3020 /*************************************************************************
3021 * GetFontLanguageInfo (GDI32.@)
3023 DWORD WINAPI
GetFontLanguageInfo(HDC hdc
)
3025 FONTSIGNATURE fontsig
;
3026 static const DWORD GCP_DBCS_MASK
=0x003F0000,
3027 GCP_DIACRITIC_MASK
=0x00000000,
3028 FLI_GLYPHS_MASK
=0x00000000,
3029 GCP_GLYPHSHAPE_MASK
=0x00000040,
3030 GCP_KASHIDA_MASK
=0x00000000,
3031 GCP_LIGATE_MASK
=0x00000000,
3032 GCP_USEKERNING_MASK
=0x00000000,
3033 GCP_REORDER_MASK
=0x00000060;
3037 GetTextCharsetInfo( hdc
, &fontsig
, 0 );
3038 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
3040 if( (fontsig
.fsCsb
[0]&GCP_DBCS_MASK
)!=0 )
3043 if( (fontsig
.fsCsb
[0]&GCP_DIACRITIC_MASK
)!=0 )
3044 result
|=GCP_DIACRITIC
;
3046 if( (fontsig
.fsCsb
[0]&FLI_GLYPHS_MASK
)!=0 )
3049 if( (fontsig
.fsCsb
[0]&GCP_GLYPHSHAPE_MASK
)!=0 )
3050 result
|=GCP_GLYPHSHAPE
;
3052 if( (fontsig
.fsCsb
[0]&GCP_KASHIDA_MASK
)!=0 )
3053 result
|=GCP_KASHIDA
;
3055 if( (fontsig
.fsCsb
[0]&GCP_LIGATE_MASK
)!=0 )
3058 if( (fontsig
.fsCsb
[0]&GCP_USEKERNING_MASK
)!=0 )
3059 result
|=GCP_USEKERNING
;
3061 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
3062 if( GetTextAlign( hdc
) & TA_RTLREADING
)
3063 if( (fontsig
.fsCsb
[0]&GCP_REORDER_MASK
)!=0 )
3064 result
|=GCP_REORDER
;
3070 /*************************************************************************
3071 * GetFontData [GDI32.@]
3073 * Retrieve data for TrueType font.
3077 * success: Number of bytes returned
3078 * failure: GDI_ERROR
3082 * Calls SetLastError()
3085 DWORD WINAPI
GetFontData(HDC hdc
, DWORD table
, DWORD offset
,
3086 LPVOID buffer
, DWORD length
)
3088 DC
*dc
= get_dc_ptr(hdc
);
3092 if(!dc
) return GDI_ERROR
;
3094 dev
= GET_DC_PHYSDEV( dc
, pGetFontData
);
3095 ret
= dev
->funcs
->pGetFontData( dev
, table
, offset
, buffer
, length
);
3096 release_dc_ptr( dc
);
3100 /*************************************************************************
3101 * GetGlyphIndicesA [GDI32.@]
3103 DWORD WINAPI
GetGlyphIndicesA(HDC hdc
, LPCSTR lpstr
, INT count
,
3104 LPWORD pgi
, DWORD flags
)
3110 TRACE("(%p, %s, %d, %p, 0x%x)\n",
3111 hdc
, debugstr_an(lpstr
, count
), count
, pgi
, flags
);
3113 lpstrW
= FONT_mbtowc(hdc
, lpstr
, count
, &countW
, NULL
);
3114 ret
= GetGlyphIndicesW(hdc
, lpstrW
, countW
, pgi
, flags
);
3115 HeapFree(GetProcessHeap(), 0, lpstrW
);
3120 /*************************************************************************
3121 * GetGlyphIndicesW [GDI32.@]
3123 DWORD WINAPI
GetGlyphIndicesW(HDC hdc
, LPCWSTR lpstr
, INT count
,
3124 LPWORD pgi
, DWORD flags
)
3126 DC
*dc
= get_dc_ptr(hdc
);
3130 TRACE("(%p, %s, %d, %p, 0x%x)\n",
3131 hdc
, debugstr_wn(lpstr
, count
), count
, pgi
, flags
);
3133 if(!dc
) return GDI_ERROR
;
3135 dev
= GET_DC_PHYSDEV( dc
, pGetGlyphIndices
);
3136 ret
= dev
->funcs
->pGetGlyphIndices( dev
, lpstr
, count
, pgi
, flags
);
3137 release_dc_ptr( dc
);
3141 /*************************************************************************
3142 * GetCharacterPlacementA [GDI32.@]
3144 * See GetCharacterPlacementW.
3147 * the web browser control of ie4 calls this with dwFlags=0
3150 GetCharacterPlacementA(HDC hdc
, LPCSTR lpString
, INT uCount
,
3151 INT nMaxExtent
, GCP_RESULTSA
*lpResults
,
3156 GCP_RESULTSW resultsW
;
3160 TRACE("%s, %d, %d, 0x%08x\n",
3161 debugstr_an(lpString
, uCount
), uCount
, nMaxExtent
, dwFlags
);
3163 /* both structs are equal in size */
3164 memcpy(&resultsW
, lpResults
, sizeof(resultsW
));
3166 lpStringW
= FONT_mbtowc(hdc
, lpString
, uCount
, &uCountW
, &font_cp
);
3167 if(lpResults
->lpOutString
)
3168 resultsW
.lpOutString
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*uCountW
);
3170 ret
= GetCharacterPlacementW(hdc
, lpStringW
, uCountW
, nMaxExtent
, &resultsW
, dwFlags
);
3172 lpResults
->nGlyphs
= resultsW
.nGlyphs
;
3173 lpResults
->nMaxFit
= resultsW
.nMaxFit
;
3175 if(lpResults
->lpOutString
) {
3176 WideCharToMultiByte(font_cp
, 0, resultsW
.lpOutString
, uCountW
,
3177 lpResults
->lpOutString
, uCount
, NULL
, NULL
);
3180 HeapFree(GetProcessHeap(), 0, lpStringW
);
3181 HeapFree(GetProcessHeap(), 0, resultsW
.lpOutString
);
3186 /*************************************************************************
3187 * GetCharacterPlacementW [GDI32.@]
3189 * Retrieve information about a string. This includes the width, reordering,
3190 * Glyphing and so on.
3194 * The width and height of the string if successful, 0 if failed.
3198 * All flags except GCP_REORDER are not yet implemented.
3199 * Reordering is not 100% compliant to the Windows BiDi method.
3200 * Caret positioning is not yet implemented for BiDi.
3201 * Classes are not yet implemented.
3205 GetCharacterPlacementW(
3206 HDC hdc
, /* [in] Device context for which the rendering is to be done */
3207 LPCWSTR lpString
, /* [in] The string for which information is to be returned */
3208 INT uCount
, /* [in] Number of WORDS in string. */
3209 INT nMaxExtent
, /* [in] Maximum extent the string is to take (in HDC logical units) */
3210 GCP_RESULTSW
*lpResults
,/* [in/out] A pointer to a GCP_RESULTSW struct */
3211 DWORD dwFlags
/* [in] Flags specifying how to process the string */
3218 TRACE("%s, %d, %d, 0x%08x\n",
3219 debugstr_wn(lpString
, uCount
), uCount
, nMaxExtent
, dwFlags
);
3221 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
3222 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
3223 lpResults
->lStructSize
, lpResults
->lpOutString
, lpResults
->lpOrder
,
3224 lpResults
->lpDx
, lpResults
->lpCaretPos
, lpResults
->lpClass
,
3225 lpResults
->lpGlyphs
, lpResults
->nGlyphs
, lpResults
->nMaxFit
);
3227 if(dwFlags
&(~GCP_REORDER
)) FIXME("flags 0x%08x ignored\n", dwFlags
);
3228 if(lpResults
->lpClass
) FIXME("classes not implemented\n");
3229 if (lpResults
->lpCaretPos
&& (dwFlags
& GCP_REORDER
))
3230 FIXME("Caret positions for complex scripts not implemented\n");
3232 nSet
= (UINT
)uCount
;
3233 if(nSet
> lpResults
->nGlyphs
)
3234 nSet
= lpResults
->nGlyphs
;
3236 /* return number of initialized fields */
3237 lpResults
->nGlyphs
= nSet
;
3239 if((dwFlags
&GCP_REORDER
)==0 )
3241 /* Treat the case where no special handling was requested in a fastpath way */
3242 /* copy will do if the GCP_REORDER flag is not set */
3243 if(lpResults
->lpOutString
)
3244 memcpy( lpResults
->lpOutString
, lpString
, nSet
* sizeof(WCHAR
));
3246 if(lpResults
->lpOrder
)
3248 for(i
= 0; i
< nSet
; i
++)
3249 lpResults
->lpOrder
[i
] = i
;
3253 BIDI_Reorder(NULL
, lpString
, uCount
, dwFlags
, WINE_GCPW_FORCE_LTR
, lpResults
->lpOutString
,
3254 nSet
, lpResults
->lpOrder
, NULL
, NULL
);
3257 /* FIXME: Will use the placement chars */
3258 if (lpResults
->lpDx
)
3261 for (i
= 0; i
< nSet
; i
++)
3263 if (GetCharWidth32W(hdc
, lpString
[i
], lpString
[i
], &c
))
3264 lpResults
->lpDx
[i
]= c
;
3268 if (lpResults
->lpCaretPos
&& !(dwFlags
& GCP_REORDER
))
3272 lpResults
->lpCaretPos
[0] = 0;
3273 for (i
= 1; i
< nSet
; i
++)
3274 if (GetTextExtentPoint32W(hdc
, &(lpString
[i
- 1]), 1, &size
))
3275 lpResults
->lpCaretPos
[i
] = (pos
+= size
.cx
);
3278 if(lpResults
->lpGlyphs
)
3279 GetGlyphIndicesW(hdc
, lpString
, nSet
, lpResults
->lpGlyphs
, 0);
3281 if (GetTextExtentPoint32W(hdc
, lpString
, uCount
, &size
))
3282 ret
= MAKELONG(size
.cx
, size
.cy
);
3287 /*************************************************************************
3288 * GetCharABCWidthsFloatA [GDI32.@]
3290 * See GetCharABCWidthsFloatW.
3292 BOOL WINAPI
GetCharABCWidthsFloatA( HDC hdc
, UINT first
, UINT last
, LPABCFLOAT abcf
)
3299 str
= FONT_GetCharsByRangeA(hdc
, first
, last
, &i
);
3303 wstr
= FONT_mbtowc( hdc
, str
, i
, &wlen
, NULL
);
3305 for (i
= 0; i
< wlen
; i
++)
3307 if (!GetCharABCWidthsFloatW( hdc
, wstr
[i
], wstr
[i
], abcf
))
3315 HeapFree( GetProcessHeap(), 0, str
);
3316 HeapFree( GetProcessHeap(), 0, wstr
);
3321 /*************************************************************************
3322 * GetCharABCWidthsFloatW [GDI32.@]
3324 * Retrieves widths of a range of characters.
3327 * hdc [I] Handle to device context.
3328 * first [I] First character in range to query.
3329 * last [I] Last character in range to query.
3330 * abcf [O] Array of LPABCFLOAT structures.
3336 BOOL WINAPI
GetCharABCWidthsFloatW( HDC hdc
, UINT first
, UINT last
, LPABCFLOAT abcf
)
3342 DC
*dc
= get_dc_ptr( hdc
);
3344 TRACE("%p, %d, %d, %p\n", hdc
, first
, last
, abcf
);
3346 if (!dc
) return FALSE
;
3348 if (!abcf
) goto done
;
3349 if (!(abc
= HeapAlloc( GetProcessHeap(), 0, (last
- first
+ 1) * sizeof(*abc
) ))) goto done
;
3351 dev
= GET_DC_PHYSDEV( dc
, pGetCharABCWidths
);
3352 ret
= dev
->funcs
->pGetCharABCWidths( dev
, first
, last
, abc
);
3355 /* convert device units to logical */
3356 for (i
= first
; i
<= last
; i
++, abcf
++)
3358 abcf
->abcfA
= abc
->abcA
* dc
->xformVport2World
.eM11
;
3359 abcf
->abcfB
= abc
->abcB
* dc
->xformVport2World
.eM11
;
3360 abcf
->abcfC
= abc
->abcC
* dc
->xformVport2World
.eM11
;
3363 HeapFree( GetProcessHeap(), 0, abc
);
3366 release_dc_ptr( dc
);
3370 /*************************************************************************
3371 * GetCharWidthFloatA [GDI32.@]
3373 BOOL WINAPI
GetCharWidthFloatA(HDC hdc
, UINT iFirstChar
,
3374 UINT iLastChar
, PFLOAT pxBuffer
)
3376 FIXME("%p, %u, %u, %p: stub!\n", hdc
, iFirstChar
, iLastChar
, pxBuffer
);
3380 /*************************************************************************
3381 * GetCharWidthFloatW [GDI32.@]
3383 BOOL WINAPI
GetCharWidthFloatW(HDC hdc
, UINT iFirstChar
,
3384 UINT iLastChar
, PFLOAT pxBuffer
)
3386 FIXME("%p, %u, %u, %p: stub!\n", hdc
, iFirstChar
, iLastChar
, pxBuffer
);
3391 /***********************************************************************
3393 * Font Resource API *
3395 ***********************************************************************/
3397 /***********************************************************************
3398 * AddFontResourceA (GDI32.@)
3400 INT WINAPI
AddFontResourceA( LPCSTR str
)
3402 return AddFontResourceExA( str
, 0, NULL
);
3405 /***********************************************************************
3406 * AddFontResourceW (GDI32.@)
3408 INT WINAPI
AddFontResourceW( LPCWSTR str
)
3410 return AddFontResourceExW(str
, 0, NULL
);
3414 /***********************************************************************
3415 * AddFontResourceExA (GDI32.@)
3417 INT WINAPI
AddFontResourceExA( LPCSTR str
, DWORD fl
, PVOID pdv
)
3419 DWORD len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
3420 LPWSTR strW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3423 MultiByteToWideChar(CP_ACP
, 0, str
, -1, strW
, len
);
3424 ret
= AddFontResourceExW(strW
, fl
, pdv
);
3425 HeapFree(GetProcessHeap(), 0, strW
);
3429 static BOOL CALLBACK
load_enumed_resource(HMODULE hModule
, LPCWSTR type
, LPWSTR name
, LONG_PTR lParam
)
3431 HRSRC rsrc
= FindResourceW(hModule
, name
, type
);
3432 HGLOBAL hMem
= LoadResource(hModule
, rsrc
);
3433 LPVOID
*pMem
= LockResource(hMem
);
3434 int *num_total
= (int *)lParam
;
3437 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type
));
3438 if (!AddFontMemResourceEx(pMem
, SizeofResource(hModule
, rsrc
), NULL
, &num_in_res
))
3440 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule
, hMem
);
3444 *num_total
+= num_in_res
;
3448 /***********************************************************************
3449 * AddFontResourceExW (GDI32.@)
3451 INT WINAPI
AddFontResourceExW( LPCWSTR str
, DWORD fl
, PVOID pdv
)
3453 int ret
= WineEngAddFontResourceEx(str
, fl
, pdv
);
3456 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3457 HMODULE hModule
= LoadLibraryExW(str
, NULL
, LOAD_LIBRARY_AS_DATAFILE
);
3458 if (hModule
!= NULL
)
3460 int num_resources
= 0;
3461 LPWSTR rt_font
= (LPWSTR
)((ULONG_PTR
)8); /* we don't want to include winuser.h */
3463 TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3464 wine_dbgstr_w(str
));
3465 if (EnumResourceNamesW(hModule
, rt_font
, load_enumed_resource
, (LONG_PTR
)&num_resources
))
3466 ret
= num_resources
;
3467 FreeLibrary(hModule
);
3473 /***********************************************************************
3474 * RemoveFontResourceA (GDI32.@)
3476 BOOL WINAPI
RemoveFontResourceA( LPCSTR str
)
3478 return RemoveFontResourceExA(str
, 0, 0);
3481 /***********************************************************************
3482 * RemoveFontResourceW (GDI32.@)
3484 BOOL WINAPI
RemoveFontResourceW( LPCWSTR str
)
3486 return RemoveFontResourceExW(str
, 0, 0);
3489 /***********************************************************************
3490 * AddFontMemResourceEx (GDI32.@)
3492 HANDLE WINAPI
AddFontMemResourceEx( PVOID pbFont
, DWORD cbFont
, PVOID pdv
, DWORD
*pcFonts
)
3497 if (!pbFont
|| !cbFont
|| !pcFonts
)
3499 SetLastError(ERROR_INVALID_PARAMETER
);
3503 ret
= WineEngAddFontMemResourceEx(pbFont
, cbFont
, pdv
, &num_fonts
);
3508 *pcFonts
= num_fonts
;
3512 WARN("page fault while writing to *pcFonts (%p)\n", pcFonts
);
3513 RemoveFontMemResourceEx(ret
);
3521 /***********************************************************************
3522 * RemoveFontMemResourceEx (GDI32.@)
3524 BOOL WINAPI
RemoveFontMemResourceEx( HANDLE fh
)
3526 FIXME("(%p) stub\n", fh
);
3530 /***********************************************************************
3531 * RemoveFontResourceExA (GDI32.@)
3533 BOOL WINAPI
RemoveFontResourceExA( LPCSTR str
, DWORD fl
, PVOID pdv
)
3535 DWORD len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
3536 LPWSTR strW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3539 MultiByteToWideChar(CP_ACP
, 0, str
, -1, strW
, len
);
3540 ret
= RemoveFontResourceExW(strW
, fl
, pdv
);
3541 HeapFree(GetProcessHeap(), 0, strW
);
3545 /***********************************************************************
3546 * RemoveFontResourceExW (GDI32.@)
3548 BOOL WINAPI
RemoveFontResourceExW( LPCWSTR str
, DWORD fl
, PVOID pdv
)
3550 return WineEngRemoveFontResourceEx(str
, fl
, pdv
);
3553 /***********************************************************************
3554 * GetTextCharset (GDI32.@)
3556 UINT WINAPI
GetTextCharset(HDC hdc
)
3558 /* MSDN docs say this is equivalent */
3559 return GetTextCharsetInfo(hdc
, NULL
, 0);
3562 /***********************************************************************
3563 * GetTextCharsetInfo (GDI32.@)
3565 UINT WINAPI
GetTextCharsetInfo(HDC hdc
, LPFONTSIGNATURE fs
, DWORD flags
)
3567 UINT ret
= DEFAULT_CHARSET
;
3568 DC
*dc
= get_dc_ptr(hdc
);
3573 dev
= GET_DC_PHYSDEV( dc
, pGetTextCharsetInfo
);
3574 ret
= dev
->funcs
->pGetTextCharsetInfo( dev
, fs
, flags
);
3575 release_dc_ptr( dc
);
3578 if (ret
== DEFAULT_CHARSET
&& fs
)
3579 memset(fs
, 0, sizeof(FONTSIGNATURE
));
3583 /***********************************************************************
3584 * GdiGetCharDimensions (GDI32.@)
3586 * Gets the average width of the characters in the English alphabet.
3589 * hdc [I] Handle to the device context to measure on.
3590 * lptm [O] Pointer to memory to store the text metrics into.
3591 * height [O] On exit, the maximum height of characters in the English alphabet.
3594 * The average width of characters in the English alphabet.
3597 * This function is used by the dialog manager to get the size of a dialog
3598 * unit. It should also be used by other pieces of code that need to know
3599 * the size of a dialog unit in logical units without having access to the
3600 * window handle of the dialog.
3601 * Windows caches the font metrics from this function, but we don't and
3602 * there doesn't appear to be an immediate advantage to do so.
3605 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3607 LONG WINAPI
GdiGetCharDimensions(HDC hdc
, LPTEXTMETRICW lptm
, LONG
*height
)
3610 static const WCHAR alphabet
[] = {
3611 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3612 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3613 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3615 if(lptm
&& !GetTextMetricsW(hdc
, lptm
)) return 0;
3617 if(!GetTextExtentPointW(hdc
, alphabet
, 52, &sz
)) return 0;
3619 if (height
) *height
= sz
.cy
;
3620 return (sz
.cx
/ 26 + 1) / 2;
3623 BOOL WINAPI
EnableEUDC(BOOL fEnableEUDC
)
3625 FIXME("(%d): stub\n", fEnableEUDC
);
3629 /***********************************************************************
3630 * GetCharWidthI (GDI32.@)
3632 * Retrieve widths of characters.
3635 * hdc [I] Handle to a device context.
3636 * first [I] First glyph in range to query.
3637 * count [I] Number of glyph indices to query.
3638 * glyphs [I] Array of glyphs to query.
3639 * buffer [O] Buffer to receive character widths.
3642 * Only works with TrueType fonts.
3648 BOOL WINAPI
GetCharWidthI(HDC hdc
, UINT first
, UINT count
, LPWORD glyphs
, LPINT buffer
)
3653 TRACE("(%p, %d, %d, %p, %p)\n", hdc
, first
, count
, glyphs
, buffer
);
3655 if (!(abc
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(ABC
))))
3658 if (!GetCharABCWidthsI(hdc
, first
, count
, glyphs
, abc
))
3660 HeapFree(GetProcessHeap(), 0, abc
);
3664 for (i
= 0; i
< count
; i
++)
3665 buffer
[i
] = abc
->abcA
+ abc
->abcB
+ abc
->abcC
;
3667 HeapFree(GetProcessHeap(), 0, abc
);
3671 /***********************************************************************
3672 * GetFontUnicodeRanges (GDI32.@)
3674 * Retrieve a list of supported Unicode characters in a font.
3677 * hdc [I] Handle to a device context.
3678 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3681 * Success: Number of bytes written to the buffer pointed to by lpgs.
3685 DWORD WINAPI
GetFontUnicodeRanges(HDC hdc
, LPGLYPHSET lpgs
)
3689 DC
*dc
= get_dc_ptr(hdc
);
3691 TRACE("(%p, %p)\n", hdc
, lpgs
);
3695 dev
= GET_DC_PHYSDEV( dc
, pGetFontUnicodeRanges
);
3696 ret
= dev
->funcs
->pGetFontUnicodeRanges( dev
, lpgs
);
3702 /*************************************************************
3703 * FontIsLinked (GDI32.@)
3705 BOOL WINAPI
FontIsLinked(HDC hdc
)
3707 DC
*dc
= get_dc_ptr(hdc
);
3711 if (!dc
) return FALSE
;
3712 dev
= GET_DC_PHYSDEV( dc
, pFontIsLinked
);
3713 ret
= dev
->funcs
->pFontIsLinked( dev
);
3715 TRACE("returning %d\n", ret
);
3719 /*************************************************************
3720 * GdiRealizationInfo (GDI32.@)
3722 * Returns a structure that contains some font information.
3724 BOOL WINAPI
GdiRealizationInfo(HDC hdc
, realization_info_t
*info
)
3726 DC
*dc
= get_dc_ptr(hdc
);
3730 if (!dc
) return FALSE
;
3731 dev
= GET_DC_PHYSDEV( dc
, pGdiRealizationInfo
);
3732 ret
= dev
->funcs
->pGdiRealizationInfo( dev
, info
);