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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include "wine/port.h"
36 #include "gdi_private.h"
37 #include "wine/unicode.h"
38 #include "wine/debug.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(font
);
41 WINE_DECLARE_DEBUG_CHANNEL(gdi
);
43 /* Device -> World size conversion */
45 /* Performs a device to world transformation on the specified width (which
46 * is in integer format).
48 static inline INT
INTERNAL_XDSTOWS(DC
*dc
, INT width
)
52 /* Perform operation with floating point */
53 floatWidth
= (FLOAT
)width
* dc
->xformVport2World
.eM11
;
54 /* Round to integers */
55 return GDI_ROUND(floatWidth
);
58 /* Performs a device to world transformation on the specified size (which
59 * is in integer format).
61 static inline INT
INTERNAL_YDSTOWS(DC
*dc
, INT height
)
65 /* Perform operation with floating point */
66 floatHeight
= (FLOAT
)height
* dc
->xformVport2World
.eM22
;
67 /* Round to integers */
68 return GDI_ROUND(floatHeight
);
72 static HGDIOBJ
FONT_SelectObject( HGDIOBJ handle
, void *obj
, HDC hdc
);
73 static INT
FONT_GetObject16( HGDIOBJ handle
, void *obj
, INT count
, LPVOID buffer
);
74 static INT
FONT_GetObjectA( HGDIOBJ handle
, void *obj
, INT count
, LPVOID buffer
);
75 static INT
FONT_GetObjectW( HGDIOBJ handle
, void *obj
, INT count
, LPVOID buffer
);
76 static BOOL
FONT_DeleteObject( HGDIOBJ handle
, void *obj
);
78 static const struct gdi_obj_funcs font_funcs
=
80 FONT_SelectObject
, /* pSelectObject */
81 FONT_GetObject16
, /* pGetObject16 */
82 FONT_GetObjectA
, /* pGetObjectA */
83 FONT_GetObjectW
, /* pGetObjectW */
84 NULL
, /* pUnrealizeObject */
85 FONT_DeleteObject
/* pDeleteObject */
88 #define ENUM_UNICODE 0x00000001
89 #define ENUM_CALLED 0x00000002
99 LPLOGFONT16 lpLogFontParam
;
100 FONTENUMPROC16 lpEnumFunc
;
103 LPNEWTEXTMETRICEX16 lpTextMetric
;
104 LPENUMLOGFONTEX16 lpLogFont
;
105 SEGPTR segTextMetric
;
115 LPLOGFONTW lpLogFontParam
;
116 FONTENUMPROCW lpEnumFunc
;
125 * For TranslateCharsetInfo
127 #define FS(x) {{0,0,0,0},{0x1<<(x),0}}
128 #define MAXTCIINDEX 32
129 static CHARSETINFO FONT_tci
[MAXTCIINDEX
] = {
131 { ANSI_CHARSET
, 1252, FS(0)},
132 { EASTEUROPE_CHARSET
, 1250, FS(1)},
133 { RUSSIAN_CHARSET
, 1251, FS(2)},
134 { GREEK_CHARSET
, 1253, FS(3)},
135 { TURKISH_CHARSET
, 1254, FS(4)},
136 { HEBREW_CHARSET
, 1255, FS(5)},
137 { ARABIC_CHARSET
, 1256, FS(6)},
138 { BALTIC_CHARSET
, 1257, FS(7)},
139 { VIETNAMESE_CHARSET
, 1258, FS(8)},
140 /* reserved by ANSI */
141 { DEFAULT_CHARSET
, 0, FS(0)},
142 { DEFAULT_CHARSET
, 0, FS(0)},
143 { DEFAULT_CHARSET
, 0, FS(0)},
144 { DEFAULT_CHARSET
, 0, FS(0)},
145 { DEFAULT_CHARSET
, 0, FS(0)},
146 { DEFAULT_CHARSET
, 0, FS(0)},
147 { DEFAULT_CHARSET
, 0, FS(0)},
149 { THAI_CHARSET
, 874, FS(16)},
150 { SHIFTJIS_CHARSET
, 932, FS(17)},
151 { GB2312_CHARSET
, 936, FS(18)},
152 { HANGEUL_CHARSET
, 949, FS(19)},
153 { CHINESEBIG5_CHARSET
, 950, FS(20)},
154 { JOHAB_CHARSET
, 1361, FS(21)},
155 /* reserved for alternate ANSI and OEM */
156 { DEFAULT_CHARSET
, 0, FS(0)},
157 { DEFAULT_CHARSET
, 0, FS(0)},
158 { DEFAULT_CHARSET
, 0, FS(0)},
159 { DEFAULT_CHARSET
, 0, FS(0)},
160 { DEFAULT_CHARSET
, 0, FS(0)},
161 { DEFAULT_CHARSET
, 0, FS(0)},
162 { DEFAULT_CHARSET
, 0, FS(0)},
163 { DEFAULT_CHARSET
, 0, FS(0)},
164 /* reserved for system */
165 { DEFAULT_CHARSET
, 0, FS(0)},
166 { SYMBOL_CHARSET
, CP_SYMBOL
, FS(31)},
169 /***********************************************************************
170 * LOGFONT conversion functions.
172 static void FONT_LogFontWTo16( const LOGFONTW
* font32
, LPLOGFONT16 font16
)
174 font16
->lfHeight
= font32
->lfHeight
;
175 font16
->lfWidth
= font32
->lfWidth
;
176 font16
->lfEscapement
= font32
->lfEscapement
;
177 font16
->lfOrientation
= font32
->lfOrientation
;
178 font16
->lfWeight
= font32
->lfWeight
;
179 font16
->lfItalic
= font32
->lfItalic
;
180 font16
->lfUnderline
= font32
->lfUnderline
;
181 font16
->lfStrikeOut
= font32
->lfStrikeOut
;
182 font16
->lfCharSet
= font32
->lfCharSet
;
183 font16
->lfOutPrecision
= font32
->lfOutPrecision
;
184 font16
->lfClipPrecision
= font32
->lfClipPrecision
;
185 font16
->lfQuality
= font32
->lfQuality
;
186 font16
->lfPitchAndFamily
= font32
->lfPitchAndFamily
;
187 WideCharToMultiByte( CP_ACP
, 0, font32
->lfFaceName
, -1,
188 font16
->lfFaceName
, LF_FACESIZE
, NULL
, NULL
);
189 font16
->lfFaceName
[LF_FACESIZE
-1] = 0;
192 static void FONT_LogFont16ToW( const LOGFONT16
*font16
, LPLOGFONTW font32
)
194 font32
->lfHeight
= font16
->lfHeight
;
195 font32
->lfWidth
= font16
->lfWidth
;
196 font32
->lfEscapement
= font16
->lfEscapement
;
197 font32
->lfOrientation
= font16
->lfOrientation
;
198 font32
->lfWeight
= font16
->lfWeight
;
199 font32
->lfItalic
= font16
->lfItalic
;
200 font32
->lfUnderline
= font16
->lfUnderline
;
201 font32
->lfStrikeOut
= font16
->lfStrikeOut
;
202 font32
->lfCharSet
= font16
->lfCharSet
;
203 font32
->lfOutPrecision
= font16
->lfOutPrecision
;
204 font32
->lfClipPrecision
= font16
->lfClipPrecision
;
205 font32
->lfQuality
= font16
->lfQuality
;
206 font32
->lfPitchAndFamily
= font16
->lfPitchAndFamily
;
207 MultiByteToWideChar( CP_ACP
, 0, font16
->lfFaceName
, -1, font32
->lfFaceName
, LF_FACESIZE
);
208 font32
->lfFaceName
[LF_FACESIZE
-1] = 0;
211 static void FONT_LogFontAToW( const LOGFONTA
*fontA
, LPLOGFONTW fontW
)
213 memcpy(fontW
, fontA
, sizeof(LOGFONTA
) - LF_FACESIZE
);
214 MultiByteToWideChar(CP_ACP
, 0, fontA
->lfFaceName
, -1, fontW
->lfFaceName
,
218 static void FONT_LogFontWToA( const LOGFONTW
*fontW
, LPLOGFONTA fontA
)
220 memcpy(fontA
, fontW
, sizeof(LOGFONTA
) - LF_FACESIZE
);
221 WideCharToMultiByte(CP_ACP
, 0, fontW
->lfFaceName
, -1, fontA
->lfFaceName
,
222 LF_FACESIZE
, NULL
, NULL
);
225 static void FONT_EnumLogFontExWTo16( const ENUMLOGFONTEXW
*fontW
, LPENUMLOGFONTEX16 font16
)
227 FONT_LogFontWTo16( (LPLOGFONTW
)fontW
, (LPLOGFONT16
)font16
);
229 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfFullName
, -1,
230 font16
->elfFullName
, LF_FULLFACESIZE
, NULL
, NULL
);
231 font16
->elfFullName
[LF_FULLFACESIZE
-1] = '\0';
232 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfStyle
, -1,
233 font16
->elfStyle
, LF_FACESIZE
, NULL
, NULL
);
234 font16
->elfStyle
[LF_FACESIZE
-1] = '\0';
235 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfScript
, -1,
236 font16
->elfScript
, LF_FACESIZE
, NULL
, NULL
);
237 font16
->elfScript
[LF_FACESIZE
-1] = '\0';
240 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW
*fontW
, LPENUMLOGFONTEXA fontA
)
242 FONT_LogFontWToA( (LPLOGFONTW
)fontW
, (LPLOGFONTA
)fontA
);
244 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfFullName
, -1,
245 fontA
->elfFullName
, LF_FULLFACESIZE
, NULL
, NULL
);
246 fontA
->elfFullName
[LF_FULLFACESIZE
-1] = '\0';
247 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfStyle
, -1,
248 fontA
->elfStyle
, LF_FACESIZE
, NULL
, NULL
);
249 fontA
->elfStyle
[LF_FACESIZE
-1] = '\0';
250 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfScript
, -1,
251 fontA
->elfScript
, LF_FACESIZE
, NULL
, NULL
);
252 fontA
->elfScript
[LF_FACESIZE
-1] = '\0';
255 /***********************************************************************
256 * TEXTMETRIC conversion functions.
258 static void FONT_TextMetricWToA(const TEXTMETRICW
*ptmW
, LPTEXTMETRICA ptmA
)
260 ptmA
->tmHeight
= ptmW
->tmHeight
;
261 ptmA
->tmAscent
= ptmW
->tmAscent
;
262 ptmA
->tmDescent
= ptmW
->tmDescent
;
263 ptmA
->tmInternalLeading
= ptmW
->tmInternalLeading
;
264 ptmA
->tmExternalLeading
= ptmW
->tmExternalLeading
;
265 ptmA
->tmAveCharWidth
= ptmW
->tmAveCharWidth
;
266 ptmA
->tmMaxCharWidth
= ptmW
->tmMaxCharWidth
;
267 ptmA
->tmWeight
= ptmW
->tmWeight
;
268 ptmA
->tmOverhang
= ptmW
->tmOverhang
;
269 ptmA
->tmDigitizedAspectX
= ptmW
->tmDigitizedAspectX
;
270 ptmA
->tmDigitizedAspectY
= ptmW
->tmDigitizedAspectY
;
271 ptmA
->tmFirstChar
= ptmW
->tmFirstChar
> 255 ? 255 : ptmW
->tmFirstChar
;
272 ptmA
->tmLastChar
= ptmW
->tmLastChar
> 255 ? 255 : ptmW
->tmLastChar
;
273 ptmA
->tmDefaultChar
= ptmW
->tmDefaultChar
> 255 ? 255 : ptmW
->tmDefaultChar
;
274 ptmA
->tmBreakChar
= ptmW
->tmBreakChar
> 255 ? 255 : ptmW
->tmBreakChar
;
275 ptmA
->tmItalic
= ptmW
->tmItalic
;
276 ptmA
->tmUnderlined
= ptmW
->tmUnderlined
;
277 ptmA
->tmStruckOut
= ptmW
->tmStruckOut
;
278 ptmA
->tmPitchAndFamily
= ptmW
->tmPitchAndFamily
;
279 ptmA
->tmCharSet
= ptmW
->tmCharSet
;
283 static void FONT_NewTextMetricExWTo16(const NEWTEXTMETRICEXW
*ptmW
, LPNEWTEXTMETRICEX16 ptm16
)
285 ptm16
->ntmTm
.tmHeight
= ptmW
->ntmTm
.tmHeight
;
286 ptm16
->ntmTm
.tmAscent
= ptmW
->ntmTm
.tmAscent
;
287 ptm16
->ntmTm
.tmDescent
= ptmW
->ntmTm
.tmDescent
;
288 ptm16
->ntmTm
.tmInternalLeading
= ptmW
->ntmTm
.tmInternalLeading
;
289 ptm16
->ntmTm
.tmExternalLeading
= ptmW
->ntmTm
.tmExternalLeading
;
290 ptm16
->ntmTm
.tmAveCharWidth
= ptmW
->ntmTm
.tmAveCharWidth
;
291 ptm16
->ntmTm
.tmMaxCharWidth
= ptmW
->ntmTm
.tmMaxCharWidth
;
292 ptm16
->ntmTm
.tmWeight
= ptmW
->ntmTm
.tmWeight
;
293 ptm16
->ntmTm
.tmOverhang
= ptmW
->ntmTm
.tmOverhang
;
294 ptm16
->ntmTm
.tmDigitizedAspectX
= ptmW
->ntmTm
.tmDigitizedAspectX
;
295 ptm16
->ntmTm
.tmDigitizedAspectY
= ptmW
->ntmTm
.tmDigitizedAspectY
;
296 ptm16
->ntmTm
.tmFirstChar
= ptmW
->ntmTm
.tmFirstChar
> 255 ? 255 : ptmW
->ntmTm
.tmFirstChar
;
297 ptm16
->ntmTm
.tmLastChar
= ptmW
->ntmTm
.tmLastChar
> 255 ? 255 : ptmW
->ntmTm
.tmLastChar
;
298 ptm16
->ntmTm
.tmDefaultChar
= ptmW
->ntmTm
.tmDefaultChar
> 255 ? 255 : ptmW
->ntmTm
.tmDefaultChar
;
299 ptm16
->ntmTm
.tmBreakChar
= ptmW
->ntmTm
.tmBreakChar
> 255 ? 255 : ptmW
->ntmTm
.tmBreakChar
;
300 ptm16
->ntmTm
.tmItalic
= ptmW
->ntmTm
.tmItalic
;
301 ptm16
->ntmTm
.tmUnderlined
= ptmW
->ntmTm
.tmUnderlined
;
302 ptm16
->ntmTm
.tmStruckOut
= ptmW
->ntmTm
.tmStruckOut
;
303 ptm16
->ntmTm
.tmPitchAndFamily
= ptmW
->ntmTm
.tmPitchAndFamily
;
304 ptm16
->ntmTm
.tmCharSet
= ptmW
->ntmTm
.tmCharSet
;
305 ptm16
->ntmTm
.ntmFlags
= ptmW
->ntmTm
.ntmFlags
;
306 ptm16
->ntmTm
.ntmSizeEM
= ptmW
->ntmTm
.ntmSizeEM
;
307 ptm16
->ntmTm
.ntmCellHeight
= ptmW
->ntmTm
.ntmCellHeight
;
308 ptm16
->ntmTm
.ntmAvgWidth
= ptmW
->ntmTm
.ntmAvgWidth
;
309 memcpy(&ptm16
->ntmFontSig
, &ptmW
->ntmFontSig
, sizeof(FONTSIGNATURE
));
312 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW
*ptmW
, NEWTEXTMETRICEXA
*ptmA
)
314 FONT_TextMetricWToA((LPTEXTMETRICW
)ptmW
, (LPTEXTMETRICA
)ptmA
);
315 ptmA
->ntmTm
.ntmFlags
= ptmW
->ntmTm
.ntmFlags
;
316 ptmA
->ntmTm
.ntmSizeEM
= ptmW
->ntmTm
.ntmSizeEM
;
317 ptmA
->ntmTm
.ntmCellHeight
= ptmW
->ntmTm
.ntmCellHeight
;
318 ptmA
->ntmTm
.ntmAvgWidth
= ptmW
->ntmTm
.ntmAvgWidth
;
319 memcpy(&ptmA
->ntmFontSig
, &ptmW
->ntmFontSig
, sizeof(FONTSIGNATURE
));
323 /***********************************************************************
326 * Returns a '\0' terminated Unicode translation of str using the
327 * charset of the currently selected font in hdc. If count is -1 then
328 * str is assumed to be '\0' terminated, otherwise it contains the
329 * number of bytes to convert. If plenW is non-NULL, on return it
330 * will point to the number of WCHARs (excluding the '\0') that have
331 * been written. If pCP is non-NULL, on return it will point to the
332 * codepage used in the conversion.
333 * The caller should free the returned LPWSTR from the process
336 static LPWSTR
FONT_mbtowc(HDC hdc
, LPCSTR str
, INT count
, INT
*plenW
, UINT
*pCP
)
342 int charset
= GetTextCharset(hdc
);
344 /* Hmm, nicely designed api this one! */
345 if(TranslateCharsetInfo((DWORD
*)charset
, &csi
, TCI_SRCCHARSET
))
352 case DEFAULT_CHARSET
:
363 /* FIXME: These have no place here, but because x11drv
364 enumerates fonts with these (made up) charsets some apps
365 might use them and then the FIXME below would become
366 annoying. Now we could pick the intended codepage for
367 each of these, but since it's broken anyway we'll just
368 use CP_ACP and hope it'll go away...
374 FIXME("Can't find codepage for charset %d\n", charset
);
379 TRACE("charset %d => cp %d\n", charset
, cp
);
381 if(count
== -1) count
= strlen(str
);
382 lenW
= MultiByteToWideChar(cp
, 0, str
, count
, NULL
, 0);
383 strW
= HeapAlloc(GetProcessHeap(), 0, (lenW
+ 1) * sizeof(WCHAR
));
384 MultiByteToWideChar(cp
, 0, str
, count
, strW
, lenW
);
386 TRACE("mapped %s -> %s\n", debugstr_an(str
, count
), debugstr_wn(strW
, lenW
));
387 if(plenW
) *plenW
= lenW
;
393 /***********************************************************************
394 * CreateFontIndirectA (GDI32.@)
396 HFONT WINAPI
CreateFontIndirectA( const LOGFONTA
*plfA
)
401 FONT_LogFontAToW( plfA
, &lfW
);
402 return CreateFontIndirectW( &lfW
);
404 return CreateFontIndirectW( NULL
);
408 /***********************************************************************
409 * CreateFontIndirectW (GDI32.@)
411 HFONT WINAPI
CreateFontIndirectW( const LOGFONTW
*plf
)
418 if ((fontPtr
= GDI_AllocObject( sizeof(FONTOBJ
), FONT_MAGIC
,
419 (HGDIOBJ
*)&hFont
, &font_funcs
)))
421 static const WCHAR ItalicW
[] = {' ','I','t','a','l','i','c','\0'};
422 static const WCHAR BoldW
[] = {' ','B','o','l','d','\0'};
423 WCHAR
*pFaceNameItalicSuffix
, *pFaceNameBoldSuffix
;
424 WCHAR
* pFaceNameSuffix
= NULL
;
426 memcpy( &fontPtr
->logfont
, plf
, sizeof(LOGFONTW
) );
428 TRACE("(%ld %ld %ld %ld %x %d %x %d %d) %s %s %s %s => %p\n",
429 plf
->lfHeight
, plf
->lfWidth
,
430 plf
->lfEscapement
, plf
->lfOrientation
,
431 plf
->lfPitchAndFamily
,
432 plf
->lfOutPrecision
, plf
->lfClipPrecision
,
433 plf
->lfQuality
, plf
->lfCharSet
,
434 debugstr_w(plf
->lfFaceName
),
435 plf
->lfWeight
> 400 ? "Bold" : "",
436 plf
->lfItalic
? "Italic" : "",
437 plf
->lfUnderline
? "Underline" : "", hFont
);
439 if (plf
->lfEscapement
!= plf
->lfOrientation
) {
440 /* this should really depend on whether GM_ADVANCED is set */
441 fontPtr
->logfont
.lfOrientation
= fontPtr
->logfont
.lfEscapement
;
442 WARN("orientation angle %f set to "
443 "escapement angle %f for new font %p\n",
444 plf
->lfOrientation
/10., plf
->lfEscapement
/10., hFont
);
447 pFaceNameItalicSuffix
= strstrW(fontPtr
->logfont
.lfFaceName
, ItalicW
);
448 if (pFaceNameItalicSuffix
) {
449 fontPtr
->logfont
.lfItalic
= TRUE
;
450 pFaceNameSuffix
= pFaceNameItalicSuffix
;
453 pFaceNameBoldSuffix
= strstrW(fontPtr
->logfont
.lfFaceName
, BoldW
);
454 if (pFaceNameBoldSuffix
) {
455 if (fontPtr
->logfont
.lfWeight
< FW_BOLD
) {
456 fontPtr
->logfont
.lfWeight
= FW_BOLD
;
458 if (!pFaceNameSuffix
||
459 (pFaceNameBoldSuffix
< pFaceNameSuffix
)) {
460 pFaceNameSuffix
= pFaceNameBoldSuffix
;
464 if (pFaceNameSuffix
) *pFaceNameSuffix
= 0;
466 GDI_ReleaseObj( hFont
);
469 else WARN("(NULL) => NULL\n");
474 /*************************************************************************
475 * CreateFontA (GDI32.@)
477 HFONT WINAPI
CreateFontA( INT height
, INT width
, INT esc
,
478 INT orient
, INT weight
, DWORD italic
,
479 DWORD underline
, DWORD strikeout
, DWORD charset
,
480 DWORD outpres
, DWORD clippres
, DWORD quality
,
481 DWORD pitch
, LPCSTR name
)
485 logfont
.lfHeight
= height
;
486 logfont
.lfWidth
= width
;
487 logfont
.lfEscapement
= esc
;
488 logfont
.lfOrientation
= orient
;
489 logfont
.lfWeight
= weight
;
490 logfont
.lfItalic
= italic
;
491 logfont
.lfUnderline
= underline
;
492 logfont
.lfStrikeOut
= strikeout
;
493 logfont
.lfCharSet
= charset
;
494 logfont
.lfOutPrecision
= outpres
;
495 logfont
.lfClipPrecision
= clippres
;
496 logfont
.lfQuality
= quality
;
497 logfont
.lfPitchAndFamily
= pitch
;
500 lstrcpynA(logfont
.lfFaceName
,name
,sizeof(logfont
.lfFaceName
));
502 logfont
.lfFaceName
[0] = '\0';
504 return CreateFontIndirectA( &logfont
);
507 /*************************************************************************
508 * CreateFontW (GDI32.@)
510 HFONT WINAPI
CreateFontW( INT height
, INT width
, INT esc
,
511 INT orient
, INT weight
, DWORD italic
,
512 DWORD underline
, DWORD strikeout
, DWORD charset
,
513 DWORD outpres
, DWORD clippres
, DWORD quality
,
514 DWORD pitch
, LPCWSTR name
)
518 logfont
.lfHeight
= height
;
519 logfont
.lfWidth
= width
;
520 logfont
.lfEscapement
= esc
;
521 logfont
.lfOrientation
= orient
;
522 logfont
.lfWeight
= weight
;
523 logfont
.lfItalic
= italic
;
524 logfont
.lfUnderline
= underline
;
525 logfont
.lfStrikeOut
= strikeout
;
526 logfont
.lfCharSet
= charset
;
527 logfont
.lfOutPrecision
= outpres
;
528 logfont
.lfClipPrecision
= clippres
;
529 logfont
.lfQuality
= quality
;
530 logfont
.lfPitchAndFamily
= pitch
;
533 lstrcpynW(logfont
.lfFaceName
, name
,
534 sizeof(logfont
.lfFaceName
) / sizeof(WCHAR
));
536 logfont
.lfFaceName
[0] = '\0';
538 return CreateFontIndirectW( &logfont
);
542 /***********************************************************************
545 * If the driver supports vector fonts we create a gdi font first and
546 * then call the driver to give it a chance to supply its own device
547 * font. If the driver wants to do this it returns TRUE and we can
548 * delete the gdi font, if the driver wants to use the gdi font it
549 * should return FALSE, to signal an error return GDI_ERROR. For
550 * drivers that don't support vector fonts they must supply their own
553 static HGDIOBJ
FONT_SelectObject( HGDIOBJ handle
, void *obj
, HDC hdc
)
556 DC
*dc
= DC_GetDCPtr( hdc
);
560 if (dc
->hFont
!= handle
|| dc
->gdiFont
== NULL
)
562 if(GetDeviceCaps(dc
->hSelf
, TEXTCAPS
) & TC_VA_ABLE
)
563 dc
->gdiFont
= WineEngCreateFontInstance(dc
, handle
);
566 if (dc
->funcs
->pSelectFont
) ret
= dc
->funcs
->pSelectFont( dc
->physDev
, handle
, dc
->gdiFont
);
568 if (ret
&& dc
->gdiFont
) dc
->gdiFont
= 0;
570 if (ret
== HGDI_ERROR
)
571 ret
= 0; /* SelectObject returns 0 on error */
577 GDI_ReleaseObj( hdc
);
582 /***********************************************************************
585 static INT
FONT_GetObject16( HGDIOBJ handle
, void *obj
, INT count
, LPVOID buffer
)
590 FONT_LogFontWTo16( &font
->logfont
, &lf16
);
592 if (count
> sizeof(LOGFONT16
)) count
= sizeof(LOGFONT16
);
593 memcpy( buffer
, &lf16
, count
);
597 /***********************************************************************
600 static INT
FONT_GetObjectA( HGDIOBJ handle
, void *obj
, INT count
, LPVOID buffer
)
607 FONT_LogFontWToA( &font
->logfont
, &lfA
);
609 if (count
> sizeof(lfA
)) count
= sizeof(lfA
);
610 memcpy( buffer
, &lfA
, count
);
614 /***********************************************************************
617 static INT
FONT_GetObjectW( HGDIOBJ handle
, void *obj
, INT count
, LPVOID buffer
)
621 return sizeof(LOGFONTW
);
622 if (count
> sizeof(LOGFONTW
)) count
= sizeof(LOGFONTW
);
623 memcpy( buffer
, &font
->logfont
, count
);
628 /***********************************************************************
631 static BOOL
FONT_DeleteObject( HGDIOBJ handle
, void *obj
)
633 WineEngDestroyFontInstance( handle
);
634 return GDI_FreeObject( handle
, obj
);
638 /***********************************************************************
639 * FONT_EnumInstance16
641 * Called by the device driver layer to pass font info
642 * down to the application.
644 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
645 * We have to use other types because of the FONTENUMPROCW definition.
647 static INT CALLBACK
FONT_EnumInstance16( const LOGFONTW
*plf
, const TEXTMETRICW
*ptm
,
648 DWORD fType
, LPARAM lp
)
650 fontEnum16
*pfe
= (fontEnum16
*)lp
;
654 if( pfe
->lpLogFontParam
->lfCharSet
== DEFAULT_CHARSET
||
655 pfe
->lpLogFontParam
->lfCharSet
== plf
->lfCharSet
)
660 FONT_EnumLogFontExWTo16((const ENUMLOGFONTEXW
*)plf
, pfe
->lpLogFont
);
661 FONT_NewTextMetricExWTo16((const NEWTEXTMETRICEXW
*)ptm
, pfe
->lpTextMetric
);
662 pfe
->dwFlags
|= ENUM_CALLED
;
663 GDI_ReleaseObj( pfe
->hdc
); /* release the GDI lock */
665 args
[6] = SELECTOROF(pfe
->segLogFont
);
666 args
[5] = OFFSETOF(pfe
->segLogFont
);
667 args
[4] = SELECTOROF(pfe
->segTextMetric
);
668 args
[3] = OFFSETOF(pfe
->segTextMetric
);
670 args
[1] = HIWORD(pfe
->lpData
);
671 args
[0] = LOWORD(pfe
->lpData
);
672 WOWCallback16Ex( (DWORD
)pfe
->lpEnumFunc
, WCB16_PASCAL
, sizeof(args
), args
, &result
);
673 ret
= LOWORD(result
);
675 /* get the lock again and make sure the DC is still valid */
676 dc
= DC_GetDCPtr( pfe
->hdc
);
677 if (!dc
|| dc
!= pfe
->dc
|| dc
->physDev
!= pfe
->physDev
)
679 if (dc
) GDI_ReleaseObj( pfe
->hdc
);
680 pfe
->hdc
= 0; /* make sure we don't try to release it later on */
687 /***********************************************************************
690 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
691 * We have to use other types because of the FONTENUMPROCW definition.
693 static INT CALLBACK
FONT_EnumInstance( const LOGFONTW
*plf
, const TEXTMETRICW
*ptm
,
694 DWORD fType
, LPARAM lp
)
696 fontEnum32
*pfe
= (fontEnum32
*)lp
;
700 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
701 if((pfe
->lpLogFontParam
->lfCharSet
== DEFAULT_CHARSET
||
702 pfe
->lpLogFontParam
->lfCharSet
== plf
->lfCharSet
) &&
703 (!(fType
& RASTER_FONTTYPE
) || GetDeviceCaps(pfe
->hdc
, TEXTCAPS
) & TC_RA_ABLE
) )
705 /* convert font metrics */
706 ENUMLOGFONTEXA logfont
;
707 NEWTEXTMETRICEXA tmA
;
709 pfe
->dwFlags
|= ENUM_CALLED
;
710 if (!(pfe
->dwFlags
& ENUM_UNICODE
))
712 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW
*)plf
, &logfont
);
713 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW
*)ptm
, &tmA
);
714 plf
= (LOGFONTW
*)&logfont
.elfLogFont
;
715 ptm
= (TEXTMETRICW
*)&tmA
;
717 GDI_ReleaseObj( pfe
->hdc
); /* release the GDI lock */
719 ret
= pfe
->lpEnumFunc( plf
, ptm
, fType
, pfe
->lpData
);
721 /* get the lock again and make sure the DC is still valid */
722 dc
= DC_GetDCPtr( pfe
->hdc
);
723 if (!dc
|| dc
!= pfe
->dc
|| dc
->physDev
!= pfe
->physDev
)
725 if (dc
) GDI_ReleaseObj( pfe
->hdc
);
726 pfe
->hdc
= 0; /* make sure we don't try to release it later on */
733 /***********************************************************************
734 * EnumFontFamiliesEx (GDI.613)
736 INT16 WINAPI
EnumFontFamiliesEx16( HDC16 hDC
, LPLOGFONT16 plf
,
737 FONTENUMPROC16 efproc
, LPARAM lParam
,
742 DC
* dc
= DC_GetDCPtr( HDC_32(hDC
) );
743 NEWTEXTMETRICEX16 tm16
;
744 ENUMLOGFONTEX16 lf16
;
749 FONT_LogFont16ToW(plf
, &lfW
);
751 fe16
.hdc
= HDC_32(hDC
);
753 fe16
.physDev
= dc
->physDev
;
754 fe16
.lpLogFontParam
= plf
;
755 fe16
.lpEnumFunc
= efproc
;
756 fe16
.lpData
= lParam
;
757 fe16
.lpTextMetric
= &tm16
;
758 fe16
.lpLogFont
= &lf16
;
759 fe16
.segTextMetric
= MapLS( &tm16
);
760 fe16
.segLogFont
= MapLS( &lf16
);
763 enum_gdi_fonts
= GetDeviceCaps(fe16
.hdc
, TEXTCAPS
) & TC_VA_ABLE
;
765 if (!dc
->funcs
->pEnumDeviceFonts
&& !enum_gdi_fonts
)
772 ret
= WineEngEnumFonts( &lfW
, FONT_EnumInstance16
, (LPARAM
)&fe16
);
773 fe16
.dwFlags
&= ~ENUM_CALLED
;
774 if (ret
&& dc
->funcs
->pEnumDeviceFonts
) {
775 ret2
= dc
->funcs
->pEnumDeviceFonts( dc
->physDev
, &lfW
, FONT_EnumInstance16
, (LPARAM
)&fe16
);
776 if(fe16
.dwFlags
& ENUM_CALLED
) /* update ret iff a font gets enumed */
780 UnMapLS( fe16
.segTextMetric
);
781 UnMapLS( fe16
.segLogFont
);
782 if (fe16
.hdc
) GDI_ReleaseObj( fe16
.hdc
);
786 /***********************************************************************
787 * FONT_EnumFontFamiliesEx
789 static INT
FONT_EnumFontFamiliesEx( HDC hDC
, LPLOGFONTW plf
,
790 FONTENUMPROCW efproc
,
791 LPARAM lParam
, DWORD dwUnicode
)
794 DC
*dc
= DC_GetDCPtr( hDC
);
800 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf
->lfFaceName
),
802 fe32
.lpLogFontParam
= plf
;
803 fe32
.lpEnumFunc
= efproc
;
804 fe32
.lpData
= lParam
;
805 fe32
.dwFlags
= dwUnicode
;
808 fe32
.physDev
= dc
->physDev
;
810 enum_gdi_fonts
= GetDeviceCaps(hDC
, TEXTCAPS
) & TC_VA_ABLE
;
812 if (!dc
->funcs
->pEnumDeviceFonts
&& !enum_gdi_fonts
)
819 ret
= WineEngEnumFonts( plf
, FONT_EnumInstance
, (LPARAM
)&fe32
);
820 fe32
.dwFlags
&= ~ENUM_CALLED
;
821 if (ret
&& dc
->funcs
->pEnumDeviceFonts
) {
822 ret2
= dc
->funcs
->pEnumDeviceFonts( dc
->physDev
, plf
, FONT_EnumInstance
, (LPARAM
)&fe32
);
823 if(fe32
.dwFlags
& ENUM_CALLED
) /* update ret iff a font gets enumed */
827 if (fe32
.hdc
) GDI_ReleaseObj( fe32
.hdc
);
831 /***********************************************************************
832 * EnumFontFamiliesExW (GDI32.@)
834 INT WINAPI
EnumFontFamiliesExW( HDC hDC
, LPLOGFONTW plf
,
835 FONTENUMPROCW efproc
,
836 LPARAM lParam
, DWORD dwFlags
)
838 return FONT_EnumFontFamiliesEx( hDC
, plf
, efproc
, lParam
, ENUM_UNICODE
);
841 /***********************************************************************
842 * EnumFontFamiliesExA (GDI32.@)
844 INT WINAPI
EnumFontFamiliesExA( HDC hDC
, LPLOGFONTA plf
,
845 FONTENUMPROCA efproc
,
846 LPARAM lParam
, DWORD dwFlags
)
849 FONT_LogFontAToW( plf
, &lfW
);
851 return FONT_EnumFontFamiliesEx( hDC
, &lfW
, (FONTENUMPROCW
)efproc
, lParam
, 0);
854 /***********************************************************************
855 * EnumFontFamilies (GDI.330)
857 INT16 WINAPI
EnumFontFamilies16( HDC16 hDC
, LPCSTR lpFamily
,
858 FONTENUMPROC16 efproc
, LPARAM lpData
)
862 lf
.lfCharSet
= DEFAULT_CHARSET
;
863 if( lpFamily
) lstrcpynA( lf
.lfFaceName
, lpFamily
, LF_FACESIZE
);
864 else lf
.lfFaceName
[0] = '\0';
866 return EnumFontFamiliesEx16( hDC
, &lf
, efproc
, lpData
, 0 );
869 /***********************************************************************
870 * EnumFontFamiliesA (GDI32.@)
872 INT WINAPI
EnumFontFamiliesA( HDC hDC
, LPCSTR lpFamily
,
873 FONTENUMPROCA efproc
, LPARAM lpData
)
877 lf
.lfCharSet
= DEFAULT_CHARSET
;
878 if( lpFamily
) lstrcpynA( lf
.lfFaceName
, lpFamily
, LF_FACESIZE
);
879 else lf
.lfFaceName
[0] = lf
.lfFaceName
[1] = '\0';
881 return EnumFontFamiliesExA( hDC
, &lf
, efproc
, lpData
, 0 );
884 /***********************************************************************
885 * EnumFontFamiliesW (GDI32.@)
887 INT WINAPI
EnumFontFamiliesW( HDC hDC
, LPCWSTR lpFamily
,
888 FONTENUMPROCW efproc
, LPARAM lpData
)
892 lf
.lfCharSet
= DEFAULT_CHARSET
;
893 if( lpFamily
) lstrcpynW( lf
.lfFaceName
, lpFamily
, LF_FACESIZE
);
894 else lf
.lfFaceName
[0] = 0;
896 return EnumFontFamiliesExW( hDC
, &lf
, efproc
, lpData
, 0 );
899 /***********************************************************************
902 INT16 WINAPI
EnumFonts16( HDC16 hDC
, LPCSTR lpName
, FONTENUMPROC16 efproc
,
905 return EnumFontFamilies16( hDC
, lpName
, efproc
, lpData
);
908 /***********************************************************************
909 * EnumFontsA (GDI32.@)
911 INT WINAPI
EnumFontsA( HDC hDC
, LPCSTR lpName
, FONTENUMPROCA efproc
,
914 return EnumFontFamiliesA( hDC
, lpName
, efproc
, lpData
);
917 /***********************************************************************
918 * EnumFontsW (GDI32.@)
920 INT WINAPI
EnumFontsW( HDC hDC
, LPCWSTR lpName
, FONTENUMPROCW efproc
,
923 return EnumFontFamiliesW( hDC
, lpName
, efproc
, lpData
);
927 /***********************************************************************
928 * GetTextCharacterExtra (GDI32.@)
930 INT WINAPI
GetTextCharacterExtra( HDC hdc
)
933 DC
*dc
= DC_GetDCPtr( hdc
);
934 if (!dc
) return 0x80000000;
936 GDI_ReleaseObj( hdc
);
941 /***********************************************************************
942 * SetTextCharacterExtra (GDI32.@)
944 INT WINAPI
SetTextCharacterExtra( HDC hdc
, INT extra
)
947 DC
* dc
= DC_GetDCPtr( hdc
);
948 if (!dc
) return 0x80000000;
949 if (dc
->funcs
->pSetTextCharacterExtra
)
950 prev
= dc
->funcs
->pSetTextCharacterExtra( dc
->physDev
, extra
);
953 prev
= dc
->charExtra
;
954 dc
->charExtra
= extra
;
956 GDI_ReleaseObj( hdc
);
961 /***********************************************************************
962 * SetTextJustification (GDI32.@)
964 BOOL WINAPI
SetTextJustification( HDC hdc
, INT extra
, INT breaks
)
967 DC
* dc
= DC_GetDCPtr( hdc
);
968 if (!dc
) return FALSE
;
969 if (dc
->funcs
->pSetTextJustification
)
970 ret
= dc
->funcs
->pSetTextJustification( dc
->physDev
, extra
, breaks
);
973 extra
= abs((extra
* dc
->vportExtX
+ dc
->wndExtX
/ 2) / dc
->wndExtX
);
974 if (!extra
) breaks
= 0;
977 dc
->breakExtra
= extra
/ breaks
;
978 dc
->breakRem
= extra
- (breaks
* dc
->breakExtra
);
986 GDI_ReleaseObj( hdc
);
991 /***********************************************************************
992 * GetTextFaceA (GDI32.@)
994 INT WINAPI
GetTextFaceA( HDC hdc
, INT count
, LPSTR name
)
996 INT res
= GetTextFaceW(hdc
, 0, NULL
);
997 LPWSTR nameW
= HeapAlloc( GetProcessHeap(), 0, res
* 2 );
998 GetTextFaceW( hdc
, res
, nameW
);
1002 if (count
&& !WideCharToMultiByte( CP_ACP
, 0, nameW
, -1, name
, count
, NULL
, NULL
))
1007 res
= WideCharToMultiByte( CP_ACP
, 0, nameW
, -1, NULL
, 0, NULL
, NULL
);
1008 HeapFree( GetProcessHeap(), 0, nameW
);
1012 /***********************************************************************
1013 * GetTextFaceW (GDI32.@)
1015 INT WINAPI
GetTextFaceW( HDC hdc
, INT count
, LPWSTR name
)
1020 DC
* dc
= DC_GetDCPtr( hdc
);
1024 ret
= WineEngGetTextFace(dc
->gdiFont
, count
, name
);
1025 else if ((font
= (FONTOBJ
*) GDI_GetObjPtr( dc
->hFont
, FONT_MAGIC
)))
1029 lstrcpynW( name
, font
->logfont
.lfFaceName
, count
);
1030 ret
= strlenW(name
);
1032 else ret
= strlenW(font
->logfont
.lfFaceName
) + 1;
1033 GDI_ReleaseObj( dc
->hFont
);
1035 GDI_ReleaseObj( hdc
);
1040 /***********************************************************************
1041 * GetTextExtentPoint32A (GDI32.@)
1043 BOOL WINAPI
GetTextExtentPoint32A( HDC hdc
, LPCSTR str
, INT count
,
1048 LPWSTR p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
1051 ret
= GetTextExtentPoint32W( hdc
, p
, wlen
, size
);
1052 HeapFree( GetProcessHeap(), 0, p
);
1055 TRACE("(%p %s %d %p): returning %ld x %ld\n",
1056 hdc
, debugstr_an (str
, count
), count
, size
, size
->cx
, size
->cy
);
1061 /***********************************************************************
1062 * GetTextExtentPoint32W [GDI32.@]
1064 * Computes width/height for a string.
1066 * Computes width and height of the specified string.
1072 BOOL WINAPI
GetTextExtentPoint32W(
1073 HDC hdc
, /* [in] Handle of device context */
1074 LPCWSTR str
, /* [in] Address of text string */
1075 INT count
, /* [in] Number of characters in string */
1076 LPSIZE size
) /* [out] Address of structure for string size */
1079 DC
* dc
= DC_GetDCPtr( hdc
);
1080 if (!dc
) return FALSE
;
1083 ret
= WineEngGetTextExtentPoint(dc
->gdiFont
, str
, count
, size
);
1084 else if(dc
->funcs
->pGetTextExtentPoint
)
1085 ret
= dc
->funcs
->pGetTextExtentPoint( dc
->physDev
, str
, count
, size
);
1089 size
->cx
= abs(INTERNAL_XDSTOWS(dc
, size
->cx
));
1090 size
->cy
= abs(INTERNAL_YDSTOWS(dc
, size
->cy
));
1091 size
->cx
+= count
* dc
->charExtra
+ dc
->breakRem
;
1094 GDI_ReleaseObj( hdc
);
1096 TRACE("(%p %s %d %p): returning %ld x %ld\n",
1097 hdc
, debugstr_wn (str
, count
), count
, size
, size
->cx
, size
->cy
);
1101 /***********************************************************************
1102 * GetTextExtentPointI [GDI32.@]
1104 * Computes width and height of the array of glyph indices.
1110 BOOL WINAPI
GetTextExtentPointI(
1111 HDC hdc
, /* [in] Handle of device context */
1112 const WORD
*indices
, /* [in] Address of glyph index array */
1113 INT count
, /* [in] Number of glyphs in array */
1114 LPSIZE size
) /* [out] Address of structure for string size */
1117 DC
* dc
= DC_GetDCPtr( hdc
);
1118 if (!dc
) return FALSE
;
1121 ret
= WineEngGetTextExtentPointI(dc
->gdiFont
, indices
, count
, size
);
1122 size
->cx
= abs(INTERNAL_XDSTOWS(dc
, size
->cx
));
1123 size
->cy
= abs(INTERNAL_YDSTOWS(dc
, size
->cy
));
1124 size
->cx
+= count
* dc
->charExtra
;
1126 else if(dc
->funcs
->pGetTextExtentPoint
) {
1127 FIXME("calling GetTextExtentPoint\n");
1128 ret
= dc
->funcs
->pGetTextExtentPoint( dc
->physDev
, (LPCWSTR
)indices
, count
, size
);
1131 GDI_ReleaseObj( hdc
);
1133 TRACE("(%p %p %d %p): returning %ld x %ld\n",
1134 hdc
, indices
, count
, size
, size
->cx
, size
->cy
);
1139 /***********************************************************************
1140 * GetTextExtentPointA (GDI32.@)
1142 BOOL WINAPI
GetTextExtentPointA( HDC hdc
, LPCSTR str
, INT count
,
1145 TRACE("not bug compatible.\n");
1146 return GetTextExtentPoint32A( hdc
, str
, count
, size
);
1149 /***********************************************************************
1150 * GetTextExtentPointW (GDI32.@)
1152 BOOL WINAPI
GetTextExtentPointW( HDC hdc
, LPCWSTR str
, INT count
,
1155 TRACE("not bug compatible.\n");
1156 return GetTextExtentPoint32W( hdc
, str
, count
, size
);
1160 /***********************************************************************
1161 * GetTextExtentExPointA (GDI32.@)
1163 BOOL WINAPI
GetTextExtentExPointA( HDC hdc
, LPCSTR str
, INT count
,
1164 INT maxExt
, LPINT lpnFit
,
1165 LPINT alpDx
, LPSIZE size
)
1169 LPWSTR p
= FONT_mbtowc( hdc
, str
, count
, &wlen
, NULL
);
1170 ret
= GetTextExtentExPointW( hdc
, p
, wlen
, maxExt
, lpnFit
, alpDx
, size
);
1171 if (lpnFit
) *lpnFit
= WideCharToMultiByte(CP_ACP
,0,p
,*lpnFit
,NULL
,0,NULL
,NULL
);
1172 HeapFree( GetProcessHeap(), 0, p
);
1177 /***********************************************************************
1178 * GetTextExtentExPointW (GDI32.@)
1180 * Return the size of the string as it would be if it was output properly by
1183 * This should include
1184 * - Intercharacter spacing
1185 * - justification spacing (not yet done)
1186 * - kerning? see below
1188 * Kerning. Since kerning would be carried out by the rendering code it should
1189 * be done by the driver. However they don't support it yet. Also I am not
1190 * yet persuaded that (certainly under Win95) any kerning is actually done.
1192 * str: According to MSDN this should be null-terminated. That is not true; a
1193 * null will not terminate it early.
1194 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1195 * than count. I have seen it be either the size of the full string or
1196 * 1 less than the size of the full string. I have not seen it bear any
1197 * resemblance to the portion that would fit.
1198 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1199 * trailing intercharacter spacing and any trailing justification.
1202 * Currently we do this by measuring each character etc. We should do it by
1203 * passing the request to the driver, perhaps by extending the
1204 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1205 * thinking about kerning issues and rounding issues in the justification.
1208 BOOL WINAPI
GetTextExtentExPointW( HDC hdc
, LPCWSTR str
, INT count
,
1209 INT maxExt
, LPINT lpnFit
,
1210 LPINT alpDx
, LPSIZE size
)
1212 int index
, nFit
, extent
;
1216 TRACE("(%p, %s, %d)\n",hdc
,debugstr_wn(str
,count
),maxExt
);
1218 size
->cx
= size
->cy
= nFit
= extent
= 0;
1219 for(index
= 0; index
< count
; index
++)
1221 if(!GetTextExtentPoint32W( hdc
, str
, 1, &tSize
)) goto done
;
1222 /* GetTextExtentPoint includes intercharacter spacing. */
1223 /* FIXME - justification needs doing yet. Remember that the base
1224 * data will not be in logical coordinates.
1227 if( !lpnFit
|| extent
<= maxExt
)
1228 /* It is allowed to be equal. */
1231 if( alpDx
) alpDx
[index
] = extent
;
1233 if( tSize
.cy
> size
->cy
) size
->cy
= tSize
.cy
;
1237 if(lpnFit
) *lpnFit
= nFit
;
1240 TRACE("returning %d %ld x %ld\n",nFit
,size
->cx
,size
->cy
);
1246 /***********************************************************************
1247 * GetTextMetricsA (GDI32.@)
1249 BOOL WINAPI
GetTextMetricsA( HDC hdc
, TEXTMETRICA
*metrics
)
1253 if (!GetTextMetricsW( hdc
, &tm32
)) return FALSE
;
1254 FONT_TextMetricWToA( &tm32
, metrics
);
1258 /***********************************************************************
1259 * GetTextMetricsW (GDI32.@)
1261 BOOL WINAPI
GetTextMetricsW( HDC hdc
, TEXTMETRICW
*metrics
)
1264 DC
* dc
= DC_GetDCPtr( hdc
);
1265 if (!dc
) return FALSE
;
1268 ret
= WineEngGetTextMetrics(dc
->gdiFont
, metrics
);
1269 else if (dc
->funcs
->pGetTextMetrics
)
1270 ret
= dc
->funcs
->pGetTextMetrics( dc
->physDev
, metrics
);
1274 /* device layer returns values in device units
1275 * therefore we have to convert them to logical */
1277 #define WDPTOLP(x) ((x<0)? \
1278 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1279 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1280 #define HDPTOLP(y) ((y<0)? \
1281 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1282 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1284 metrics
->tmHeight
= HDPTOLP(metrics
->tmHeight
);
1285 metrics
->tmAscent
= HDPTOLP(metrics
->tmAscent
);
1286 metrics
->tmDescent
= HDPTOLP(metrics
->tmDescent
);
1287 metrics
->tmInternalLeading
= HDPTOLP(metrics
->tmInternalLeading
);
1288 metrics
->tmExternalLeading
= HDPTOLP(metrics
->tmExternalLeading
);
1289 metrics
->tmAveCharWidth
= WDPTOLP(metrics
->tmAveCharWidth
);
1290 metrics
->tmMaxCharWidth
= WDPTOLP(metrics
->tmMaxCharWidth
);
1291 metrics
->tmOverhang
= WDPTOLP(metrics
->tmOverhang
);
1295 TRACE("text metrics:\n"
1296 " Weight = %03li\t FirstChar = %i\t AveCharWidth = %li\n"
1297 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %li\n"
1298 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %li\n"
1299 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1300 " PitchAndFamily = %02x\n"
1301 " --------------------\n"
1302 " InternalLeading = %li\n"
1306 metrics
->tmWeight
, metrics
->tmFirstChar
, metrics
->tmAveCharWidth
,
1307 metrics
->tmItalic
, metrics
->tmLastChar
, metrics
->tmMaxCharWidth
,
1308 metrics
->tmUnderlined
, metrics
->tmDefaultChar
, metrics
->tmOverhang
,
1309 metrics
->tmStruckOut
, metrics
->tmBreakChar
, metrics
->tmCharSet
,
1310 metrics
->tmPitchAndFamily
,
1311 metrics
->tmInternalLeading
,
1314 metrics
->tmHeight
);
1316 GDI_ReleaseObj( hdc
);
1321 /***********************************************************************
1322 * GetOutlineTextMetrics [GDI.308] Gets metrics for TrueType fonts.
1325 * lpOTM should be LPOUTLINETEXTMETRIC
1328 * Success: Non-zero or size of required buffer
1331 UINT16 WINAPI
GetOutlineTextMetrics16(
1332 HDC16 hdc
, /* [in] Handle of device context */
1333 UINT16 cbData
, /* [in] Size of metric data array */
1334 LPOUTLINETEXTMETRIC16 lpOTM
) /* [out] Address of metric data array */
1336 FIXME("(%04x,%04x,%p): stub\n", hdc
,cbData
,lpOTM
);
1341 /***********************************************************************
1342 * GetOutlineTextMetricsA (GDI32.@)
1343 * Gets metrics for TrueType fonts.
1346 * If the supplied buffer isn't big enough Windows partially fills it up to
1347 * its given length and returns that length.
1350 * Success: Non-zero or size of required buffer
1353 UINT WINAPI
GetOutlineTextMetricsA(
1354 HDC hdc
, /* [in] Handle of device context */
1355 UINT cbData
, /* [in] Size of metric data array */
1356 LPOUTLINETEXTMETRICA lpOTM
) /* [out] Address of metric data array */
1358 char buf
[512], *ptr
;
1360 OUTLINETEXTMETRICW
*lpOTMW
= (OUTLINETEXTMETRICW
*)buf
;
1361 OUTLINETEXTMETRICA
*output
= lpOTM
;
1364 if((ret
= GetOutlineTextMetricsW(hdc
, 0, NULL
)) == 0)
1366 if(ret
> sizeof(buf
))
1367 lpOTMW
= HeapAlloc(GetProcessHeap(), 0, ret
);
1368 GetOutlineTextMetricsW(hdc
, ret
, lpOTMW
);
1370 needed
= sizeof(OUTLINETEXTMETRICA
);
1371 if(lpOTMW
->otmpFamilyName
)
1372 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1373 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFamilyName
), -1,
1374 NULL
, 0, NULL
, NULL
);
1375 if(lpOTMW
->otmpFaceName
)
1376 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1377 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFaceName
), -1,
1378 NULL
, 0, NULL
, NULL
);
1379 if(lpOTMW
->otmpStyleName
)
1380 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1381 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpStyleName
), -1,
1382 NULL
, 0, NULL
, NULL
);
1383 if(lpOTMW
->otmpFullName
)
1384 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1385 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFullName
), -1,
1386 NULL
, 0, NULL
, NULL
);
1393 TRACE("needed = %d\n", needed
);
1395 /* Since the supplied buffer isn't big enough, we'll alloc one
1396 that is and memcpy the first cbData bytes into the lpOTM at
1398 output
= HeapAlloc(GetProcessHeap(), 0, needed
);
1400 ret
= output
->otmSize
= min(needed
, cbData
);
1401 FONT_TextMetricWToA( &lpOTMW
->otmTextMetrics
, &output
->otmTextMetrics
);
1402 output
->otmFiller
= 0;
1403 output
->otmPanoseNumber
= lpOTMW
->otmPanoseNumber
;
1404 output
->otmfsSelection
= lpOTMW
->otmfsSelection
;
1405 output
->otmfsType
= lpOTMW
->otmfsType
;
1406 output
->otmsCharSlopeRise
= lpOTMW
->otmsCharSlopeRise
;
1407 output
->otmsCharSlopeRun
= lpOTMW
->otmsCharSlopeRun
;
1408 output
->otmItalicAngle
= lpOTMW
->otmItalicAngle
;
1409 output
->otmEMSquare
= lpOTMW
->otmEMSquare
;
1410 output
->otmAscent
= lpOTMW
->otmAscent
;
1411 output
->otmDescent
= lpOTMW
->otmDescent
;
1412 output
->otmLineGap
= lpOTMW
->otmLineGap
;
1413 output
->otmsCapEmHeight
= lpOTMW
->otmsCapEmHeight
;
1414 output
->otmsXHeight
= lpOTMW
->otmsXHeight
;
1415 output
->otmrcFontBox
= lpOTMW
->otmrcFontBox
;
1416 output
->otmMacAscent
= lpOTMW
->otmMacAscent
;
1417 output
->otmMacDescent
= lpOTMW
->otmMacDescent
;
1418 output
->otmMacLineGap
= lpOTMW
->otmMacLineGap
;
1419 output
->otmusMinimumPPEM
= lpOTMW
->otmusMinimumPPEM
;
1420 output
->otmptSubscriptSize
= lpOTMW
->otmptSubscriptSize
;
1421 output
->otmptSubscriptOffset
= lpOTMW
->otmptSubscriptOffset
;
1422 output
->otmptSuperscriptSize
= lpOTMW
->otmptSuperscriptSize
;
1423 output
->otmptSuperscriptOffset
= lpOTMW
->otmptSuperscriptOffset
;
1424 output
->otmsStrikeoutSize
= lpOTMW
->otmsStrikeoutSize
;
1425 output
->otmsStrikeoutPosition
= lpOTMW
->otmsStrikeoutPosition
;
1426 output
->otmsUnderscoreSize
= lpOTMW
->otmsUnderscoreSize
;
1427 output
->otmsUnderscorePosition
= lpOTMW
->otmsUnderscorePosition
;
1430 ptr
= (char*)(output
+ 1);
1431 left
= needed
- sizeof(*output
);
1433 if(lpOTMW
->otmpFamilyName
) {
1434 output
->otmpFamilyName
= (LPSTR
)(ptr
- (char*)output
);
1435 len
= WideCharToMultiByte(CP_ACP
, 0,
1436 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFamilyName
), -1,
1437 ptr
, left
, NULL
, NULL
);
1441 output
->otmpFamilyName
= 0;
1443 if(lpOTMW
->otmpFaceName
) {
1444 output
->otmpFaceName
= (LPSTR
)(ptr
- (char*)output
);
1445 len
= WideCharToMultiByte(CP_ACP
, 0,
1446 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFaceName
), -1,
1447 ptr
, left
, NULL
, NULL
);
1451 output
->otmpFaceName
= 0;
1453 if(lpOTMW
->otmpStyleName
) {
1454 output
->otmpStyleName
= (LPSTR
)(ptr
- (char*)output
);
1455 len
= WideCharToMultiByte(CP_ACP
, 0,
1456 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpStyleName
), -1,
1457 ptr
, left
, NULL
, NULL
);
1461 output
->otmpStyleName
= 0;
1463 if(lpOTMW
->otmpFullName
) {
1464 output
->otmpFullName
= (LPSTR
)(ptr
- (char*)output
);
1465 len
= WideCharToMultiByte(CP_ACP
, 0,
1466 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFullName
), -1,
1467 ptr
, left
, NULL
, NULL
);
1470 output
->otmpFullName
= 0;
1474 if(output
!= lpOTM
) {
1475 memcpy(lpOTM
, output
, cbData
);
1476 HeapFree(GetProcessHeap(), 0, output
);
1480 if(lpOTMW
!= (OUTLINETEXTMETRICW
*)buf
)
1481 HeapFree(GetProcessHeap(), 0, lpOTMW
);
1487 /***********************************************************************
1488 * GetOutlineTextMetricsW [GDI32.@]
1490 UINT WINAPI
GetOutlineTextMetricsW(
1491 HDC hdc
, /* [in] Handle of device context */
1492 UINT cbData
, /* [in] Size of metric data array */
1493 LPOUTLINETEXTMETRICW lpOTM
) /* [out] Address of metric data array */
1495 DC
*dc
= DC_GetDCPtr( hdc
);
1496 OUTLINETEXTMETRICW
*output
= lpOTM
;
1499 TRACE("(%p,%d,%p)\n", hdc
, cbData
, lpOTM
);
1503 ret
= WineEngGetOutlineTextMetrics(dc
->gdiFont
, cbData
, output
);
1506 output
= HeapAlloc(GetProcessHeap(), 0, ret
);
1507 WineEngGetOutlineTextMetrics(dc
->gdiFont
, ret
, output
);
1510 #define WDPTOLP(x) ((x<0)? \
1511 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1512 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1513 #define HDPTOLP(y) ((y<0)? \
1514 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1515 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1517 output
->otmTextMetrics
.tmHeight
= HDPTOLP(output
->otmTextMetrics
.tmHeight
);
1518 output
->otmTextMetrics
.tmAscent
= HDPTOLP(output
->otmTextMetrics
.tmAscent
);
1519 output
->otmTextMetrics
.tmDescent
= HDPTOLP(output
->otmTextMetrics
.tmDescent
);
1520 output
->otmTextMetrics
.tmInternalLeading
= HDPTOLP(output
->otmTextMetrics
.tmInternalLeading
);
1521 output
->otmTextMetrics
.tmExternalLeading
= HDPTOLP(output
->otmTextMetrics
.tmExternalLeading
);
1522 output
->otmTextMetrics
.tmAveCharWidth
= WDPTOLP(output
->otmTextMetrics
.tmAveCharWidth
);
1523 output
->otmTextMetrics
.tmMaxCharWidth
= WDPTOLP(output
->otmTextMetrics
.tmMaxCharWidth
);
1524 output
->otmTextMetrics
.tmOverhang
= WDPTOLP(output
->otmTextMetrics
.tmOverhang
);
1525 output
->otmAscent
= HDPTOLP(output
->otmAscent
);
1526 output
->otmDescent
= HDPTOLP(output
->otmDescent
);
1527 output
->otmLineGap
= HDPTOLP(output
->otmLineGap
);
1528 output
->otmsCapEmHeight
= HDPTOLP(output
->otmsCapEmHeight
);
1529 output
->otmsXHeight
= HDPTOLP(output
->otmsXHeight
);
1530 output
->otmrcFontBox
.top
= HDPTOLP(output
->otmrcFontBox
.top
);
1531 output
->otmrcFontBox
.bottom
= HDPTOLP(output
->otmrcFontBox
.bottom
);
1532 output
->otmrcFontBox
.left
= WDPTOLP(output
->otmrcFontBox
.left
);
1533 output
->otmrcFontBox
.right
= WDPTOLP(output
->otmrcFontBox
.right
);
1534 output
->otmMacAscent
= HDPTOLP(output
->otmMacAscent
);
1535 output
->otmMacDescent
= HDPTOLP(output
->otmMacDescent
);
1536 output
->otmMacLineGap
= HDPTOLP(output
->otmMacLineGap
);
1537 output
->otmptSubscriptSize
.x
= WDPTOLP(output
->otmptSubscriptSize
.x
);
1538 output
->otmptSubscriptSize
.y
= HDPTOLP(output
->otmptSubscriptSize
.y
);
1539 output
->otmptSubscriptOffset
.x
= WDPTOLP(output
->otmptSubscriptOffset
.x
);
1540 output
->otmptSubscriptOffset
.y
= HDPTOLP(output
->otmptSubscriptOffset
.y
);
1541 output
->otmptSuperscriptSize
.x
= WDPTOLP(output
->otmptSuperscriptSize
.x
);
1542 output
->otmptSuperscriptSize
.y
= HDPTOLP(output
->otmptSuperscriptSize
.y
);
1543 output
->otmptSuperscriptOffset
.x
= WDPTOLP(output
->otmptSuperscriptOffset
.x
);
1544 output
->otmptSuperscriptOffset
.y
= HDPTOLP(output
->otmptSuperscriptOffset
.y
);
1545 output
->otmsStrikeoutSize
= HDPTOLP(output
->otmsStrikeoutSize
);
1546 output
->otmsStrikeoutPosition
= HDPTOLP(output
->otmsStrikeoutPosition
);
1547 output
->otmsUnderscoreSize
= HDPTOLP(output
->otmsUnderscoreSize
);
1548 output
->otmsUnderscorePosition
= HDPTOLP(output
->otmsUnderscorePosition
);
1551 if(output
!= lpOTM
) {
1552 memcpy(lpOTM
, output
, cbData
);
1553 HeapFree(GetProcessHeap(), 0, output
);
1559 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1560 but really this should just be a return 0. */
1562 ret
= sizeof(*lpOTM
);
1567 memset(lpOTM
, 0, ret
);
1568 lpOTM
->otmSize
= sizeof(*lpOTM
);
1569 GetTextMetricsW(hdc
, &lpOTM
->otmTextMetrics
);
1571 Further fill of the structure not implemented,
1572 Needs real values for the structure members
1577 GDI_ReleaseObj(hdc
);
1582 /***********************************************************************
1583 * GetCharWidthW (GDI32.@)
1584 * GetCharWidth32W (GDI32.@)
1586 BOOL WINAPI
GetCharWidth32W( HDC hdc
, UINT firstChar
, UINT lastChar
,
1591 DC
* dc
= DC_GetDCPtr( hdc
);
1592 if (!dc
) return FALSE
;
1595 ret
= WineEngGetCharWidth( dc
->gdiFont
, firstChar
, lastChar
, buffer
);
1596 else if (dc
->funcs
->pGetCharWidth
)
1597 ret
= dc
->funcs
->pGetCharWidth( dc
->physDev
, firstChar
, lastChar
, buffer
);
1601 /* convert device units to logical */
1602 for( i
= firstChar
; i
<= lastChar
; i
++, buffer
++ )
1603 *buffer
= INTERNAL_XDSTOWS(dc
, *buffer
);
1606 GDI_ReleaseObj( hdc
);
1611 /***********************************************************************
1612 * GetCharWidthA (GDI32.@)
1613 * GetCharWidth32A (GDI32.@)
1615 BOOL WINAPI
GetCharWidth32A( HDC hdc
, UINT firstChar
, UINT lastChar
,
1618 INT i
, wlen
, count
= (INT
)(lastChar
- firstChar
+ 1);
1623 if(count
<= 0) return FALSE
;
1625 str
= HeapAlloc(GetProcessHeap(), 0, count
);
1626 for(i
= 0; i
< count
; i
++)
1627 str
[i
] = (BYTE
)(firstChar
+ i
);
1629 wstr
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
1631 for(i
= 0; i
< wlen
; i
++)
1633 if(!GetCharWidth32W(hdc
, wstr
[i
], wstr
[i
], buffer
))
1641 HeapFree(GetProcessHeap(), 0, str
);
1642 HeapFree(GetProcessHeap(), 0, wstr
);
1648 /***********************************************************************
1649 * ExtTextOutA (GDI32.@)
1651 BOOL WINAPI
ExtTextOutA( HDC hdc
, INT x
, INT y
, UINT flags
,
1652 const RECT
*lprect
, LPCSTR str
, UINT count
, const INT
*lpDx
)
1656 LPWSTR p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, &codepage
);
1661 unsigned int i
= 0, j
= 0;
1663 lpDxW
= (LPINT
)HeapAlloc( GetProcessHeap(), 0, wlen
*sizeof(INT
));
1665 if(IsDBCSLeadByteEx(codepage
, str
[i
])) {
1666 lpDxW
[j
++] = lpDx
[i
] + lpDx
[i
+1];
1669 lpDxW
[j
++] = lpDx
[i
];
1675 ret
= ExtTextOutW( hdc
, x
, y
, flags
, lprect
, p
, wlen
, lpDxW
);
1677 HeapFree( GetProcessHeap(), 0, p
);
1678 if (lpDxW
) HeapFree( GetProcessHeap(), 0, lpDxW
);
1683 /***********************************************************************
1684 * ExtTextOutW (GDI32.@)
1686 BOOL WINAPI
ExtTextOutW( HDC hdc
, INT x
, INT y
, UINT flags
,
1687 const RECT
*lprect
, LPCWSTR str
, UINT count
, const INT
*lpDx
)
1690 DC
* dc
= DC_GetDCUpdate( hdc
);
1693 if(PATH_IsPathOpen(dc
->path
))
1694 FIXME("called on an open path\n");
1695 else if(dc
->funcs
->pExtTextOut
)
1697 if( !(flags
&(ETO_GLYPH_INDEX
|ETO_IGNORELANGUAGE
)) && BidiAvail
&& count
>0 )
1699 /* The caller did not specify that language processing was already done.
1701 LPWSTR lpReorderedString
=HeapAlloc(GetProcessHeap(), 0, count
*sizeof(WCHAR
));
1703 BIDI_Reorder( str
, count
, GCP_REORDER
,
1704 ((flags
&ETO_RTLREADING
)!=0 || (GetTextAlign(hdc
)&TA_RTLREADING
)!=0)?
1705 WINE_GCPW_FORCE_RTL
:WINE_GCPW_FORCE_LTR
,
1706 lpReorderedString
, count
, NULL
);
1708 ret
= dc
->funcs
->pExtTextOut(dc
->physDev
,x
,y
,flags
|ETO_IGNORELANGUAGE
,
1709 lprect
,lpReorderedString
,count
,lpDx
,dc
->breakExtra
);
1710 HeapFree(GetProcessHeap(), 0, lpReorderedString
);
1712 ret
= dc
->funcs
->pExtTextOut(dc
->physDev
,x
,y
,flags
,lprect
,str
,count
,
1713 lpDx
,dc
->breakExtra
);
1715 GDI_ReleaseObj( hdc
);
1721 /***********************************************************************
1722 * TextOutA (GDI32.@)
1724 BOOL WINAPI
TextOutA( HDC hdc
, INT x
, INT y
, LPCSTR str
, INT count
)
1726 return ExtTextOutA( hdc
, x
, y
, 0, NULL
, str
, count
, NULL
);
1730 /***********************************************************************
1731 * TextOutW (GDI32.@)
1733 BOOL WINAPI
TextOutW(HDC hdc
, INT x
, INT y
, LPCWSTR str
, INT count
)
1735 return ExtTextOutW( hdc
, x
, y
, 0, NULL
, str
, count
, NULL
);
1739 /***********************************************************************
1740 * PolyTextOutA (GDI32.@)
1742 * Draw several Strings
1744 BOOL WINAPI
PolyTextOutA ( HDC hdc
, /* [in] Handle to device context */
1745 PPOLYTEXTA pptxt
, /* [in] Array of strings */
1746 INT cStrings
) /* [in] Number of strings in array */
1748 for (; cStrings
>0; cStrings
--, pptxt
++)
1749 if (!ExtTextOutA( hdc
, pptxt
->x
, pptxt
->y
, pptxt
->uiFlags
, &pptxt
->rcl
, pptxt
->lpstr
, pptxt
->n
, pptxt
->pdx
))
1756 /***********************************************************************
1757 * PolyTextOutW (GDI32.@)
1759 * Draw several Strings
1761 BOOL WINAPI
PolyTextOutW ( HDC hdc
, /* [in] Handle to device context */
1762 PPOLYTEXTW pptxt
, /* [in] Array of strings */
1763 INT cStrings
) /* [in] Number of strings in array */
1765 for (; cStrings
>0; cStrings
--, pptxt
++)
1766 if (!ExtTextOutW( hdc
, pptxt
->x
, pptxt
->y
, pptxt
->uiFlags
, &pptxt
->rcl
, pptxt
->lpstr
, pptxt
->n
, pptxt
->pdx
))
1772 /* FIXME: all following APIs ******************************************/
1775 /***********************************************************************
1776 * SetMapperFlags (GDI32.@)
1778 DWORD WINAPI
SetMapperFlags( HDC hDC
, DWORD dwFlag
)
1780 DC
*dc
= DC_GetDCPtr( hDC
);
1783 if(dc
->funcs
->pSetMapperFlags
)
1784 ret
= dc
->funcs
->pSetMapperFlags( dc
->physDev
, dwFlag
);
1786 FIXME("(%p, 0x%08lx): stub - harmless\n", hDC
, dwFlag
);
1787 GDI_ReleaseObj( hDC
);
1791 /***********************************************************************
1792 * GetAspectRatioFilterEx (GDI.486)
1794 BOOL16 WINAPI
GetAspectRatioFilterEx16( HDC16 hdc
, LPSIZE16 pAspectRatio
)
1796 FIXME("(%04x, %p): -- Empty Stub !\n", hdc
, pAspectRatio
);
1800 /***********************************************************************
1801 * GetAspectRatioFilterEx (GDI32.@)
1803 BOOL WINAPI
GetAspectRatioFilterEx( HDC hdc
, LPSIZE pAspectRatio
)
1805 FIXME("(%p, %p): -- Empty Stub !\n", hdc
, pAspectRatio
);
1810 /***********************************************************************
1811 * GetCharABCWidthsA (GDI32.@)
1813 BOOL WINAPI
GetCharABCWidthsA(HDC hdc
, UINT firstChar
, UINT lastChar
,
1816 INT i
, wlen
, count
= (INT
)(lastChar
- firstChar
+ 1);
1821 if(count
<= 0) return FALSE
;
1823 str
= HeapAlloc(GetProcessHeap(), 0, count
);
1824 for(i
= 0; i
< count
; i
++)
1825 str
[i
] = (BYTE
)(firstChar
+ i
);
1827 wstr
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
1829 for(i
= 0; i
< wlen
; i
++)
1831 if(!GetCharABCWidthsW(hdc
, wstr
[i
], wstr
[i
], abc
))
1839 HeapFree(GetProcessHeap(), 0, str
);
1840 HeapFree(GetProcessHeap(), 0, wstr
);
1846 /******************************************************************************
1847 * GetCharABCWidthsW [GDI32.@]
1849 * Retrieves widths of characters in range.
1852 * hdc [I] Handle of device context
1853 * firstChar [I] First character in range to query
1854 * lastChar [I] Last character in range to query
1855 * abc [O] Address of character-width structure
1858 * Only works with TrueType fonts
1864 BOOL WINAPI
GetCharABCWidthsW( HDC hdc
, UINT firstChar
, UINT lastChar
,
1867 DC
*dc
= DC_GetDCPtr(hdc
);
1872 ret
= WineEngGetCharABCWidths( dc
->gdiFont
, firstChar
, lastChar
, abc
);
1878 /* convert device units to logical */
1879 for( i
= firstChar
; i
<= lastChar
; i
++, abc
++ ) {
1880 abc
->abcA
= INTERNAL_XDSTOWS(dc
, abc
->abcA
);
1881 abc
->abcB
= INTERNAL_XDSTOWS(dc
, abc
->abcB
);
1882 abc
->abcC
= INTERNAL_XDSTOWS(dc
, abc
->abcC
);
1887 GDI_ReleaseObj(hdc
);
1892 /***********************************************************************
1893 * GetGlyphOutline (GDI.309)
1895 DWORD WINAPI
GetGlyphOutline16( HDC16 hdc
, UINT16 uChar
, UINT16 fuFormat
,
1896 LPGLYPHMETRICS16 lpgm
, DWORD cbBuffer
,
1897 LPVOID lpBuffer
, const MAT2
*lpmat2
)
1899 FIXME("(%04x, '%c', %04x, %p, %ld, %p, %p): stub\n",
1900 hdc
, uChar
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
, lpmat2
);
1901 return ~0UL; /* failure */
1905 /***********************************************************************
1906 * GetGlyphOutlineA (GDI32.@)
1908 DWORD WINAPI
GetGlyphOutlineA( HDC hdc
, UINT uChar
, UINT fuFormat
,
1909 LPGLYPHMETRICS lpgm
, DWORD cbBuffer
,
1910 LPVOID lpBuffer
, const MAT2
*lpmat2
)
1916 if(!(fuFormat
& GGO_GLYPH_INDEX
)) {
1917 p
= FONT_mbtowc(hdc
, (char*)&uChar
, 1, NULL
, NULL
);
1921 ret
= GetGlyphOutlineW(hdc
, c
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
,
1924 HeapFree(GetProcessHeap(), 0, p
);
1928 /***********************************************************************
1929 * GetGlyphOutlineW (GDI32.@)
1931 DWORD WINAPI
GetGlyphOutlineW( HDC hdc
, UINT uChar
, UINT fuFormat
,
1932 LPGLYPHMETRICS lpgm
, DWORD cbBuffer
,
1933 LPVOID lpBuffer
, const MAT2
*lpmat2
)
1935 DC
*dc
= DC_GetDCPtr(hdc
);
1938 TRACE("(%p, %04x, %04x, %p, %ld, %p, %p)\n",
1939 hdc
, uChar
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
, lpmat2
);
1941 if(!dc
) return GDI_ERROR
;
1944 ret
= WineEngGetGlyphOutline(dc
->gdiFont
, uChar
, fuFormat
, lpgm
,
1945 cbBuffer
, lpBuffer
, lpmat2
);
1949 GDI_ReleaseObj(hdc
);
1954 /***********************************************************************
1955 * CreateScalableFontResourceA (GDI32.@)
1957 BOOL WINAPI
CreateScalableFontResourceA( DWORD fHidden
,
1958 LPCSTR lpszResourceFile
,
1959 LPCSTR lpszFontFile
,
1960 LPCSTR lpszCurrentPath
)
1964 /* fHidden=1 - only visible for the calling app, read-only, not
1965 * enumbered with EnumFonts/EnumFontFamilies
1966 * lpszCurrentPath can be NULL
1968 FIXME("(%ld,%s,%s,%s): stub\n",
1969 fHidden
, debugstr_a(lpszResourceFile
), debugstr_a(lpszFontFile
),
1970 debugstr_a(lpszCurrentPath
) );
1972 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
1973 if ((f
= CreateFileA(lpszResourceFile
, 0, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, 0)) != INVALID_HANDLE_VALUE
) {
1975 SetLastError(ERROR_FILE_EXISTS
);
1978 return FALSE
; /* create failed */
1981 /***********************************************************************
1982 * CreateScalableFontResourceW (GDI32.@)
1984 BOOL WINAPI
CreateScalableFontResourceW( DWORD fHidden
,
1985 LPCWSTR lpszResourceFile
,
1986 LPCWSTR lpszFontFile
,
1987 LPCWSTR lpszCurrentPath
)
1989 FIXME("(%ld,%p,%p,%p): stub\n",
1990 fHidden
, lpszResourceFile
, lpszFontFile
, lpszCurrentPath
);
1991 return FALSE
; /* create failed */
1995 /*************************************************************************
1996 * GetRasterizerCaps (GDI32.@)
1998 BOOL WINAPI
GetRasterizerCaps( LPRASTERIZER_STATUS lprs
, UINT cbNumBytes
)
2000 lprs
->nSize
= sizeof(RASTERIZER_STATUS
);
2001 lprs
->wFlags
= TT_AVAILABLE
|TT_ENABLED
;
2002 lprs
->nLanguageID
= 0;
2007 /*************************************************************************
2008 * GetKerningPairsA (GDI32.@)
2010 DWORD WINAPI
GetKerningPairsA( HDC hDC
, DWORD cPairs
,
2011 LPKERNINGPAIR lpKerningPairs
)
2013 return GetKerningPairsW( hDC
, cPairs
, lpKerningPairs
);
2017 /*************************************************************************
2018 * GetKerningPairsW (GDI32.@)
2020 DWORD WINAPI
GetKerningPairsW( HDC hDC
, DWORD cPairs
,
2021 LPKERNINGPAIR lpKerningPairs
)
2024 FIXME("(%p,%ld,%p): almost empty stub!\n", hDC
, cPairs
, lpKerningPairs
);
2025 for (i
= 0; i
< cPairs
; i
++)
2026 lpKerningPairs
[i
].iKernAmount
= 0;
2030 /*************************************************************************
2031 * TranslateCharsetInfo [GDI32.@]
2033 * Fills a CHARSETINFO structure for a character set, code page, or
2034 * font. This allows making the correspondance between different labelings
2035 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2036 * of the same encoding.
2038 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2039 * only one codepage should be set in *lpSrc.
2042 * TRUE on success, FALSE on failure.
2045 BOOL WINAPI
TranslateCharsetInfo(
2046 LPDWORD lpSrc
, /* [in]
2047 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2048 if flags == TCI_SRCCHARSET: a character set value
2049 if flags == TCI_SRCCODEPAGE: a code page value
2051 LPCHARSETINFO lpCs
, /* [out] structure to receive charset information */
2052 DWORD flags
/* [in] determines interpretation of lpSrc */)
2056 case TCI_SRCFONTSIG
:
2057 while (!(*lpSrc
>>index
& 0x0001) && index
<MAXTCIINDEX
) index
++;
2059 case TCI_SRCCODEPAGE
:
2060 while ((UINT
) (lpSrc
) != FONT_tci
[index
].ciACP
&& index
< MAXTCIINDEX
) index
++;
2062 case TCI_SRCCHARSET
:
2063 while ((UINT
) (lpSrc
) != FONT_tci
[index
].ciCharset
&& index
< MAXTCIINDEX
) index
++;
2068 if (index
>= MAXTCIINDEX
|| FONT_tci
[index
].ciCharset
== DEFAULT_CHARSET
) return FALSE
;
2069 memcpy(lpCs
, &FONT_tci
[index
], sizeof(CHARSETINFO
));
2073 /*************************************************************************
2074 * GetFontLanguageInfo (GDI32.@)
2076 DWORD WINAPI
GetFontLanguageInfo(HDC hdc
)
2078 FONTSIGNATURE fontsig
;
2079 static const DWORD GCP_DBCS_MASK
=0x003F0000,
2080 GCP_DIACRITIC_MASK
=0x00000000,
2081 FLI_GLYPHS_MASK
=0x00000000,
2082 GCP_GLYPHSHAPE_MASK
=0x00000040,
2083 GCP_KASHIDA_MASK
=0x00000000,
2084 GCP_LIGATE_MASK
=0x00000000,
2085 GCP_USEKERNING_MASK
=0x00000000,
2086 GCP_REORDER_MASK
=0x00000060;
2090 GetTextCharsetInfo( hdc
, &fontsig
, 0 );
2091 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2093 if( (fontsig
.fsCsb
[0]&GCP_DBCS_MASK
)!=0 )
2096 if( (fontsig
.fsCsb
[0]&GCP_DIACRITIC_MASK
)!=0 )
2097 result
|=GCP_DIACRITIC
;
2099 if( (fontsig
.fsCsb
[0]&FLI_GLYPHS_MASK
)!=0 )
2102 if( (fontsig
.fsCsb
[0]&GCP_GLYPHSHAPE_MASK
)!=0 )
2103 result
|=GCP_GLYPHSHAPE
;
2105 if( (fontsig
.fsCsb
[0]&GCP_KASHIDA_MASK
)!=0 )
2106 result
|=GCP_KASHIDA
;
2108 if( (fontsig
.fsCsb
[0]&GCP_LIGATE_MASK
)!=0 )
2111 if( (fontsig
.fsCsb
[0]&GCP_USEKERNING_MASK
)!=0 )
2112 result
|=GCP_USEKERNING
;
2114 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2115 if( GetTextAlign( hdc
) & TA_RTLREADING
)
2116 if( (fontsig
.fsCsb
[0]&GCP_REORDER_MASK
)!=0 )
2117 result
|=GCP_REORDER
;
2123 /*************************************************************************
2124 * GetFontData [GDI32.@]
2126 * Retrieve data for TrueType font.
2130 * success: Number of bytes returned
2131 * failure: GDI_ERROR
2135 * Calls SetLastError()
2138 DWORD WINAPI
GetFontData(HDC hdc
, DWORD table
, DWORD offset
,
2139 LPVOID buffer
, DWORD length
)
2141 DC
*dc
= DC_GetDCPtr(hdc
);
2142 DWORD ret
= GDI_ERROR
;
2144 if(!dc
) return GDI_ERROR
;
2147 ret
= WineEngGetFontData(dc
->gdiFont
, table
, offset
, buffer
, length
);
2149 GDI_ReleaseObj(hdc
);
2153 /*************************************************************************
2154 * GetGlyphIndicesA [GDI32.@]
2156 DWORD WINAPI
GetGlyphIndicesA(HDC hdc
, LPCSTR lpstr
, INT count
,
2157 LPWORD pgi
, DWORD flags
)
2163 TRACE("(%p, %s, %d, %p, 0x%lx)\n",
2164 hdc
, debugstr_an(lpstr
, count
), count
, pgi
, flags
);
2166 lpstrW
= FONT_mbtowc(hdc
, lpstr
, count
, &countW
, NULL
);
2167 ret
= GetGlyphIndicesW(hdc
, lpstrW
, countW
, pgi
, flags
);
2168 HeapFree(GetProcessHeap(), 0, lpstrW
);
2173 /*************************************************************************
2174 * GetGlyphIndicesW [GDI32.@]
2176 DWORD WINAPI
GetGlyphIndicesW(HDC hdc
, LPCWSTR lpstr
, INT count
,
2177 LPWORD pgi
, DWORD flags
)
2179 DC
*dc
= DC_GetDCPtr(hdc
);
2180 DWORD ret
= GDI_ERROR
;
2182 TRACE("(%p, %s, %d, %p, 0x%lx)\n",
2183 hdc
, debugstr_wn(lpstr
, count
), count
, pgi
, flags
);
2185 if(!dc
) return GDI_ERROR
;
2188 ret
= WineEngGetGlyphIndices(dc
->gdiFont
, lpstr
, count
, pgi
, flags
);
2190 GDI_ReleaseObj(hdc
);
2194 /*************************************************************************
2195 * GetCharacterPlacementA [GDI32.@]
2198 * the web browser control of ie4 calls this with dwFlags=0
2201 GetCharacterPlacementA(HDC hdc
, LPCSTR lpString
, INT uCount
,
2202 INT nMaxExtent
, GCP_RESULTSA
*lpResults
,
2207 GCP_RESULTSW resultsW
;
2211 TRACE("%s, %d, %d, 0x%08lx\n",
2212 debugstr_an(lpString
, uCount
), uCount
, nMaxExtent
, dwFlags
);
2214 /* both structs are equal in size */
2215 memcpy(&resultsW
, lpResults
, sizeof(resultsW
));
2217 lpStringW
= FONT_mbtowc(hdc
, lpString
, uCount
, &uCountW
, &font_cp
);
2218 if(lpResults
->lpOutString
)
2219 resultsW
.lpOutString
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*uCountW
);
2221 ret
= GetCharacterPlacementW(hdc
, lpStringW
, uCountW
, nMaxExtent
, &resultsW
, dwFlags
);
2223 if(lpResults
->lpOutString
) {
2224 WideCharToMultiByte(font_cp
, 0, resultsW
.lpOutString
, uCountW
,
2225 lpResults
->lpOutString
, uCount
, NULL
, NULL
);
2228 HeapFree(GetProcessHeap(), 0, lpStringW
);
2229 HeapFree(GetProcessHeap(), 0, resultsW
.lpOutString
);
2234 /*************************************************************************
2235 * GetCharacterPlacementW [GDI32.@]
2237 * Retrieve information about a string. This includes the width, reordering,
2238 * Glyphing and so on.
2242 * The width and height of the string if successful, 0 if failed.
2246 * All flags except GCP_REORDER are not yet implemented.
2247 * Reordering is not 100% complient to the Windows BiDi method.
2248 * Caret positioning is not yet implemented for BiDi.
2249 * Classes are not yet implemented.
2253 GetCharacterPlacementW(
2254 HDC hdc
, /* [in] Device context for which the rendering is to be done */
2255 LPCWSTR lpString
, /* [in] The string for which information is to be returned */
2256 INT uCount
, /* [in] Number of WORDS in string. */
2257 INT nMaxExtent
, /* [in] Maximum extent the string is to take (in HDC logical units) */
2258 GCP_RESULTSW
*lpResults
,/* [in/out] A pointer to a GCP_RESULTSW struct */
2259 DWORD dwFlags
/* [in] Flags specifying how to process the string */
2266 TRACE("%s, %d, %d, 0x%08lx\n",
2267 debugstr_wn(lpString
, uCount
), uCount
, nMaxExtent
, dwFlags
);
2269 TRACE("lStructSize=%ld, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2270 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2271 lpResults
->lStructSize
, lpResults
->lpOutString
, lpResults
->lpOrder
,
2272 lpResults
->lpDx
, lpResults
->lpCaretPos
, lpResults
->lpClass
,
2273 lpResults
->lpGlyphs
, lpResults
->nGlyphs
, lpResults
->nMaxFit
);
2275 if(dwFlags
&(~GCP_REORDER
)) FIXME("flags 0x%08lx ignored\n", dwFlags
);
2276 if(lpResults
->lpClass
) FIXME("classes not implemented\n");
2277 if (lpResults
->lpCaretPos
&& (dwFlags
& GCP_REORDER
))
2278 FIXME("Caret positions for complex scripts not implemented\n");
2280 nSet
= (UINT
)uCount
;
2281 if(nSet
> lpResults
->nGlyphs
)
2282 nSet
= lpResults
->nGlyphs
;
2284 /* return number of initialized fields */
2285 lpResults
->nGlyphs
= nSet
;
2287 if((dwFlags
&GCP_REORDER
)==0 || !BidiAvail
)
2289 /* Treat the case where no special handling was requested in a fastpath way */
2290 /* copy will do if the GCP_REORDER flag is not set */
2291 if(lpResults
->lpOutString
)
2292 strncpyW( lpResults
->lpOutString
, lpString
, nSet
);
2294 if(lpResults
->lpOrder
)
2296 for(i
= 0; i
< nSet
; i
++)
2297 lpResults
->lpOrder
[i
] = i
;
2301 BIDI_Reorder( lpString
, uCount
, dwFlags
, WINE_GCPW_FORCE_LTR
, lpResults
->lpOutString
,
2302 nSet
, lpResults
->lpOrder
);
2305 /* FIXME: Will use the placement chars */
2306 if (lpResults
->lpDx
)
2309 for (i
= 0; i
< nSet
; i
++)
2311 if (GetCharWidth32W(hdc
, lpString
[i
], lpString
[i
], &c
))
2312 lpResults
->lpDx
[i
]= c
;
2316 if (lpResults
->lpCaretPos
&& !(dwFlags
& GCP_REORDER
))
2320 lpResults
->lpCaretPos
[0] = 0;
2321 for (i
= 1; i
< nSet
; i
++)
2322 if (GetTextExtentPoint32W(hdc
, &(lpString
[i
- 1]), 1, &size
))
2323 lpResults
->lpCaretPos
[i
] = (pos
+= size
.cx
);
2326 if(lpResults
->lpGlyphs
)
2327 GetGlyphIndicesW(hdc
, lpString
, nSet
, lpResults
->lpGlyphs
, 0);
2329 if (GetTextExtentPoint32W(hdc
, lpString
, uCount
, &size
))
2330 ret
= MAKELONG(size
.cx
, size
.cy
);
2335 /*************************************************************************
2336 * GetCharABCWidthsFloatA [GDI32.@]
2338 BOOL WINAPI
GetCharABCWidthsFloatA(HDC hdc
, UINT iFirstChar
, UINT iLastChar
,
2341 FIXME_(gdi
)("GetCharABCWidthsFloatA, stub\n");
2345 /*************************************************************************
2346 * GetCharABCWidthsFloatW [GDI32.@]
2348 BOOL WINAPI
GetCharABCWidthsFloatW(HDC hdc
, UINT iFirstChar
,
2349 UINT iLastChar
, LPABCFLOAT lpABCF
)
2351 FIXME_(gdi
)("GetCharABCWidthsFloatW, stub\n");
2355 /*************************************************************************
2356 * GetCharWidthFloatA [GDI32.@]
2358 BOOL WINAPI
GetCharWidthFloatA(HDC hdc
, UINT iFirstChar
,
2359 UINT iLastChar
, PFLOAT pxBuffer
)
2361 FIXME_(gdi
)("GetCharWidthFloatA, stub\n");
2365 /*************************************************************************
2366 * GetCharWidthFloatW [GDI32.@]
2368 BOOL WINAPI
GetCharWidthFloatW(HDC hdc
, UINT iFirstChar
,
2369 UINT iLastChar
, PFLOAT pxBuffer
)
2371 FIXME_(gdi
)("GetCharWidthFloatW, stub\n");
2376 /***********************************************************************
2378 * Font Resource API *
2380 ***********************************************************************/
2382 /***********************************************************************
2383 * AddFontResourceA (GDI32.@)
2385 INT WINAPI
AddFontResourceA( LPCSTR str
)
2387 return AddFontResourceExA( str
, 0, NULL
);
2390 /***********************************************************************
2391 * AddFontResourceW (GDI32.@)
2393 INT WINAPI
AddFontResourceW( LPCWSTR str
)
2395 return AddFontResourceExW(str
, 0, NULL
);
2399 /***********************************************************************
2400 * AddFontResourceExA (GDI32.@)
2402 INT WINAPI
AddFontResourceExA( LPCSTR str
, DWORD fl
, PVOID pdv
)
2404 DWORD len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
2405 LPWSTR strW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2408 MultiByteToWideChar(CP_ACP
, 0, str
, -1, strW
, len
);
2409 ret
= AddFontResourceExW(strW
, fl
, pdv
);
2410 HeapFree(GetProcessHeap(), 0, strW
);
2414 /***********************************************************************
2415 * AddFontResourceExW (GDI32.@)
2417 INT WINAPI
AddFontResourceExW( LPCWSTR str
, DWORD fl
, PVOID pdv
)
2419 return WineEngAddFontResourceEx(str
, fl
, pdv
);
2422 /***********************************************************************
2423 * RemoveFontResourceA (GDI32.@)
2425 BOOL WINAPI
RemoveFontResourceA( LPCSTR str
)
2427 return RemoveFontResourceExA(str
, 0, 0);
2430 /***********************************************************************
2431 * RemoveFontResourceW (GDI32.@)
2433 BOOL WINAPI
RemoveFontResourceW( LPCWSTR str
)
2435 return RemoveFontResourceExW(str
, 0, 0);
2438 /***********************************************************************
2439 * RemoveFontResourceExA (GDI32.@)
2441 BOOL WINAPI
RemoveFontResourceExA( LPCSTR str
, DWORD fl
, PVOID pdv
)
2443 DWORD len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
2444 LPWSTR strW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2447 MultiByteToWideChar(CP_ACP
, 0, str
, -1, strW
, len
);
2448 ret
= RemoveFontResourceExW(strW
, fl
, pdv
);
2449 HeapFree(GetProcessHeap(), 0, strW
);
2453 /***********************************************************************
2454 * RemoveFontResourceExW (GDI32.@)
2456 BOOL WINAPI
RemoveFontResourceExW( LPCWSTR str
, DWORD fl
, PVOID pdv
)
2458 return WineEngRemoveFontResourceEx(str
, fl
, pdv
);
2461 /***********************************************************************
2462 * GetTextCharset (GDI32.@)
2464 UINT WINAPI
GetTextCharset(HDC hdc
)
2466 /* MSDN docs say this is equivalent */
2467 return GetTextCharsetInfo(hdc
, NULL
, 0);
2470 /***********************************************************************
2471 * GetTextCharsetInfo (GDI32.@)
2473 UINT WINAPI
GetTextCharsetInfo(HDC hdc
, LPFONTSIGNATURE fs
, DWORD flags
)
2475 UINT ret
= DEFAULT_CHARSET
;
2476 DC
*dc
= DC_GetDCPtr(hdc
);
2481 ret
= WineEngGetTextCharsetInfo(dc
->gdiFont
, fs
, flags
);
2483 GDI_ReleaseObj(hdc
);
2486 if (ret
== DEFAULT_CHARSET
&& fs
)
2487 memset(fs
, 0, sizeof(FONTSIGNATURE
));