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"
35 #include "gdi_private.h"
36 #include "wine/unicode.h"
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(font
);
41 /* Device -> World size conversion */
43 /* Performs a device to world transformation on the specified width (which
44 * is in integer format).
46 static inline INT
INTERNAL_XDSTOWS(DC
*dc
, INT width
)
50 /* Perform operation with floating point */
51 floatWidth
= (FLOAT
)width
* dc
->xformVport2World
.eM11
;
52 /* Round to integers */
53 return GDI_ROUND(floatWidth
);
56 /* Performs a device to world transformation on the specified size (which
57 * is in integer format).
59 static inline INT
INTERNAL_YDSTOWS(DC
*dc
, INT height
)
63 /* Perform operation with floating point */
64 floatHeight
= (FLOAT
)height
* dc
->xformVport2World
.eM22
;
65 /* Round to integers */
66 return GDI_ROUND(floatHeight
);
69 static inline INT
INTERNAL_XWSTODS(DC
*dc
, INT width
)
72 pt
[0].x
= pt
[0].y
= 0;
75 LPtoDP(dc
->hSelf
, pt
, 2);
76 return pt
[1].x
- pt
[0].x
;
79 static inline INT
INTERNAL_YWSTODS(DC
*dc
, INT height
)
82 pt
[0].x
= pt
[0].y
= 0;
85 LPtoDP(dc
->hSelf
, pt
, 2);
86 return pt
[1].y
- pt
[0].y
;
89 static HGDIOBJ
FONT_SelectObject( HGDIOBJ handle
, void *obj
, HDC hdc
);
90 static INT
FONT_GetObject16( HGDIOBJ handle
, void *obj
, INT count
, LPVOID buffer
);
91 static INT
FONT_GetObjectA( HGDIOBJ handle
, void *obj
, INT count
, LPVOID buffer
);
92 static INT
FONT_GetObjectW( HGDIOBJ handle
, void *obj
, INT count
, LPVOID buffer
);
93 static BOOL
FONT_DeleteObject( HGDIOBJ handle
, void *obj
);
95 static const struct gdi_obj_funcs font_funcs
=
97 FONT_SelectObject
, /* pSelectObject */
98 FONT_GetObject16
, /* pGetObject16 */
99 FONT_GetObjectA
, /* pGetObjectA */
100 FONT_GetObjectW
, /* pGetObjectW */
101 NULL
, /* pUnrealizeObject */
102 FONT_DeleteObject
/* pDeleteObject */
105 #define ENUM_UNICODE 0x00000001
106 #define ENUM_CALLED 0x00000002
116 LPLOGFONT16 lpLogFontParam
;
117 FONTENUMPROC16 lpEnumFunc
;
120 LPNEWTEXTMETRICEX16 lpTextMetric
;
121 LPENUMLOGFONTEX16 lpLogFont
;
122 SEGPTR segTextMetric
;
132 LPLOGFONTW lpLogFontParam
;
133 FONTENUMPROCW lpEnumFunc
;
142 * For TranslateCharsetInfo
144 #define FS(x) {{0,0,0,0},{0x1<<(x),0}}
145 #define MAXTCIINDEX 32
146 static const CHARSETINFO FONT_tci
[MAXTCIINDEX
] = {
148 { ANSI_CHARSET
, 1252, FS(0)},
149 { EASTEUROPE_CHARSET
, 1250, FS(1)},
150 { RUSSIAN_CHARSET
, 1251, FS(2)},
151 { GREEK_CHARSET
, 1253, FS(3)},
152 { TURKISH_CHARSET
, 1254, FS(4)},
153 { HEBREW_CHARSET
, 1255, FS(5)},
154 { ARABIC_CHARSET
, 1256, FS(6)},
155 { BALTIC_CHARSET
, 1257, FS(7)},
156 { VIETNAMESE_CHARSET
, 1258, FS(8)},
157 /* reserved by ANSI */
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 { DEFAULT_CHARSET
, 0, FS(0)},
166 { THAI_CHARSET
, 874, FS(16)},
167 { SHIFTJIS_CHARSET
, 932, FS(17)},
168 { GB2312_CHARSET
, 936, FS(18)},
169 { HANGEUL_CHARSET
, 949, FS(19)},
170 { CHINESEBIG5_CHARSET
, 950, FS(20)},
171 { JOHAB_CHARSET
, 1361, FS(21)},
172 /* reserved for alternate ANSI and OEM */
173 { DEFAULT_CHARSET
, 0, FS(0)},
174 { DEFAULT_CHARSET
, 0, FS(0)},
175 { DEFAULT_CHARSET
, 0, FS(0)},
176 { DEFAULT_CHARSET
, 0, FS(0)},
177 { DEFAULT_CHARSET
, 0, FS(0)},
178 { DEFAULT_CHARSET
, 0, FS(0)},
179 { DEFAULT_CHARSET
, 0, FS(0)},
180 { DEFAULT_CHARSET
, 0, FS(0)},
181 /* reserved for system */
182 { DEFAULT_CHARSET
, 0, FS(0)},
183 { SYMBOL_CHARSET
, CP_SYMBOL
, FS(31)},
186 /***********************************************************************
187 * LOGFONT conversion functions.
189 static void FONT_LogFontWTo16( const LOGFONTW
* font32
, LPLOGFONT16 font16
)
191 font16
->lfHeight
= font32
->lfHeight
;
192 font16
->lfWidth
= font32
->lfWidth
;
193 font16
->lfEscapement
= font32
->lfEscapement
;
194 font16
->lfOrientation
= font32
->lfOrientation
;
195 font16
->lfWeight
= font32
->lfWeight
;
196 font16
->lfItalic
= font32
->lfItalic
;
197 font16
->lfUnderline
= font32
->lfUnderline
;
198 font16
->lfStrikeOut
= font32
->lfStrikeOut
;
199 font16
->lfCharSet
= font32
->lfCharSet
;
200 font16
->lfOutPrecision
= font32
->lfOutPrecision
;
201 font16
->lfClipPrecision
= font32
->lfClipPrecision
;
202 font16
->lfQuality
= font32
->lfQuality
;
203 font16
->lfPitchAndFamily
= font32
->lfPitchAndFamily
;
204 WideCharToMultiByte( CP_ACP
, 0, font32
->lfFaceName
, -1,
205 font16
->lfFaceName
, LF_FACESIZE
, NULL
, NULL
);
206 font16
->lfFaceName
[LF_FACESIZE
-1] = 0;
209 static void FONT_LogFont16ToW( const LOGFONT16
*font16
, LPLOGFONTW font32
)
211 font32
->lfHeight
= font16
->lfHeight
;
212 font32
->lfWidth
= font16
->lfWidth
;
213 font32
->lfEscapement
= font16
->lfEscapement
;
214 font32
->lfOrientation
= font16
->lfOrientation
;
215 font32
->lfWeight
= font16
->lfWeight
;
216 font32
->lfItalic
= font16
->lfItalic
;
217 font32
->lfUnderline
= font16
->lfUnderline
;
218 font32
->lfStrikeOut
= font16
->lfStrikeOut
;
219 font32
->lfCharSet
= font16
->lfCharSet
;
220 font32
->lfOutPrecision
= font16
->lfOutPrecision
;
221 font32
->lfClipPrecision
= font16
->lfClipPrecision
;
222 font32
->lfQuality
= font16
->lfQuality
;
223 font32
->lfPitchAndFamily
= font16
->lfPitchAndFamily
;
224 MultiByteToWideChar( CP_ACP
, 0, font16
->lfFaceName
, -1, font32
->lfFaceName
, LF_FACESIZE
);
225 font32
->lfFaceName
[LF_FACESIZE
-1] = 0;
228 static void FONT_LogFontAToW( const LOGFONTA
*fontA
, LPLOGFONTW fontW
)
230 memcpy(fontW
, fontA
, sizeof(LOGFONTA
) - LF_FACESIZE
);
231 MultiByteToWideChar(CP_ACP
, 0, fontA
->lfFaceName
, -1, fontW
->lfFaceName
,
233 fontW
->lfFaceName
[LF_FACESIZE
-1] = 0;
236 static void FONT_LogFontWToA( const LOGFONTW
*fontW
, LPLOGFONTA fontA
)
238 memcpy(fontA
, fontW
, sizeof(LOGFONTA
) - LF_FACESIZE
);
239 WideCharToMultiByte(CP_ACP
, 0, fontW
->lfFaceName
, -1, fontA
->lfFaceName
,
240 LF_FACESIZE
, NULL
, NULL
);
241 fontA
->lfFaceName
[LF_FACESIZE
-1] = 0;
244 static void FONT_EnumLogFontExWTo16( const ENUMLOGFONTEXW
*fontW
, LPENUMLOGFONTEX16 font16
)
246 FONT_LogFontWTo16( (const LOGFONTW
*)fontW
, (LPLOGFONT16
)font16
);
248 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfFullName
, -1,
249 (LPSTR
) font16
->elfFullName
, LF_FULLFACESIZE
, NULL
, NULL
);
250 font16
->elfFullName
[LF_FULLFACESIZE
-1] = '\0';
251 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfStyle
, -1,
252 (LPSTR
) font16
->elfStyle
, LF_FACESIZE
, NULL
, NULL
);
253 font16
->elfStyle
[LF_FACESIZE
-1] = '\0';
254 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfScript
, -1,
255 (LPSTR
) font16
->elfScript
, LF_FACESIZE
, NULL
, NULL
);
256 font16
->elfScript
[LF_FACESIZE
-1] = '\0';
259 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW
*fontW
, LPENUMLOGFONTEXA fontA
)
261 FONT_LogFontWToA( (const LOGFONTW
*)fontW
, (LPLOGFONTA
)fontA
);
263 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfFullName
, -1,
264 (LPSTR
) fontA
->elfFullName
, LF_FULLFACESIZE
, NULL
, NULL
);
265 fontA
->elfFullName
[LF_FULLFACESIZE
-1] = '\0';
266 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfStyle
, -1,
267 (LPSTR
) fontA
->elfStyle
, LF_FACESIZE
, NULL
, NULL
);
268 fontA
->elfStyle
[LF_FACESIZE
-1] = '\0';
269 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfScript
, -1,
270 (LPSTR
) fontA
->elfScript
, LF_FACESIZE
, NULL
, NULL
);
271 fontA
->elfScript
[LF_FACESIZE
-1] = '\0';
274 /***********************************************************************
275 * TEXTMETRIC conversion functions.
277 static void FONT_TextMetricWToA(const TEXTMETRICW
*ptmW
, LPTEXTMETRICA ptmA
)
279 ptmA
->tmHeight
= ptmW
->tmHeight
;
280 ptmA
->tmAscent
= ptmW
->tmAscent
;
281 ptmA
->tmDescent
= ptmW
->tmDescent
;
282 ptmA
->tmInternalLeading
= ptmW
->tmInternalLeading
;
283 ptmA
->tmExternalLeading
= ptmW
->tmExternalLeading
;
284 ptmA
->tmAveCharWidth
= ptmW
->tmAveCharWidth
;
285 ptmA
->tmMaxCharWidth
= ptmW
->tmMaxCharWidth
;
286 ptmA
->tmWeight
= ptmW
->tmWeight
;
287 ptmA
->tmOverhang
= ptmW
->tmOverhang
;
288 ptmA
->tmDigitizedAspectX
= ptmW
->tmDigitizedAspectX
;
289 ptmA
->tmDigitizedAspectY
= ptmW
->tmDigitizedAspectY
;
290 ptmA
->tmFirstChar
= min(ptmW
->tmFirstChar
, 255);
291 if (ptmW
->tmCharSet
== SYMBOL_CHARSET
)
293 UINT last_char
= ptmW
->tmLastChar
;
294 if (last_char
> 0xf000) last_char
-= 0xf000;
295 ptmA
->tmLastChar
= min(last_char
, 255);
298 ptmA
->tmLastChar
= min(ptmW
->tmLastChar
, 255);
299 ptmA
->tmDefaultChar
= min(ptmW
->tmDefaultChar
, 255);
300 ptmA
->tmBreakChar
= min(ptmW
->tmBreakChar
, 255);
301 ptmA
->tmItalic
= ptmW
->tmItalic
;
302 ptmA
->tmUnderlined
= ptmW
->tmUnderlined
;
303 ptmA
->tmStruckOut
= ptmW
->tmStruckOut
;
304 ptmA
->tmPitchAndFamily
= ptmW
->tmPitchAndFamily
;
305 ptmA
->tmCharSet
= ptmW
->tmCharSet
;
309 static void FONT_NewTextMetricExWTo16(const NEWTEXTMETRICEXW
*ptmW
, LPNEWTEXTMETRICEX16 ptm16
)
311 ptm16
->ntmTm
.tmHeight
= ptmW
->ntmTm
.tmHeight
;
312 ptm16
->ntmTm
.tmAscent
= ptmW
->ntmTm
.tmAscent
;
313 ptm16
->ntmTm
.tmDescent
= ptmW
->ntmTm
.tmDescent
;
314 ptm16
->ntmTm
.tmInternalLeading
= ptmW
->ntmTm
.tmInternalLeading
;
315 ptm16
->ntmTm
.tmExternalLeading
= ptmW
->ntmTm
.tmExternalLeading
;
316 ptm16
->ntmTm
.tmAveCharWidth
= ptmW
->ntmTm
.tmAveCharWidth
;
317 ptm16
->ntmTm
.tmMaxCharWidth
= ptmW
->ntmTm
.tmMaxCharWidth
;
318 ptm16
->ntmTm
.tmWeight
= ptmW
->ntmTm
.tmWeight
;
319 ptm16
->ntmTm
.tmOverhang
= ptmW
->ntmTm
.tmOverhang
;
320 ptm16
->ntmTm
.tmDigitizedAspectX
= ptmW
->ntmTm
.tmDigitizedAspectX
;
321 ptm16
->ntmTm
.tmDigitizedAspectY
= ptmW
->ntmTm
.tmDigitizedAspectY
;
322 ptm16
->ntmTm
.tmFirstChar
= ptmW
->ntmTm
.tmFirstChar
> 255 ? 255 : ptmW
->ntmTm
.tmFirstChar
;
323 ptm16
->ntmTm
.tmLastChar
= ptmW
->ntmTm
.tmLastChar
> 255 ? 255 : ptmW
->ntmTm
.tmLastChar
;
324 ptm16
->ntmTm
.tmDefaultChar
= ptmW
->ntmTm
.tmDefaultChar
> 255 ? 255 : ptmW
->ntmTm
.tmDefaultChar
;
325 ptm16
->ntmTm
.tmBreakChar
= ptmW
->ntmTm
.tmBreakChar
> 255 ? 255 : ptmW
->ntmTm
.tmBreakChar
;
326 ptm16
->ntmTm
.tmItalic
= ptmW
->ntmTm
.tmItalic
;
327 ptm16
->ntmTm
.tmUnderlined
= ptmW
->ntmTm
.tmUnderlined
;
328 ptm16
->ntmTm
.tmStruckOut
= ptmW
->ntmTm
.tmStruckOut
;
329 ptm16
->ntmTm
.tmPitchAndFamily
= ptmW
->ntmTm
.tmPitchAndFamily
;
330 ptm16
->ntmTm
.tmCharSet
= ptmW
->ntmTm
.tmCharSet
;
331 ptm16
->ntmTm
.ntmFlags
= ptmW
->ntmTm
.ntmFlags
;
332 ptm16
->ntmTm
.ntmSizeEM
= ptmW
->ntmTm
.ntmSizeEM
;
333 ptm16
->ntmTm
.ntmCellHeight
= ptmW
->ntmTm
.ntmCellHeight
;
334 ptm16
->ntmTm
.ntmAvgWidth
= ptmW
->ntmTm
.ntmAvgWidth
;
335 memcpy(&ptm16
->ntmFontSig
, &ptmW
->ntmFontSig
, sizeof(FONTSIGNATURE
));
338 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW
*ptmW
, NEWTEXTMETRICEXA
*ptmA
)
340 FONT_TextMetricWToA((const TEXTMETRICW
*)ptmW
, (LPTEXTMETRICA
)ptmA
);
341 ptmA
->ntmTm
.ntmFlags
= ptmW
->ntmTm
.ntmFlags
;
342 ptmA
->ntmTm
.ntmSizeEM
= ptmW
->ntmTm
.ntmSizeEM
;
343 ptmA
->ntmTm
.ntmCellHeight
= ptmW
->ntmTm
.ntmCellHeight
;
344 ptmA
->ntmTm
.ntmAvgWidth
= ptmW
->ntmTm
.ntmAvgWidth
;
345 memcpy(&ptmA
->ntmFontSig
, &ptmW
->ntmFontSig
, sizeof(FONTSIGNATURE
));
349 /***********************************************************************
350 * GdiGetCodePage (GDI32.@)
352 DWORD WINAPI
GdiGetCodePage( HDC hdc
)
356 int charset
= GetTextCharset(hdc
);
358 /* Hmm, nicely designed api this one! */
359 if(TranslateCharsetInfo(ULongToPtr(charset
), &csi
, TCI_SRCCHARSET
))
366 case DEFAULT_CHARSET
:
377 /* FIXME: These have no place here, but because x11drv
378 enumerates fonts with these (made up) charsets some apps
379 might use them and then the FIXME below would become
380 annoying. Now we could pick the intended codepage for
381 each of these, but since it's broken anyway we'll just
382 use CP_ACP and hope it'll go away...
388 FIXME("Can't find codepage for charset %d\n", charset
);
393 TRACE("charset %d => cp %d\n", charset
, cp
);
397 /***********************************************************************
400 * Returns a Unicode translation of str using the charset of the
401 * currently selected font in hdc. If count is -1 then str is assumed
402 * to be '\0' terminated, otherwise it contains the number of bytes to
403 * convert. If plenW is non-NULL, on return it will point to the
404 * number of WCHARs that have been written. If pCP is non-NULL, on
405 * return it will point to the codepage used in the conversion. The
406 * caller should free the returned LPWSTR from the process heap
409 static LPWSTR
FONT_mbtowc(HDC hdc
, LPCSTR str
, INT count
, INT
*plenW
, UINT
*pCP
)
415 cp
= GdiGetCodePage( hdc
);
417 if(count
== -1) count
= strlen(str
);
418 lenW
= MultiByteToWideChar(cp
, 0, str
, count
, NULL
, 0);
419 strW
= HeapAlloc(GetProcessHeap(), 0, lenW
*sizeof(WCHAR
));
420 MultiByteToWideChar(cp
, 0, str
, count
, strW
, lenW
);
421 TRACE("mapped %s -> %s\n", debugstr_an(str
, count
), debugstr_wn(strW
, lenW
));
422 if(plenW
) *plenW
= lenW
;
428 /***********************************************************************
429 * CreateFontIndirectA (GDI32.@)
431 HFONT WINAPI
CreateFontIndirectA( const LOGFONTA
*plfA
)
436 FONT_LogFontAToW( plfA
, &lfW
);
437 return CreateFontIndirectW( &lfW
);
439 return CreateFontIndirectW( NULL
);
443 /***********************************************************************
444 * CreateFontIndirectW (GDI32.@)
446 HFONT WINAPI
CreateFontIndirectW( const LOGFONTW
*plf
)
453 if ((fontPtr
= GDI_AllocObject( sizeof(FONTOBJ
), FONT_MAGIC
,
454 (HGDIOBJ
*)&hFont
, &font_funcs
)))
456 static const WCHAR ItalicW
[] = {' ','I','t','a','l','i','c','\0'};
457 static const WCHAR BoldW
[] = {' ','B','o','l','d','\0'};
458 WCHAR
*pFaceNameItalicSuffix
, *pFaceNameBoldSuffix
;
459 WCHAR
* pFaceNameSuffix
= NULL
;
461 memcpy( &fontPtr
->logfont
, plf
, sizeof(LOGFONTW
) );
463 TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
464 plf
->lfHeight
, plf
->lfWidth
,
465 plf
->lfEscapement
, plf
->lfOrientation
,
466 plf
->lfPitchAndFamily
,
467 plf
->lfOutPrecision
, plf
->lfClipPrecision
,
468 plf
->lfQuality
, plf
->lfCharSet
,
469 debugstr_w(plf
->lfFaceName
),
470 plf
->lfWeight
> 400 ? "Bold" : "",
471 plf
->lfItalic
? "Italic" : "",
472 plf
->lfUnderline
? "Underline" : "", hFont
);
474 if (plf
->lfEscapement
!= plf
->lfOrientation
) {
475 /* this should really depend on whether GM_ADVANCED is set */
476 fontPtr
->logfont
.lfOrientation
= fontPtr
->logfont
.lfEscapement
;
477 WARN("orientation angle %f set to "
478 "escapement angle %f for new font %p\n",
479 plf
->lfOrientation
/10., plf
->lfEscapement
/10., hFont
);
482 pFaceNameItalicSuffix
= strstrW(fontPtr
->logfont
.lfFaceName
, ItalicW
);
483 if (pFaceNameItalicSuffix
) {
484 fontPtr
->logfont
.lfItalic
= TRUE
;
485 pFaceNameSuffix
= pFaceNameItalicSuffix
;
488 pFaceNameBoldSuffix
= strstrW(fontPtr
->logfont
.lfFaceName
, BoldW
);
489 if (pFaceNameBoldSuffix
) {
490 if (fontPtr
->logfont
.lfWeight
< FW_BOLD
) {
491 fontPtr
->logfont
.lfWeight
= FW_BOLD
;
493 if (!pFaceNameSuffix
||
494 (pFaceNameBoldSuffix
< pFaceNameSuffix
)) {
495 pFaceNameSuffix
= pFaceNameBoldSuffix
;
499 if (pFaceNameSuffix
) *pFaceNameSuffix
= 0;
501 GDI_ReleaseObj( hFont
);
504 else WARN("(NULL) => NULL\n");
509 /*************************************************************************
510 * CreateFontA (GDI32.@)
512 HFONT WINAPI
CreateFontA( INT height
, INT width
, INT esc
,
513 INT orient
, INT weight
, DWORD italic
,
514 DWORD underline
, DWORD strikeout
, DWORD charset
,
515 DWORD outpres
, DWORD clippres
, DWORD quality
,
516 DWORD pitch
, LPCSTR name
)
520 logfont
.lfHeight
= height
;
521 logfont
.lfWidth
= width
;
522 logfont
.lfEscapement
= esc
;
523 logfont
.lfOrientation
= orient
;
524 logfont
.lfWeight
= weight
;
525 logfont
.lfItalic
= italic
;
526 logfont
.lfUnderline
= underline
;
527 logfont
.lfStrikeOut
= strikeout
;
528 logfont
.lfCharSet
= charset
;
529 logfont
.lfOutPrecision
= outpres
;
530 logfont
.lfClipPrecision
= clippres
;
531 logfont
.lfQuality
= quality
;
532 logfont
.lfPitchAndFamily
= pitch
;
535 lstrcpynA(logfont
.lfFaceName
,name
,sizeof(logfont
.lfFaceName
));
537 logfont
.lfFaceName
[0] = '\0';
539 return CreateFontIndirectA( &logfont
);
542 /*************************************************************************
543 * CreateFontW (GDI32.@)
545 HFONT WINAPI
CreateFontW( INT height
, INT width
, INT esc
,
546 INT orient
, INT weight
, DWORD italic
,
547 DWORD underline
, DWORD strikeout
, DWORD charset
,
548 DWORD outpres
, DWORD clippres
, DWORD quality
,
549 DWORD pitch
, LPCWSTR name
)
553 logfont
.lfHeight
= height
;
554 logfont
.lfWidth
= width
;
555 logfont
.lfEscapement
= esc
;
556 logfont
.lfOrientation
= orient
;
557 logfont
.lfWeight
= weight
;
558 logfont
.lfItalic
= italic
;
559 logfont
.lfUnderline
= underline
;
560 logfont
.lfStrikeOut
= strikeout
;
561 logfont
.lfCharSet
= charset
;
562 logfont
.lfOutPrecision
= outpres
;
563 logfont
.lfClipPrecision
= clippres
;
564 logfont
.lfQuality
= quality
;
565 logfont
.lfPitchAndFamily
= pitch
;
568 lstrcpynW(logfont
.lfFaceName
, name
,
569 sizeof(logfont
.lfFaceName
) / sizeof(WCHAR
));
571 logfont
.lfFaceName
[0] = '\0';
573 return CreateFontIndirectW( &logfont
);
577 /***********************************************************************
580 * If the driver supports vector fonts we create a gdi font first and
581 * then call the driver to give it a chance to supply its own device
582 * font. If the driver wants to do this it returns TRUE and we can
583 * delete the gdi font, if the driver wants to use the gdi font it
584 * should return FALSE, to signal an error return GDI_ERROR. For
585 * drivers that don't support vector fonts they must supply their own
588 static HGDIOBJ
FONT_SelectObject( HGDIOBJ handle
, void *obj
, HDC hdc
)
591 DC
*dc
= DC_GetDCPtr( hdc
);
595 if (dc
->hFont
!= handle
|| dc
->gdiFont
== NULL
)
597 if(GetDeviceCaps(dc
->hSelf
, TEXTCAPS
) & TC_VA_ABLE
)
598 dc
->gdiFont
= WineEngCreateFontInstance(dc
, handle
);
601 if (dc
->funcs
->pSelectFont
) ret
= dc
->funcs
->pSelectFont( dc
->physDev
, handle
, dc
->gdiFont
);
603 if (ret
&& dc
->gdiFont
) dc
->gdiFont
= 0;
605 if (ret
== HGDI_ERROR
)
606 ret
= 0; /* SelectObject returns 0 on error */
612 GDI_ReleaseObj( hdc
);
617 /***********************************************************************
620 static INT
FONT_GetObject16( HGDIOBJ handle
, void *obj
, INT count
, LPVOID buffer
)
625 FONT_LogFontWTo16( &font
->logfont
, &lf16
);
627 if (count
> sizeof(LOGFONT16
)) count
= sizeof(LOGFONT16
);
628 memcpy( buffer
, &lf16
, count
);
632 /***********************************************************************
635 static INT
FONT_GetObjectA( HGDIOBJ handle
, void *obj
, INT count
, LPVOID buffer
)
642 FONT_LogFontWToA( &font
->logfont
, &lfA
);
644 if (count
> sizeof(lfA
)) count
= sizeof(lfA
);
645 memcpy( buffer
, &lfA
, count
);
649 /***********************************************************************
652 static INT
FONT_GetObjectW( HGDIOBJ handle
, void *obj
, INT count
, LPVOID buffer
)
656 return sizeof(LOGFONTW
);
657 if (count
> sizeof(LOGFONTW
)) count
= sizeof(LOGFONTW
);
658 memcpy( buffer
, &font
->logfont
, count
);
663 /***********************************************************************
666 static BOOL
FONT_DeleteObject( HGDIOBJ handle
, void *obj
)
668 WineEngDestroyFontInstance( handle
);
669 return GDI_FreeObject( handle
, obj
);
673 /***********************************************************************
674 * FONT_EnumInstance16
676 * Called by the device driver layer to pass font info
677 * down to the application.
679 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
680 * We have to use other types because of the FONTENUMPROCW definition.
682 static INT CALLBACK
FONT_EnumInstance16( const LOGFONTW
*plf
, const TEXTMETRICW
*ptm
,
683 DWORD fType
, LPARAM lp
)
685 fontEnum16
*pfe
= (fontEnum16
*)lp
;
689 if( pfe
->lpLogFontParam
->lfCharSet
== DEFAULT_CHARSET
||
690 pfe
->lpLogFontParam
->lfCharSet
== plf
->lfCharSet
)
695 FONT_EnumLogFontExWTo16((const ENUMLOGFONTEXW
*)plf
, pfe
->lpLogFont
);
696 FONT_NewTextMetricExWTo16((const NEWTEXTMETRICEXW
*)ptm
, pfe
->lpTextMetric
);
697 pfe
->dwFlags
|= ENUM_CALLED
;
698 GDI_ReleaseObj( pfe
->hdc
); /* release the GDI lock */
700 args
[6] = SELECTOROF(pfe
->segLogFont
);
701 args
[5] = OFFSETOF(pfe
->segLogFont
);
702 args
[4] = SELECTOROF(pfe
->segTextMetric
);
703 args
[3] = OFFSETOF(pfe
->segTextMetric
);
705 args
[1] = HIWORD(pfe
->lpData
);
706 args
[0] = LOWORD(pfe
->lpData
);
707 WOWCallback16Ex( (DWORD
)pfe
->lpEnumFunc
, WCB16_PASCAL
, sizeof(args
), args
, &result
);
708 ret
= LOWORD(result
);
710 /* get the lock again and make sure the DC is still valid */
711 dc
= DC_GetDCPtr( pfe
->hdc
);
712 if (!dc
|| dc
!= pfe
->dc
|| dc
->physDev
!= pfe
->physDev
)
714 if (dc
) GDI_ReleaseObj( pfe
->hdc
);
715 pfe
->hdc
= 0; /* make sure we don't try to release it later on */
722 /***********************************************************************
725 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
726 * We have to use other types because of the FONTENUMPROCW definition.
728 static INT CALLBACK
FONT_EnumInstance( const LOGFONTW
*plf
, const TEXTMETRICW
*ptm
,
729 DWORD fType
, LPARAM lp
)
731 fontEnum32
*pfe
= (fontEnum32
*)lp
;
735 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
736 if((pfe
->lpLogFontParam
->lfCharSet
== DEFAULT_CHARSET
||
737 pfe
->lpLogFontParam
->lfCharSet
== plf
->lfCharSet
) &&
738 (!(fType
& RASTER_FONTTYPE
) || GetDeviceCaps(pfe
->hdc
, TEXTCAPS
) & TC_RA_ABLE
) )
740 /* convert font metrics */
741 ENUMLOGFONTEXA logfont
;
742 NEWTEXTMETRICEXA tmA
;
744 pfe
->dwFlags
|= ENUM_CALLED
;
745 if (!(pfe
->dwFlags
& ENUM_UNICODE
))
747 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW
*)plf
, &logfont
);
748 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW
*)ptm
, &tmA
);
749 plf
= (LOGFONTW
*)&logfont
.elfLogFont
;
750 ptm
= (TEXTMETRICW
*)&tmA
;
752 GDI_ReleaseObj( pfe
->hdc
); /* release the GDI lock */
754 ret
= pfe
->lpEnumFunc( plf
, ptm
, fType
, pfe
->lpData
);
756 /* get the lock again and make sure the DC is still valid */
757 dc
= DC_GetDCPtr( pfe
->hdc
);
758 if (!dc
|| dc
!= pfe
->dc
|| dc
->physDev
!= pfe
->physDev
)
760 if (dc
) GDI_ReleaseObj( pfe
->hdc
);
761 pfe
->hdc
= 0; /* make sure we don't try to release it later on */
768 /***********************************************************************
769 * EnumFontFamiliesEx (GDI.613)
771 INT16 WINAPI
EnumFontFamiliesEx16( HDC16 hDC
, LPLOGFONT16 plf
,
772 FONTENUMPROC16 efproc
, LPARAM lParam
,
777 DC
* dc
= DC_GetDCPtr( HDC_32(hDC
) );
778 NEWTEXTMETRICEX16 tm16
;
779 ENUMLOGFONTEX16 lf16
;
784 FONT_LogFont16ToW(plf
, &lfW
);
786 fe16
.hdc
= HDC_32(hDC
);
788 fe16
.physDev
= dc
->physDev
;
789 fe16
.lpLogFontParam
= plf
;
790 fe16
.lpEnumFunc
= efproc
;
791 fe16
.lpData
= lParam
;
792 fe16
.lpTextMetric
= &tm16
;
793 fe16
.lpLogFont
= &lf16
;
794 fe16
.segTextMetric
= MapLS( &tm16
);
795 fe16
.segLogFont
= MapLS( &lf16
);
798 enum_gdi_fonts
= GetDeviceCaps(fe16
.hdc
, TEXTCAPS
) & TC_VA_ABLE
;
800 if (!dc
->funcs
->pEnumDeviceFonts
&& !enum_gdi_fonts
)
807 ret
= WineEngEnumFonts( &lfW
, FONT_EnumInstance16
, (LPARAM
)&fe16
);
808 fe16
.dwFlags
&= ~ENUM_CALLED
;
809 if (ret
&& dc
->funcs
->pEnumDeviceFonts
) {
810 ret2
= dc
->funcs
->pEnumDeviceFonts( dc
->physDev
, &lfW
, FONT_EnumInstance16
, (LPARAM
)&fe16
);
811 if(fe16
.dwFlags
& ENUM_CALLED
) /* update ret iff a font gets enumed */
815 UnMapLS( fe16
.segTextMetric
);
816 UnMapLS( fe16
.segLogFont
);
817 if (fe16
.hdc
) GDI_ReleaseObj( fe16
.hdc
);
821 /***********************************************************************
822 * FONT_EnumFontFamiliesEx
824 static INT
FONT_EnumFontFamiliesEx( HDC hDC
, LPLOGFONTW plf
,
825 FONTENUMPROCW efproc
,
826 LPARAM lParam
, DWORD dwUnicode
)
829 DC
*dc
= DC_GetDCPtr( hDC
);
835 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf
->lfFaceName
),
837 fe32
.lpLogFontParam
= plf
;
838 fe32
.lpEnumFunc
= efproc
;
839 fe32
.lpData
= lParam
;
840 fe32
.dwFlags
= dwUnicode
;
843 fe32
.physDev
= dc
->physDev
;
845 enum_gdi_fonts
= GetDeviceCaps(hDC
, TEXTCAPS
) & TC_VA_ABLE
;
847 if (!dc
->funcs
->pEnumDeviceFonts
&& !enum_gdi_fonts
)
854 ret
= WineEngEnumFonts( plf
, FONT_EnumInstance
, (LPARAM
)&fe32
);
855 fe32
.dwFlags
&= ~ENUM_CALLED
;
856 if (ret
&& dc
->funcs
->pEnumDeviceFonts
) {
857 ret2
= dc
->funcs
->pEnumDeviceFonts( dc
->physDev
, plf
, FONT_EnumInstance
, (LPARAM
)&fe32
);
858 if(fe32
.dwFlags
& ENUM_CALLED
) /* update ret iff a font gets enumed */
862 if (fe32
.hdc
) GDI_ReleaseObj( fe32
.hdc
);
866 /***********************************************************************
867 * EnumFontFamiliesExW (GDI32.@)
869 INT WINAPI
EnumFontFamiliesExW( HDC hDC
, LPLOGFONTW plf
,
870 FONTENUMPROCW efproc
,
871 LPARAM lParam
, DWORD dwFlags
)
873 return FONT_EnumFontFamiliesEx( hDC
, plf
, efproc
, lParam
, ENUM_UNICODE
);
876 /***********************************************************************
877 * EnumFontFamiliesExA (GDI32.@)
879 INT WINAPI
EnumFontFamiliesExA( HDC hDC
, LPLOGFONTA plf
,
880 FONTENUMPROCA efproc
,
881 LPARAM lParam
, DWORD dwFlags
)
884 FONT_LogFontAToW( plf
, &lfW
);
886 return FONT_EnumFontFamiliesEx( hDC
, &lfW
, (FONTENUMPROCW
)efproc
, lParam
, 0);
889 /***********************************************************************
890 * EnumFontFamilies (GDI.330)
892 INT16 WINAPI
EnumFontFamilies16( HDC16 hDC
, LPCSTR lpFamily
,
893 FONTENUMPROC16 efproc
, LPARAM lpData
)
897 lf
.lfCharSet
= DEFAULT_CHARSET
;
900 if (!*lpFamily
) return 1;
901 lstrcpynA( lf
.lfFaceName
, lpFamily
, LF_FACESIZE
);
903 else lf
.lfFaceName
[0] = '\0';
905 return EnumFontFamiliesEx16( hDC
, &lf
, efproc
, lpData
, 0 );
908 /***********************************************************************
909 * EnumFontFamiliesA (GDI32.@)
911 INT WINAPI
EnumFontFamiliesA( HDC hDC
, LPCSTR lpFamily
,
912 FONTENUMPROCA efproc
, LPARAM lpData
)
916 lf
.lfCharSet
= DEFAULT_CHARSET
;
919 if (!*lpFamily
) return 1;
920 lstrcpynA( lf
.lfFaceName
, lpFamily
, LF_FACESIZE
);
922 else lf
.lfFaceName
[0] = lf
.lfFaceName
[1] = '\0';
924 return EnumFontFamiliesExA( hDC
, &lf
, efproc
, lpData
, 0 );
927 /***********************************************************************
928 * EnumFontFamiliesW (GDI32.@)
930 INT WINAPI
EnumFontFamiliesW( HDC hDC
, LPCWSTR lpFamily
,
931 FONTENUMPROCW efproc
, LPARAM lpData
)
935 lf
.lfCharSet
= DEFAULT_CHARSET
;
938 if (!*lpFamily
) return 1;
939 lstrcpynW( lf
.lfFaceName
, lpFamily
, LF_FACESIZE
);
941 else lf
.lfFaceName
[0] = 0;
943 return EnumFontFamiliesExW( hDC
, &lf
, efproc
, lpData
, 0 );
946 /***********************************************************************
949 INT16 WINAPI
EnumFonts16( HDC16 hDC
, LPCSTR lpName
, FONTENUMPROC16 efproc
,
952 return EnumFontFamilies16( hDC
, lpName
, efproc
, lpData
);
955 /***********************************************************************
956 * EnumFontsA (GDI32.@)
958 INT WINAPI
EnumFontsA( HDC hDC
, LPCSTR lpName
, FONTENUMPROCA efproc
,
961 return EnumFontFamiliesA( hDC
, lpName
, efproc
, lpData
);
964 /***********************************************************************
965 * EnumFontsW (GDI32.@)
967 INT WINAPI
EnumFontsW( HDC hDC
, LPCWSTR lpName
, FONTENUMPROCW efproc
,
970 return EnumFontFamiliesW( hDC
, lpName
, efproc
, lpData
);
974 /***********************************************************************
975 * GetTextCharacterExtra (GDI32.@)
977 INT WINAPI
GetTextCharacterExtra( HDC hdc
)
980 DC
*dc
= DC_GetDCPtr( hdc
);
981 if (!dc
) return 0x80000000;
983 GDI_ReleaseObj( hdc
);
988 /***********************************************************************
989 * SetTextCharacterExtra (GDI32.@)
991 INT WINAPI
SetTextCharacterExtra( HDC hdc
, INT extra
)
994 DC
* dc
= DC_GetDCPtr( hdc
);
995 if (!dc
) return 0x80000000;
996 if (dc
->funcs
->pSetTextCharacterExtra
)
997 prev
= dc
->funcs
->pSetTextCharacterExtra( dc
->physDev
, extra
);
1000 prev
= dc
->charExtra
;
1001 dc
->charExtra
= extra
;
1003 GDI_ReleaseObj( hdc
);
1008 /***********************************************************************
1009 * SetTextJustification (GDI32.@)
1011 BOOL WINAPI
SetTextJustification( HDC hdc
, INT extra
, INT breaks
)
1014 DC
* dc
= DC_GetDCPtr( hdc
);
1015 if (!dc
) return FALSE
;
1016 if (dc
->funcs
->pSetTextJustification
)
1017 ret
= dc
->funcs
->pSetTextJustification( dc
->physDev
, extra
, breaks
);
1020 extra
= abs((extra
* dc
->vportExtX
+ dc
->wndExtX
/ 2) / dc
->wndExtX
);
1021 if (!extra
) breaks
= 0;
1024 dc
->breakExtra
= extra
/ breaks
;
1025 dc
->breakRem
= extra
- (breaks
* dc
->breakExtra
);
1033 GDI_ReleaseObj( hdc
);
1038 /***********************************************************************
1039 * GetTextFaceA (GDI32.@)
1041 INT WINAPI
GetTextFaceA( HDC hdc
, INT count
, LPSTR name
)
1043 INT res
= GetTextFaceW(hdc
, 0, NULL
);
1044 LPWSTR nameW
= HeapAlloc( GetProcessHeap(), 0, res
* 2 );
1045 GetTextFaceW( hdc
, res
, nameW
);
1049 if (count
&& !WideCharToMultiByte( CP_ACP
, 0, nameW
, -1, name
, count
, NULL
, NULL
))
1054 res
= WideCharToMultiByte( CP_ACP
, 0, nameW
, -1, NULL
, 0, NULL
, NULL
);
1055 HeapFree( GetProcessHeap(), 0, nameW
);
1059 /***********************************************************************
1060 * GetTextFaceW (GDI32.@)
1062 INT WINAPI
GetTextFaceW( HDC hdc
, INT count
, LPWSTR name
)
1067 DC
* dc
= DC_GetDCPtr( hdc
);
1071 ret
= WineEngGetTextFace(dc
->gdiFont
, count
, name
);
1072 else if ((font
= (FONTOBJ
*) GDI_GetObjPtr( dc
->hFont
, FONT_MAGIC
)))
1076 lstrcpynW( name
, font
->logfont
.lfFaceName
, count
);
1077 ret
= strlenW(name
);
1079 else ret
= strlenW(font
->logfont
.lfFaceName
) + 1;
1080 GDI_ReleaseObj( dc
->hFont
);
1082 GDI_ReleaseObj( hdc
);
1087 /***********************************************************************
1088 * GetTextExtentPoint32A (GDI32.@)
1090 * See GetTextExtentPoint32W.
1092 BOOL WINAPI
GetTextExtentPoint32A( HDC hdc
, LPCSTR str
, INT count
,
1097 LPWSTR p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
1100 ret
= GetTextExtentPoint32W( hdc
, p
, wlen
, size
);
1101 HeapFree( GetProcessHeap(), 0, p
);
1104 TRACE("(%p %s %d %p): returning %d x %d\n",
1105 hdc
, debugstr_an (str
, count
), count
, size
, size
->cx
, size
->cy
);
1110 /***********************************************************************
1111 * GetTextExtentPoint32W [GDI32.@]
1113 * Computes width/height for a string.
1115 * Computes width and height of the specified string.
1121 BOOL WINAPI
GetTextExtentPoint32W(
1122 HDC hdc
, /* [in] Handle of device context */
1123 LPCWSTR str
, /* [in] Address of text string */
1124 INT count
, /* [in] Number of characters in string */
1125 LPSIZE size
) /* [out] Address of structure for string size */
1127 return GetTextExtentExPointW(hdc
, str
, count
, 0, NULL
, NULL
, size
);
1130 /***********************************************************************
1131 * GetTextExtentPointI [GDI32.@]
1133 * Computes width and height of the array of glyph indices.
1139 BOOL WINAPI
GetTextExtentPointI(
1140 HDC hdc
, /* [in] Handle of device context */
1141 const WORD
*indices
, /* [in] Address of glyph index array */
1142 INT count
, /* [in] Number of glyphs in array */
1143 LPSIZE size
) /* [out] Address of structure for string size */
1146 DC
* dc
= DC_GetDCPtr( hdc
);
1147 if (!dc
) return FALSE
;
1150 ret
= WineEngGetTextExtentPointI(dc
->gdiFont
, indices
, count
, size
);
1151 size
->cx
= abs(INTERNAL_XDSTOWS(dc
, size
->cx
));
1152 size
->cy
= abs(INTERNAL_YDSTOWS(dc
, size
->cy
));
1153 size
->cx
+= count
* dc
->charExtra
;
1155 else if(dc
->funcs
->pGetTextExtentExPoint
) {
1156 FIXME("calling GetTextExtentExPoint\n");
1157 ret
= dc
->funcs
->pGetTextExtentExPoint( dc
->physDev
, (LPCWSTR
)indices
,
1158 count
, 0, NULL
, NULL
, size
);
1161 GDI_ReleaseObj( hdc
);
1163 TRACE("(%p %p %d %p): returning %d x %d\n",
1164 hdc
, indices
, count
, size
, size
->cx
, size
->cy
);
1169 /***********************************************************************
1170 * GetTextExtentPointA (GDI32.@)
1172 BOOL WINAPI
GetTextExtentPointA( HDC hdc
, LPCSTR str
, INT count
,
1175 TRACE("not bug compatible.\n");
1176 return GetTextExtentPoint32A( hdc
, str
, count
, size
);
1179 /***********************************************************************
1180 * GetTextExtentPointW (GDI32.@)
1182 BOOL WINAPI
GetTextExtentPointW( HDC hdc
, LPCWSTR str
, INT count
,
1185 TRACE("not bug compatible.\n");
1186 return GetTextExtentPoint32W( hdc
, str
, count
, size
);
1190 /***********************************************************************
1191 * GetTextExtentExPointA (GDI32.@)
1193 BOOL WINAPI
GetTextExtentExPointA( HDC hdc
, LPCSTR str
, INT count
,
1194 INT maxExt
, LPINT lpnFit
,
1195 LPINT alpDx
, LPSIZE size
)
1203 NULL
== (walpDx
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(INT
))))
1206 p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
1207 ret
= GetTextExtentExPointW( hdc
, p
, wlen
, maxExt
, lpnFit
, walpDx
, size
);
1210 INT n
= lpnFit
? *lpnFit
: wlen
;
1212 for(i
= 0, j
= 0; i
< n
; i
++, j
++)
1214 alpDx
[j
] = walpDx
[i
];
1215 if (IsDBCSLeadByte(str
[j
])) alpDx
[++j
] = walpDx
[i
];
1218 if (lpnFit
) *lpnFit
= WideCharToMultiByte(CP_ACP
,0,p
,*lpnFit
,NULL
,0,NULL
,NULL
);
1219 HeapFree( GetProcessHeap(), 0, p
);
1220 HeapFree( GetProcessHeap(), 0, walpDx
);
1225 /***********************************************************************
1226 * GetTextExtentExPointW (GDI32.@)
1228 * Return the size of the string as it would be if it was output properly by
1231 * This should include
1232 * - Intercharacter spacing
1233 * - justification spacing (not yet done)
1234 * - kerning? see below
1236 * Kerning. Since kerning would be carried out by the rendering code it should
1237 * be done by the driver. However they don't support it yet. Also I am not
1238 * yet persuaded that (certainly under Win95) any kerning is actually done.
1240 * str: According to MSDN this should be null-terminated. That is not true; a
1241 * null will not terminate it early.
1242 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1243 * than count. I have seen it be either the size of the full string or
1244 * 1 less than the size of the full string. I have not seen it bear any
1245 * resemblance to the portion that would fit.
1246 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1247 * trailing intercharacter spacing and any trailing justification.
1250 * Currently we do this by measuring each character etc. We should do it by
1251 * passing the request to the driver, perhaps by extending the
1252 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1253 * thinking about kerning issues and rounding issues in the justification.
1256 BOOL WINAPI
GetTextExtentExPointW( HDC hdc
, LPCWSTR str
, INT count
,
1257 INT maxExt
, LPINT lpnFit
,
1258 LPINT alpDx
, LPSIZE size
)
1266 TRACE("(%p, %s, %d)\n",hdc
,debugstr_wn(str
,count
),maxExt
);
1268 dc
= DC_GetDCPtr(hdc
);
1272 GetTextMetricsW(hdc
, &tm
);
1274 /* If we need to calculate nFit, then we need the partial extents even if
1275 the user hasn't provided us with an array. */
1278 dxs
= alpDx
? alpDx
: HeapAlloc(GetProcessHeap(), 0, count
* sizeof alpDx
[0]);
1281 GDI_ReleaseObj(hdc
);
1282 SetLastError(ERROR_OUTOFMEMORY
);
1290 ret
= WineEngGetTextExtentExPoint(dc
->gdiFont
, str
, count
,
1291 0, NULL
, dxs
, size
);
1292 else if (dc
->funcs
->pGetTextExtentExPoint
)
1293 ret
= dc
->funcs
->pGetTextExtentExPoint(dc
->physDev
, str
, count
,
1294 0, NULL
, dxs
, size
);
1296 /* Perform device size to world size transformations. */
1299 INT extra
= dc
->charExtra
,
1300 breakExtra
= dc
->breakExtra
,
1301 breakRem
= dc
->breakRem
,
1306 for (i
= 0; i
< count
; ++i
)
1308 dxs
[i
] = abs(INTERNAL_XDSTOWS(dc
, dxs
[i
]));
1309 dxs
[i
] += (i
+1) * extra
;
1310 if (count
> 1 && (breakExtra
|| breakRem
) && str
[i
] == tm
.tmBreakChar
)
1312 dxs
[i
] += breakExtra
;
1319 if (dxs
[i
] <= maxExt
)
1322 breakRem
= dc
->breakRem
;
1324 size
->cx
= abs(INTERNAL_XDSTOWS(dc
, size
->cx
));
1325 size
->cy
= abs(INTERNAL_YDSTOWS(dc
, size
->cy
));
1327 if (!dxs
&& count
> 1 && (breakExtra
|| breakRem
))
1329 for (i
= 0; i
< count
; i
++)
1331 if (str
[i
] == tm
.tmBreakChar
)
1333 size
->cx
+= breakExtra
;
1348 HeapFree(GetProcessHeap(), 0, dxs
);
1350 GDI_ReleaseObj( hdc
);
1352 TRACE("returning %d %d x %d\n",nFit
,size
->cx
,size
->cy
);
1356 /***********************************************************************
1357 * GetTextMetricsA (GDI32.@)
1359 BOOL WINAPI
GetTextMetricsA( HDC hdc
, TEXTMETRICA
*metrics
)
1363 if (!GetTextMetricsW( hdc
, &tm32
)) return FALSE
;
1364 FONT_TextMetricWToA( &tm32
, metrics
);
1368 /***********************************************************************
1369 * GetTextMetricsW (GDI32.@)
1371 BOOL WINAPI
GetTextMetricsW( HDC hdc
, TEXTMETRICW
*metrics
)
1374 DC
* dc
= DC_GetDCPtr( hdc
);
1375 if (!dc
) return FALSE
;
1378 ret
= WineEngGetTextMetrics(dc
->gdiFont
, metrics
);
1379 else if (dc
->funcs
->pGetTextMetrics
)
1380 ret
= dc
->funcs
->pGetTextMetrics( dc
->physDev
, metrics
);
1384 /* device layer returns values in device units
1385 * therefore we have to convert them to logical */
1387 metrics
->tmDigitizedAspectX
= GetDeviceCaps(hdc
, LOGPIXELSX
);
1388 metrics
->tmDigitizedAspectY
= GetDeviceCaps(hdc
, LOGPIXELSY
);
1390 #define WDPTOLP(x) ((x<0)? \
1391 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1392 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1393 #define HDPTOLP(y) ((y<0)? \
1394 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1395 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1397 metrics
->tmHeight
= HDPTOLP(metrics
->tmHeight
);
1398 metrics
->tmAscent
= HDPTOLP(metrics
->tmAscent
);
1399 metrics
->tmDescent
= HDPTOLP(metrics
->tmDescent
);
1400 metrics
->tmInternalLeading
= HDPTOLP(metrics
->tmInternalLeading
);
1401 metrics
->tmExternalLeading
= HDPTOLP(metrics
->tmExternalLeading
);
1402 metrics
->tmAveCharWidth
= WDPTOLP(metrics
->tmAveCharWidth
);
1403 metrics
->tmMaxCharWidth
= WDPTOLP(metrics
->tmMaxCharWidth
);
1404 metrics
->tmOverhang
= WDPTOLP(metrics
->tmOverhang
);
1408 TRACE("text metrics:\n"
1409 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1410 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1411 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1412 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1413 " PitchAndFamily = %02x\n"
1414 " --------------------\n"
1415 " InternalLeading = %i\n"
1419 metrics
->tmWeight
, metrics
->tmFirstChar
, metrics
->tmAveCharWidth
,
1420 metrics
->tmItalic
, metrics
->tmLastChar
, metrics
->tmMaxCharWidth
,
1421 metrics
->tmUnderlined
, metrics
->tmDefaultChar
, metrics
->tmOverhang
,
1422 metrics
->tmStruckOut
, metrics
->tmBreakChar
, metrics
->tmCharSet
,
1423 metrics
->tmPitchAndFamily
,
1424 metrics
->tmInternalLeading
,
1427 metrics
->tmHeight
);
1429 GDI_ReleaseObj( hdc
);
1434 /***********************************************************************
1435 * GetOutlineTextMetrics [GDI.308] Gets metrics for TrueType fonts.
1438 * lpOTM should be LPOUTLINETEXTMETRIC
1441 * Success: Non-zero or size of required buffer
1444 UINT16 WINAPI
GetOutlineTextMetrics16(
1445 HDC16 hdc
, /* [in] Handle of device context */
1446 UINT16 cbData
, /* [in] Size of metric data array */
1447 LPOUTLINETEXTMETRIC16 lpOTM
) /* [out] Address of metric data array */
1449 FIXME("(%04x,%04x,%p): stub\n", hdc
,cbData
,lpOTM
);
1454 /***********************************************************************
1455 * GetOutlineTextMetricsA (GDI32.@)
1456 * Gets metrics for TrueType fonts.
1459 * If the supplied buffer isn't big enough Windows partially fills it up to
1460 * its given length and returns that length.
1463 * Success: Non-zero or size of required buffer
1466 UINT WINAPI
GetOutlineTextMetricsA(
1467 HDC hdc
, /* [in] Handle of device context */
1468 UINT cbData
, /* [in] Size of metric data array */
1469 LPOUTLINETEXTMETRICA lpOTM
) /* [out] Address of metric data array */
1471 char buf
[512], *ptr
;
1473 OUTLINETEXTMETRICW
*lpOTMW
= (OUTLINETEXTMETRICW
*)buf
;
1474 OUTLINETEXTMETRICA
*output
= lpOTM
;
1477 if((ret
= GetOutlineTextMetricsW(hdc
, 0, NULL
)) == 0)
1479 if(ret
> sizeof(buf
))
1480 lpOTMW
= HeapAlloc(GetProcessHeap(), 0, ret
);
1481 GetOutlineTextMetricsW(hdc
, ret
, lpOTMW
);
1483 needed
= sizeof(OUTLINETEXTMETRICA
);
1484 if(lpOTMW
->otmpFamilyName
)
1485 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1486 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFamilyName
), -1,
1487 NULL
, 0, NULL
, NULL
);
1488 if(lpOTMW
->otmpFaceName
)
1489 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1490 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFaceName
), -1,
1491 NULL
, 0, NULL
, NULL
);
1492 if(lpOTMW
->otmpStyleName
)
1493 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1494 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpStyleName
), -1,
1495 NULL
, 0, NULL
, NULL
);
1496 if(lpOTMW
->otmpFullName
)
1497 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1498 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFullName
), -1,
1499 NULL
, 0, NULL
, NULL
);
1506 TRACE("needed = %d\n", needed
);
1508 /* Since the supplied buffer isn't big enough, we'll alloc one
1509 that is and memcpy the first cbData bytes into the lpOTM at
1511 output
= HeapAlloc(GetProcessHeap(), 0, needed
);
1513 ret
= output
->otmSize
= min(needed
, cbData
);
1514 FONT_TextMetricWToA( &lpOTMW
->otmTextMetrics
, &output
->otmTextMetrics
);
1515 output
->otmFiller
= 0;
1516 output
->otmPanoseNumber
= lpOTMW
->otmPanoseNumber
;
1517 output
->otmfsSelection
= lpOTMW
->otmfsSelection
;
1518 output
->otmfsType
= lpOTMW
->otmfsType
;
1519 output
->otmsCharSlopeRise
= lpOTMW
->otmsCharSlopeRise
;
1520 output
->otmsCharSlopeRun
= lpOTMW
->otmsCharSlopeRun
;
1521 output
->otmItalicAngle
= lpOTMW
->otmItalicAngle
;
1522 output
->otmEMSquare
= lpOTMW
->otmEMSquare
;
1523 output
->otmAscent
= lpOTMW
->otmAscent
;
1524 output
->otmDescent
= lpOTMW
->otmDescent
;
1525 output
->otmLineGap
= lpOTMW
->otmLineGap
;
1526 output
->otmsCapEmHeight
= lpOTMW
->otmsCapEmHeight
;
1527 output
->otmsXHeight
= lpOTMW
->otmsXHeight
;
1528 output
->otmrcFontBox
= lpOTMW
->otmrcFontBox
;
1529 output
->otmMacAscent
= lpOTMW
->otmMacAscent
;
1530 output
->otmMacDescent
= lpOTMW
->otmMacDescent
;
1531 output
->otmMacLineGap
= lpOTMW
->otmMacLineGap
;
1532 output
->otmusMinimumPPEM
= lpOTMW
->otmusMinimumPPEM
;
1533 output
->otmptSubscriptSize
= lpOTMW
->otmptSubscriptSize
;
1534 output
->otmptSubscriptOffset
= lpOTMW
->otmptSubscriptOffset
;
1535 output
->otmptSuperscriptSize
= lpOTMW
->otmptSuperscriptSize
;
1536 output
->otmptSuperscriptOffset
= lpOTMW
->otmptSuperscriptOffset
;
1537 output
->otmsStrikeoutSize
= lpOTMW
->otmsStrikeoutSize
;
1538 output
->otmsStrikeoutPosition
= lpOTMW
->otmsStrikeoutPosition
;
1539 output
->otmsUnderscoreSize
= lpOTMW
->otmsUnderscoreSize
;
1540 output
->otmsUnderscorePosition
= lpOTMW
->otmsUnderscorePosition
;
1543 ptr
= (char*)(output
+ 1);
1544 left
= needed
- sizeof(*output
);
1546 if(lpOTMW
->otmpFamilyName
) {
1547 output
->otmpFamilyName
= (LPSTR
)(ptr
- (char*)output
);
1548 len
= WideCharToMultiByte(CP_ACP
, 0,
1549 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFamilyName
), -1,
1550 ptr
, left
, NULL
, NULL
);
1554 output
->otmpFamilyName
= 0;
1556 if(lpOTMW
->otmpFaceName
) {
1557 output
->otmpFaceName
= (LPSTR
)(ptr
- (char*)output
);
1558 len
= WideCharToMultiByte(CP_ACP
, 0,
1559 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFaceName
), -1,
1560 ptr
, left
, NULL
, NULL
);
1564 output
->otmpFaceName
= 0;
1566 if(lpOTMW
->otmpStyleName
) {
1567 output
->otmpStyleName
= (LPSTR
)(ptr
- (char*)output
);
1568 len
= WideCharToMultiByte(CP_ACP
, 0,
1569 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpStyleName
), -1,
1570 ptr
, left
, NULL
, NULL
);
1574 output
->otmpStyleName
= 0;
1576 if(lpOTMW
->otmpFullName
) {
1577 output
->otmpFullName
= (LPSTR
)(ptr
- (char*)output
);
1578 len
= WideCharToMultiByte(CP_ACP
, 0,
1579 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFullName
), -1,
1580 ptr
, left
, NULL
, NULL
);
1583 output
->otmpFullName
= 0;
1587 if(output
!= lpOTM
) {
1588 memcpy(lpOTM
, output
, cbData
);
1589 HeapFree(GetProcessHeap(), 0, output
);
1591 /* check if the string offsets really fit into the provided size */
1592 /* FIXME: should we check string length as well? */
1593 /* make sure that we don't read/write beyond the provided buffer */
1594 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFamilyName
) + sizeof(LPSTR
))
1596 if ((UINT_PTR
)lpOTM
->otmpFamilyName
>= lpOTM
->otmSize
)
1597 lpOTM
->otmpFamilyName
= 0; /* doesn't fit */
1600 /* make sure that we don't read/write beyond the provided buffer */
1601 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFaceName
) + sizeof(LPSTR
))
1603 if ((UINT_PTR
)lpOTM
->otmpFaceName
>= lpOTM
->otmSize
)
1604 lpOTM
->otmpFaceName
= 0; /* doesn't fit */
1607 /* make sure that we don't read/write beyond the provided buffer */
1608 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpStyleName
) + sizeof(LPSTR
))
1610 if ((UINT_PTR
)lpOTM
->otmpStyleName
>= lpOTM
->otmSize
)
1611 lpOTM
->otmpStyleName
= 0; /* doesn't fit */
1614 /* make sure that we don't read/write beyond the provided buffer */
1615 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFullName
) + sizeof(LPSTR
))
1617 if ((UINT_PTR
)lpOTM
->otmpFullName
>= lpOTM
->otmSize
)
1618 lpOTM
->otmpFullName
= 0; /* doesn't fit */
1623 if(lpOTMW
!= (OUTLINETEXTMETRICW
*)buf
)
1624 HeapFree(GetProcessHeap(), 0, lpOTMW
);
1630 /***********************************************************************
1631 * GetOutlineTextMetricsW [GDI32.@]
1633 UINT WINAPI
GetOutlineTextMetricsW(
1634 HDC hdc
, /* [in] Handle of device context */
1635 UINT cbData
, /* [in] Size of metric data array */
1636 LPOUTLINETEXTMETRICW lpOTM
) /* [out] Address of metric data array */
1638 DC
*dc
= DC_GetDCPtr( hdc
);
1639 OUTLINETEXTMETRICW
*output
= lpOTM
;
1642 TRACE("(%p,%d,%p)\n", hdc
, cbData
, lpOTM
);
1646 ret
= WineEngGetOutlineTextMetrics(dc
->gdiFont
, cbData
, output
);
1649 output
= HeapAlloc(GetProcessHeap(), 0, ret
);
1650 WineEngGetOutlineTextMetrics(dc
->gdiFont
, ret
, output
);
1653 #define WDPTOLP(x) ((x<0)? \
1654 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1655 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1656 #define HDPTOLP(y) ((y<0)? \
1657 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1658 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1660 output
->otmTextMetrics
.tmHeight
= HDPTOLP(output
->otmTextMetrics
.tmHeight
);
1661 output
->otmTextMetrics
.tmAscent
= HDPTOLP(output
->otmTextMetrics
.tmAscent
);
1662 output
->otmTextMetrics
.tmDescent
= HDPTOLP(output
->otmTextMetrics
.tmDescent
);
1663 output
->otmTextMetrics
.tmInternalLeading
= HDPTOLP(output
->otmTextMetrics
.tmInternalLeading
);
1664 output
->otmTextMetrics
.tmExternalLeading
= HDPTOLP(output
->otmTextMetrics
.tmExternalLeading
);
1665 output
->otmTextMetrics
.tmAveCharWidth
= WDPTOLP(output
->otmTextMetrics
.tmAveCharWidth
);
1666 output
->otmTextMetrics
.tmMaxCharWidth
= WDPTOLP(output
->otmTextMetrics
.tmMaxCharWidth
);
1667 output
->otmTextMetrics
.tmOverhang
= WDPTOLP(output
->otmTextMetrics
.tmOverhang
);
1668 output
->otmAscent
= HDPTOLP(output
->otmAscent
);
1669 output
->otmDescent
= HDPTOLP(output
->otmDescent
);
1670 output
->otmLineGap
= HDPTOLP(output
->otmLineGap
);
1671 output
->otmsCapEmHeight
= HDPTOLP(output
->otmsCapEmHeight
);
1672 output
->otmsXHeight
= HDPTOLP(output
->otmsXHeight
);
1673 output
->otmrcFontBox
.top
= HDPTOLP(output
->otmrcFontBox
.top
);
1674 output
->otmrcFontBox
.bottom
= HDPTOLP(output
->otmrcFontBox
.bottom
);
1675 output
->otmrcFontBox
.left
= WDPTOLP(output
->otmrcFontBox
.left
);
1676 output
->otmrcFontBox
.right
= WDPTOLP(output
->otmrcFontBox
.right
);
1677 output
->otmMacAscent
= HDPTOLP(output
->otmMacAscent
);
1678 output
->otmMacDescent
= HDPTOLP(output
->otmMacDescent
);
1679 output
->otmMacLineGap
= HDPTOLP(output
->otmMacLineGap
);
1680 output
->otmptSubscriptSize
.x
= WDPTOLP(output
->otmptSubscriptSize
.x
);
1681 output
->otmptSubscriptSize
.y
= HDPTOLP(output
->otmptSubscriptSize
.y
);
1682 output
->otmptSubscriptOffset
.x
= WDPTOLP(output
->otmptSubscriptOffset
.x
);
1683 output
->otmptSubscriptOffset
.y
= HDPTOLP(output
->otmptSubscriptOffset
.y
);
1684 output
->otmptSuperscriptSize
.x
= WDPTOLP(output
->otmptSuperscriptSize
.x
);
1685 output
->otmptSuperscriptSize
.y
= HDPTOLP(output
->otmptSuperscriptSize
.y
);
1686 output
->otmptSuperscriptOffset
.x
= WDPTOLP(output
->otmptSuperscriptOffset
.x
);
1687 output
->otmptSuperscriptOffset
.y
= HDPTOLP(output
->otmptSuperscriptOffset
.y
);
1688 output
->otmsStrikeoutSize
= HDPTOLP(output
->otmsStrikeoutSize
);
1689 output
->otmsStrikeoutPosition
= HDPTOLP(output
->otmsStrikeoutPosition
);
1690 output
->otmsUnderscoreSize
= HDPTOLP(output
->otmsUnderscoreSize
);
1691 output
->otmsUnderscorePosition
= HDPTOLP(output
->otmsUnderscorePosition
);
1694 if(output
!= lpOTM
) {
1695 memcpy(lpOTM
, output
, cbData
);
1696 HeapFree(GetProcessHeap(), 0, output
);
1702 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1703 but really this should just be a return 0. */
1705 ret
= sizeof(*lpOTM
);
1710 memset(lpOTM
, 0, ret
);
1711 lpOTM
->otmSize
= sizeof(*lpOTM
);
1712 GetTextMetricsW(hdc
, &lpOTM
->otmTextMetrics
);
1714 Further fill of the structure not implemented,
1715 Needs real values for the structure members
1720 GDI_ReleaseObj(hdc
);
1725 /***********************************************************************
1726 * GetCharWidthW (GDI32.@)
1727 * GetCharWidth32W (GDI32.@)
1729 BOOL WINAPI
GetCharWidth32W( HDC hdc
, UINT firstChar
, UINT lastChar
,
1734 DC
* dc
= DC_GetDCPtr( hdc
);
1735 if (!dc
) return FALSE
;
1738 ret
= WineEngGetCharWidth( dc
->gdiFont
, firstChar
, lastChar
, buffer
);
1739 else if (dc
->funcs
->pGetCharWidth
)
1740 ret
= dc
->funcs
->pGetCharWidth( dc
->physDev
, firstChar
, lastChar
, buffer
);
1744 /* convert device units to logical */
1745 for( i
= firstChar
; i
<= lastChar
; i
++, buffer
++ )
1746 *buffer
= INTERNAL_XDSTOWS(dc
, *buffer
);
1749 GDI_ReleaseObj( hdc
);
1754 /***********************************************************************
1755 * GetCharWidthA (GDI32.@)
1756 * GetCharWidth32A (GDI32.@)
1758 BOOL WINAPI
GetCharWidth32A( HDC hdc
, UINT firstChar
, UINT lastChar
,
1761 INT i
, wlen
, count
= (INT
)(lastChar
- firstChar
+ 1);
1766 if(count
<= 0) return FALSE
;
1768 str
= HeapAlloc(GetProcessHeap(), 0, count
);
1769 for(i
= 0; i
< count
; i
++)
1770 str
[i
] = (BYTE
)(firstChar
+ i
);
1772 wstr
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
1774 for(i
= 0; i
< wlen
; i
++)
1776 if(!GetCharWidth32W(hdc
, wstr
[i
], wstr
[i
], buffer
))
1784 HeapFree(GetProcessHeap(), 0, str
);
1785 HeapFree(GetProcessHeap(), 0, wstr
);
1791 /***********************************************************************
1792 * ExtTextOutA (GDI32.@)
1796 BOOL WINAPI
ExtTextOutA( HDC hdc
, INT x
, INT y
, UINT flags
,
1797 const RECT
*lprect
, LPCSTR str
, UINT count
, const INT
*lpDx
)
1805 if (flags
& ETO_GLYPH_INDEX
)
1806 return ExtTextOutW( hdc
, x
, y
, flags
, lprect
, (LPCWSTR
)str
, count
, lpDx
);
1808 p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, &codepage
);
1811 unsigned int i
= 0, j
= 0;
1813 lpDxW
= HeapAlloc( GetProcessHeap(), 0, wlen
*sizeof(INT
));
1815 if(IsDBCSLeadByteEx(codepage
, str
[i
])) {
1816 lpDxW
[j
++] = lpDx
[i
] + lpDx
[i
+1];
1819 lpDxW
[j
++] = lpDx
[i
];
1825 ret
= ExtTextOutW( hdc
, x
, y
, flags
, lprect
, p
, wlen
, lpDxW
);
1827 HeapFree( GetProcessHeap(), 0, p
);
1828 HeapFree( GetProcessHeap(), 0, lpDxW
);
1833 /***********************************************************************
1834 * ExtTextOutW (GDI32.@)
1836 * Draws text using the currently selected font, background color, and text color.
1840 * x,y [I] coordinates of string
1842 * ETO_GRAYED - undocumented on MSDN
1843 * ETO_OPAQUE - use background color for fill the rectangle
1844 * ETO_CLIPPED - clipping text to the rectangle
1845 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1846 * than encoded characters. Implies ETO_IGNORELANGUAGE
1847 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1848 * Affects BiDi ordering
1849 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1850 * ETO_PDY - unimplemented
1851 * ETO_NUMERICSLATIN - unimplemented always assumed -
1852 * do not translate numbers into locale representations
1853 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1854 * lprect [I] dimensions for clipping or/and opaquing
1855 * str [I] text string
1856 * count [I] number of symbols in string
1857 * lpDx [I] optional parameter with distance between drawing characters
1863 BOOL WINAPI
ExtTextOutW( HDC hdc
, INT x
, INT y
, UINT flags
,
1864 const RECT
*lprect
, LPCWSTR str
, UINT count
, const INT
*lpDx
)
1867 LPWSTR reordered_str
= (LPWSTR
)str
;
1868 WORD
*glyphs
= NULL
;
1869 UINT align
= GetTextAlign( hdc
);
1873 double cosEsc
, sinEsc
;
1874 INT
*deltas
= NULL
, char_extra
;
1877 BOOL done_extents
= FALSE
;
1878 INT width
= 0, xwidth
= 0, ywidth
= 0;
1880 DC
* dc
= DC_GetDCUpdate( hdc
);
1883 if (!dc
) return FALSE
;
1885 breakRem
= dc
->breakRem
;
1887 if (flags
& (ETO_NUMERICSLOCAL
| ETO_NUMERICSLATIN
| ETO_PDY
))
1888 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY unimplemented\n");
1890 if (!dc
->funcs
->pExtTextOut
&& !PATH_IsPathOpen(dc
->path
))
1892 GDI_ReleaseObj( hdc
);
1896 type
= GetObjectType(hdc
);
1897 if(type
== OBJ_METADC
|| type
== OBJ_ENHMETADC
)
1899 ret
= dc
->funcs
->pExtTextOut(dc
->physDev
, x
, y
, flags
, lprect
, str
, count
, lpDx
);
1900 GDI_ReleaseObj( hdc
);
1905 flags
&= ~ETO_CLIPPED
;
1907 if( !(flags
& (ETO_GLYPH_INDEX
| ETO_IGNORELANGUAGE
)) && BidiAvail
&& count
> 0 )
1909 reordered_str
= HeapAlloc(GetProcessHeap(), 0, count
*sizeof(WCHAR
));
1911 BIDI_Reorder( str
, count
, GCP_REORDER
,
1912 ((flags
&ETO_RTLREADING
)!=0 || (GetTextAlign(hdc
)&TA_RTLREADING
)!=0)?
1913 WINE_GCPW_FORCE_RTL
:WINE_GCPW_FORCE_LTR
,
1914 reordered_str
, count
, NULL
);
1916 flags
|= ETO_IGNORELANGUAGE
;
1919 TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc
, x
, y
, flags
,
1920 lprect
, debugstr_wn(str
, count
), count
, lpDx
);
1922 if(flags
& ETO_GLYPH_INDEX
)
1923 glyphs
= reordered_str
;
1926 TRACE("rect: %d,%d - %d,%d\n", lprect
->left
, lprect
->top
, lprect
->right
,
1928 TRACE("align = %x bkmode = %x mapmode = %x\n", align
, GetBkMode(hdc
), GetMapMode(hdc
));
1930 if(align
& TA_UPDATECP
)
1932 GetCurrentPositionEx( hdc
, &pt
);
1937 GetTextMetricsW(hdc
, &tm
);
1938 GetObjectW(GetCurrentObject(hdc
, OBJ_FONT
), sizeof(lf
), &lf
);
1940 if(!(tm
.tmPitchAndFamily
& TMPF_VECTOR
)) /* Non-scalable fonts shouldn't be rotated */
1941 lf
.lfEscapement
= 0;
1943 if(lf
.lfEscapement
!= 0)
1945 cosEsc
= cos(lf
.lfEscapement
* M_PI
/ 1800);
1946 sinEsc
= sin(lf
.lfEscapement
* M_PI
/ 1800);
1954 if(flags
& (ETO_CLIPPED
| ETO_OPAQUE
))
1958 if(flags
& ETO_GLYPH_INDEX
)
1959 GetTextExtentPointI(hdc
, glyphs
, count
, &sz
);
1961 GetTextExtentPointW(hdc
, reordered_str
, count
, &sz
);
1963 done_extents
= TRUE
;
1966 rc
.right
= x
+ sz
.cx
;
1967 rc
.bottom
= y
+ sz
.cy
;
1974 LPtoDP(hdc
, (POINT
*)&rc
, 2);
1976 if(rc
.left
> rc
.right
) {INT tmp
= rc
.left
; rc
.left
= rc
.right
; rc
.right
= tmp
;}
1977 if(rc
.top
> rc
.bottom
) {INT tmp
= rc
.top
; rc
.top
= rc
.bottom
; rc
.bottom
= tmp
;}
1980 if ((flags
& ETO_OPAQUE
) && !PATH_IsPathOpen(dc
->path
))
1981 dc
->funcs
->pExtTextOut(dc
->physDev
, 0, 0, ETO_OPAQUE
, &rc
, NULL
, 0, NULL
);
1991 LPtoDP(hdc
, &pt
, 1);
1995 char_extra
= GetTextCharacterExtra(hdc
);
1996 if(char_extra
|| dc
->breakExtra
|| breakRem
|| lpDx
|| lf
.lfEscapement
!= 0)
2000 deltas
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(INT
));
2001 for(i
= 0; i
< count
; i
++)
2003 if(lpDx
&& (flags
& ETO_PDY
))
2004 deltas
[i
] = lpDx
[i
*2] + char_extra
;
2006 deltas
[i
] = lpDx
[i
] + char_extra
;
2009 if(flags
& ETO_GLYPH_INDEX
)
2010 GetTextExtentPointI(hdc
, glyphs
+ i
, 1, &tmpsz
);
2012 GetTextExtentPointW(hdc
, reordered_str
+ i
, 1, &tmpsz
);
2014 deltas
[i
] = tmpsz
.cx
;
2017 if (!(flags
& ETO_GLYPH_INDEX
) && (dc
->breakExtra
|| breakRem
) && reordered_str
[i
] == tm
.tmBreakChar
)
2019 deltas
[i
] = deltas
[i
] + dc
->breakExtra
;
2026 deltas
[i
] = INTERNAL_XWSTODS(dc
, deltas
[i
]);
2034 if(flags
& ETO_GLYPH_INDEX
)
2035 GetTextExtentPointI(hdc
, glyphs
, count
, &sz
);
2037 GetTextExtentPointW(hdc
, reordered_str
, count
, &sz
);
2038 done_extents
= TRUE
;
2040 width
= INTERNAL_XWSTODS(dc
, sz
.cx
);
2042 xwidth
= width
* cosEsc
;
2043 ywidth
= width
* sinEsc
;
2045 tm
.tmAscent
= abs(INTERNAL_YWSTODS(dc
, tm
.tmAscent
));
2046 tm
.tmDescent
= abs(INTERNAL_YWSTODS(dc
, tm
.tmDescent
));
2047 switch( align
& (TA_LEFT
| TA_RIGHT
| TA_CENTER
) )
2050 if (align
& TA_UPDATECP
)
2054 DPtoLP(hdc
, &pt
, 1);
2055 MoveToEx(hdc
, pt
.x
, pt
.y
, NULL
);
2067 if (align
& TA_UPDATECP
)
2071 DPtoLP(hdc
, &pt
, 1);
2072 MoveToEx(hdc
, pt
.x
, pt
.y
, NULL
);
2077 switch( align
& (TA_TOP
| TA_BOTTOM
| TA_BASELINE
) )
2080 y
+= tm
.tmAscent
* cosEsc
;
2081 x
+= tm
.tmAscent
* sinEsc
;
2085 y
-= tm
.tmDescent
* cosEsc
;
2086 x
-= tm
.tmDescent
* sinEsc
;
2093 if (GetBkMode(hdc
) != TRANSPARENT
&& !PATH_IsPathOpen(dc
->path
))
2095 if(!((flags
& ETO_CLIPPED
) && (flags
& ETO_OPAQUE
)))
2097 if(!(flags
& ETO_OPAQUE
) || x
< rc
.left
|| x
+ width
>= rc
.right
||
2098 y
- tm
.tmAscent
< rc
.top
|| y
+ tm
.tmDescent
>= rc
.bottom
)
2102 rc
.right
= x
+ width
;
2103 rc
.top
= y
- tm
.tmAscent
;
2104 rc
.bottom
= y
+ tm
.tmDescent
;
2105 dc
->funcs
->pExtTextOut(dc
->physDev
, 0, 0, ETO_OPAQUE
, &rc
, NULL
, 0, NULL
);
2110 if(FontIsLinked(hdc
) && !(flags
& ETO_GLYPH_INDEX
))
2112 HFONT orig_font
= dc
->hFont
, cur_font
;
2114 INT span
= 0, *offsets
= NULL
, i
;
2116 glyphs
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(WORD
));
2117 for(i
= 0; i
< count
; i
++)
2119 WineEngGetLinkedHFont(dc
, reordered_str
[i
], &cur_font
, &glyph
);
2120 if(cur_font
!= dc
->hFont
)
2125 offsets
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(*deltas
));
2130 for(j
= 1; j
< count
; j
++)
2132 GetTextExtentPointW(hdc
, reordered_str
+ j
- 1, 1, &tmpsz
);
2133 offsets
[j
] = offsets
[j
-1] + INTERNAL_XWSTODS(dc
, tmpsz
.cx
);
2138 for(j
= 1; j
< count
; j
++)
2139 offsets
[j
] = offsets
[j
-1] + deltas
[j
];
2144 if (PATH_IsPathOpen(dc
->path
))
2145 ret
= PATH_ExtTextOut(dc
, x
+ offsets
[i
- span
] * cosEsc
, y
- offsets
[i
- span
] * sinEsc
,
2146 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
,
2147 glyphs
, span
, deltas
? deltas
+ i
- span
: NULL
);
2149 dc
->funcs
->pExtTextOut(dc
->physDev
, x
+ offsets
[i
- span
] * cosEsc
, y
- offsets
[i
- span
] * sinEsc
,
2150 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
,
2151 glyphs
, span
, deltas
? deltas
+ i
- span
: NULL
);
2154 SelectObject(hdc
, cur_font
);
2156 glyphs
[span
++] = glyph
;
2160 if (PATH_IsPathOpen(dc
->path
))
2161 ret
= PATH_ExtTextOut(dc
, x
+ (offsets
? offsets
[count
- span
] * cosEsc
: 0),
2162 y
- (offsets
? offsets
[count
- span
] * sinEsc
: 0),
2163 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
,
2164 glyphs
, span
, deltas
? deltas
+ count
- span
: NULL
);
2166 ret
= dc
->funcs
->pExtTextOut(dc
->physDev
, x
+ (offsets
? offsets
[count
- span
] * cosEsc
: 0),
2167 y
- (offsets
? offsets
[count
- span
] * sinEsc
: 0),
2168 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
,
2169 glyphs
, span
, deltas
? deltas
+ count
- span
: NULL
);
2170 SelectObject(hdc
, orig_font
);
2171 HeapFree(GetProcessHeap(), 0, offsets
);
2177 if(!(flags
& ETO_GLYPH_INDEX
) && dc
->gdiFont
)
2179 glyphs
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(WORD
));
2180 GetGlyphIndicesW(hdc
, reordered_str
, count
, glyphs
, 0);
2181 flags
|= ETO_GLYPH_INDEX
;
2184 if (PATH_IsPathOpen(dc
->path
))
2185 ret
= PATH_ExtTextOut(dc
, x
, y
, (flags
& ~ETO_OPAQUE
), &rc
,
2186 glyphs
? glyphs
: reordered_str
, count
, deltas
);
2188 ret
= dc
->funcs
->pExtTextOut(dc
->physDev
, x
, y
, (flags
& ~ETO_OPAQUE
), &rc
,
2189 glyphs
? glyphs
: reordered_str
, count
, deltas
);
2193 HeapFree(GetProcessHeap(), 0, deltas
);
2194 if(glyphs
!= reordered_str
)
2195 HeapFree(GetProcessHeap(), 0, glyphs
);
2196 if(reordered_str
!= str
)
2197 HeapFree(GetProcessHeap(), 0, reordered_str
);
2199 GDI_ReleaseObj( hdc
);
2201 if (ret
&& (lf
.lfUnderline
|| lf
.lfStrikeOut
))
2203 int underlinePos
, strikeoutPos
;
2204 int underlineWidth
, strikeoutWidth
;
2205 UINT size
= GetOutlineTextMetricsW(hdc
, 0, NULL
);
2206 OUTLINETEXTMETRICW
* otm
= NULL
;
2211 underlineWidth
= tm
.tmAscent
/ 20 + 1;
2212 strikeoutPos
= tm
.tmAscent
/ 2;
2213 strikeoutWidth
= underlineWidth
;
2217 otm
= HeapAlloc(GetProcessHeap(), 0, size
);
2218 GetOutlineTextMetricsW(hdc
, size
, otm
);
2219 underlinePos
= otm
->otmsUnderscorePosition
;
2220 underlineWidth
= otm
->otmsUnderscoreSize
;
2221 strikeoutPos
= otm
->otmsStrikeoutPosition
;
2222 strikeoutWidth
= otm
->otmsStrikeoutSize
;
2223 HeapFree(GetProcessHeap(), 0, otm
);
2226 if (PATH_IsPathOpen(dc
->path
))
2230 HBRUSH hbrush
= CreateSolidBrush(GetTextColor(hdc
));
2232 hbrush
= SelectObject(hdc
, hbrush
);
2233 hpen
= SelectObject(hdc
, GetStockObject(NULL_PEN
));
2237 pts
[0].x
= x
- underlinePos
* sinEsc
;
2238 pts
[0].y
= y
- underlinePos
* cosEsc
;
2239 pts
[1].x
= x
+ xwidth
- underlinePos
* sinEsc
;
2240 pts
[1].y
= y
- ywidth
- underlinePos
* cosEsc
;
2241 pts
[2].x
= pts
[1].x
+ underlineWidth
* sinEsc
;
2242 pts
[2].y
= pts
[1].y
+ underlineWidth
* cosEsc
;
2243 pts
[3].x
= pts
[0].x
+ underlineWidth
* sinEsc
;
2244 pts
[3].y
= pts
[0].y
+ underlineWidth
* cosEsc
;
2245 pts
[4].x
= pts
[0].x
;
2246 pts
[4].y
= pts
[0].y
;
2247 DPtoLP(hdc
, pts
, 5);
2248 Polygon(hdc
, pts
, 5);
2253 pts
[0].x
= x
- strikeoutPos
* sinEsc
;
2254 pts
[0].y
= y
- strikeoutPos
* cosEsc
;
2255 pts
[1].x
= x
+ xwidth
- strikeoutPos
* sinEsc
;
2256 pts
[1].y
= y
- ywidth
- strikeoutPos
* cosEsc
;
2257 pts
[2].x
= pts
[1].x
+ strikeoutWidth
* sinEsc
;
2258 pts
[2].y
= pts
[1].y
+ strikeoutWidth
* cosEsc
;
2259 pts
[3].x
= pts
[0].x
+ strikeoutWidth
* sinEsc
;
2260 pts
[3].y
= pts
[0].y
+ strikeoutWidth
* cosEsc
;
2261 pts
[4].x
= pts
[0].x
;
2262 pts
[4].y
= pts
[0].y
;
2263 DPtoLP(hdc
, pts
, 5);
2264 Polygon(hdc
, pts
, 5);
2267 SelectObject(hdc
, hpen
);
2268 hbrush
= SelectObject(hdc
, hbrush
);
2269 DeleteObject(hbrush
);
2273 POINT pts
[2], oldpt
;
2278 hpen
= CreatePen(PS_SOLID
, underlineWidth
, GetTextColor(hdc
));
2279 hpen
= SelectObject(hdc
, hpen
);
2282 pts
[1].x
= x
+ xwidth
;
2283 pts
[1].y
= y
- ywidth
;
2284 DPtoLP(hdc
, pts
, 2);
2285 MoveToEx(hdc
, pts
[0].x
- underlinePos
* sinEsc
, pts
[0].y
- underlinePos
* cosEsc
, &oldpt
);
2286 LineTo(hdc
, pts
[1].x
- underlinePos
* sinEsc
, pts
[1].y
- underlinePos
* cosEsc
);
2287 MoveToEx(hdc
, oldpt
.x
, oldpt
.y
, NULL
);
2288 DeleteObject(SelectObject(hdc
, hpen
));
2293 hpen
= CreatePen(PS_SOLID
, strikeoutWidth
, GetTextColor(hdc
));
2294 hpen
= SelectObject(hdc
, hpen
);
2297 pts
[1].x
= x
+ xwidth
;
2298 pts
[1].y
= y
- ywidth
;
2299 DPtoLP(hdc
, pts
, 2);
2300 MoveToEx(hdc
, pts
[0].x
- strikeoutPos
* sinEsc
, pts
[0].y
- strikeoutPos
* cosEsc
, &oldpt
);
2301 LineTo(hdc
, pts
[1].x
- strikeoutPos
* sinEsc
, pts
[1].y
- strikeoutPos
* cosEsc
);
2302 MoveToEx(hdc
, oldpt
.x
, oldpt
.y
, NULL
);
2303 DeleteObject(SelectObject(hdc
, hpen
));
2312 /***********************************************************************
2313 * TextOutA (GDI32.@)
2315 BOOL WINAPI
TextOutA( HDC hdc
, INT x
, INT y
, LPCSTR str
, INT count
)
2317 return ExtTextOutA( hdc
, x
, y
, 0, NULL
, str
, count
, NULL
);
2321 /***********************************************************************
2322 * TextOutW (GDI32.@)
2324 BOOL WINAPI
TextOutW(HDC hdc
, INT x
, INT y
, LPCWSTR str
, INT count
)
2326 return ExtTextOutW( hdc
, x
, y
, 0, NULL
, str
, count
, NULL
);
2330 /***********************************************************************
2331 * PolyTextOutA (GDI32.@)
2335 BOOL WINAPI
PolyTextOutA( HDC hdc
, const POLYTEXTA
*pptxt
, INT cStrings
)
2337 for (; cStrings
>0; cStrings
--, pptxt
++)
2338 if (!ExtTextOutA( hdc
, pptxt
->x
, pptxt
->y
, pptxt
->uiFlags
, &pptxt
->rcl
, pptxt
->lpstr
, pptxt
->n
, pptxt
->pdx
))
2345 /***********************************************************************
2346 * PolyTextOutW (GDI32.@)
2348 * Draw several Strings
2354 BOOL WINAPI
PolyTextOutW( HDC hdc
, const POLYTEXTW
*pptxt
, INT cStrings
)
2356 for (; cStrings
>0; cStrings
--, pptxt
++)
2357 if (!ExtTextOutW( hdc
, pptxt
->x
, pptxt
->y
, pptxt
->uiFlags
, &pptxt
->rcl
, pptxt
->lpstr
, pptxt
->n
, pptxt
->pdx
))
2363 /* FIXME: all following APIs ******************************************/
2366 /***********************************************************************
2367 * SetMapperFlags (GDI32.@)
2369 DWORD WINAPI
SetMapperFlags( HDC hDC
, DWORD dwFlag
)
2371 DC
*dc
= DC_GetDCPtr( hDC
);
2374 if(dc
->funcs
->pSetMapperFlags
)
2376 ret
= dc
->funcs
->pSetMapperFlags( dc
->physDev
, dwFlag
);
2377 /* FIXME: ret is just a success flag, we should return a proper value */
2380 FIXME("(%p, 0x%08x): stub - harmless\n", hDC
, dwFlag
);
2381 GDI_ReleaseObj( hDC
);
2385 /***********************************************************************
2386 * GetAspectRatioFilterEx (GDI.486)
2388 BOOL16 WINAPI
GetAspectRatioFilterEx16( HDC16 hdc
, LPSIZE16 pAspectRatio
)
2390 FIXME("(%04x, %p): -- Empty Stub !\n", hdc
, pAspectRatio
);
2394 /***********************************************************************
2395 * GetAspectRatioFilterEx (GDI32.@)
2397 BOOL WINAPI
GetAspectRatioFilterEx( HDC hdc
, LPSIZE pAspectRatio
)
2399 FIXME("(%p, %p): -- Empty Stub !\n", hdc
, pAspectRatio
);
2404 /***********************************************************************
2405 * GetCharABCWidthsA (GDI32.@)
2407 * See GetCharABCWidthsW.
2409 BOOL WINAPI
GetCharABCWidthsA(HDC hdc
, UINT firstChar
, UINT lastChar
,
2412 INT i
, wlen
, count
= (INT
)(lastChar
- firstChar
+ 1);
2417 if(count
<= 0) return FALSE
;
2419 str
= HeapAlloc(GetProcessHeap(), 0, count
);
2420 for(i
= 0; i
< count
; i
++)
2421 str
[i
] = (BYTE
)(firstChar
+ i
);
2423 wstr
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
2425 for(i
= 0; i
< wlen
; i
++)
2427 if(!GetCharABCWidthsW(hdc
, wstr
[i
], wstr
[i
], abc
))
2435 HeapFree(GetProcessHeap(), 0, str
);
2436 HeapFree(GetProcessHeap(), 0, wstr
);
2442 /******************************************************************************
2443 * GetCharABCWidthsW [GDI32.@]
2445 * Retrieves widths of characters in range.
2448 * hdc [I] Handle of device context
2449 * firstChar [I] First character in range to query
2450 * lastChar [I] Last character in range to query
2451 * abc [O] Address of character-width structure
2454 * Only works with TrueType fonts
2460 BOOL WINAPI
GetCharABCWidthsW( HDC hdc
, UINT firstChar
, UINT lastChar
,
2463 DC
*dc
= DC_GetDCPtr(hdc
);
2467 if (!dc
) return FALSE
;
2470 ret
= WineEngGetCharABCWidths( dc
->gdiFont
, firstChar
, lastChar
, abc
);
2476 /* convert device units to logical */
2477 for( i
= firstChar
; i
<= lastChar
; i
++, abc
++ ) {
2478 abc
->abcA
= INTERNAL_XDSTOWS(dc
, abc
->abcA
);
2479 abc
->abcB
= INTERNAL_XDSTOWS(dc
, abc
->abcB
);
2480 abc
->abcC
= INTERNAL_XDSTOWS(dc
, abc
->abcC
);
2485 GDI_ReleaseObj(hdc
);
2490 /******************************************************************************
2491 * GetCharABCWidthsI [GDI32.@]
2493 * Retrieves widths of characters in range.
2496 * hdc [I] Handle of device context
2497 * firstChar [I] First glyphs in range to query
2498 * count [I] Last glyphs in range to query
2499 * pgi [i] Array of glyphs to query
2500 * abc [O] Address of character-width structure
2503 * Only works with TrueType fonts
2509 BOOL WINAPI
GetCharABCWidthsI( HDC hdc
, UINT firstChar
, UINT count
,
2510 LPWORD pgi
, LPABC abc
)
2512 DC
*dc
= DC_GetDCPtr(hdc
);
2516 if (!dc
) return FALSE
;
2519 ret
= WineEngGetCharABCWidthsI( dc
->gdiFont
, firstChar
, count
, pgi
, abc
);
2525 /* convert device units to logical */
2526 for( i
= 0; i
< count
; i
++, abc
++ ) {
2527 abc
->abcA
= INTERNAL_XDSTOWS(dc
, abc
->abcA
);
2528 abc
->abcB
= INTERNAL_XDSTOWS(dc
, abc
->abcB
);
2529 abc
->abcC
= INTERNAL_XDSTOWS(dc
, abc
->abcC
);
2534 GDI_ReleaseObj(hdc
);
2539 /***********************************************************************
2540 * GetGlyphOutlineA (GDI32.@)
2542 DWORD WINAPI
GetGlyphOutlineA( HDC hdc
, UINT uChar
, UINT fuFormat
,
2543 LPGLYPHMETRICS lpgm
, DWORD cbBuffer
,
2544 LPVOID lpBuffer
, const MAT2
*lpmat2
)
2550 if(!(fuFormat
& GGO_GLYPH_INDEX
)) {
2553 if(uChar
> 0xff) { /* but, 2 bytes character only */
2555 mbchs
[0] = (uChar
& 0xff00) >> 8;
2556 mbchs
[1] = (uChar
& 0xff);
2559 mbchs
[0] = (uChar
& 0xff);
2561 p
= FONT_mbtowc(hdc
, mbchs
, len
, NULL
, NULL
);
2565 ret
= GetGlyphOutlineW(hdc
, c
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
,
2567 HeapFree(GetProcessHeap(), 0, p
);
2571 /***********************************************************************
2572 * GetGlyphOutlineW (GDI32.@)
2574 DWORD WINAPI
GetGlyphOutlineW( HDC hdc
, UINT uChar
, UINT fuFormat
,
2575 LPGLYPHMETRICS lpgm
, DWORD cbBuffer
,
2576 LPVOID lpBuffer
, const MAT2
*lpmat2
)
2578 DC
*dc
= DC_GetDCPtr(hdc
);
2581 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2582 hdc
, uChar
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
, lpmat2
);
2584 if(!dc
) return GDI_ERROR
;
2587 ret
= WineEngGetGlyphOutline(dc
->gdiFont
, uChar
, fuFormat
, lpgm
,
2588 cbBuffer
, lpBuffer
, lpmat2
);
2592 GDI_ReleaseObj(hdc
);
2597 /***********************************************************************
2598 * CreateScalableFontResourceA (GDI32.@)
2600 BOOL WINAPI
CreateScalableFontResourceA( DWORD fHidden
,
2601 LPCSTR lpszResourceFile
,
2602 LPCSTR lpszFontFile
,
2603 LPCSTR lpszCurrentPath
)
2607 /* fHidden=1 - only visible for the calling app, read-only, not
2608 * enumbered with EnumFonts/EnumFontFamilies
2609 * lpszCurrentPath can be NULL
2611 FIXME("(%d,%s,%s,%s): stub\n",
2612 fHidden
, debugstr_a(lpszResourceFile
), debugstr_a(lpszFontFile
),
2613 debugstr_a(lpszCurrentPath
) );
2615 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2616 if ((f
= CreateFileA(lpszResourceFile
, 0, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, 0)) != INVALID_HANDLE_VALUE
) {
2618 SetLastError(ERROR_FILE_EXISTS
);
2621 return FALSE
; /* create failed */
2624 /***********************************************************************
2625 * CreateScalableFontResourceW (GDI32.@)
2627 BOOL WINAPI
CreateScalableFontResourceW( DWORD fHidden
,
2628 LPCWSTR lpszResourceFile
,
2629 LPCWSTR lpszFontFile
,
2630 LPCWSTR lpszCurrentPath
)
2632 FIXME("(%d,%p,%p,%p): stub\n",
2633 fHidden
, lpszResourceFile
, lpszFontFile
, lpszCurrentPath
);
2634 return FALSE
; /* create failed */
2637 /*************************************************************************
2638 * GetKerningPairsA (GDI32.@)
2640 DWORD WINAPI
GetKerningPairsA( HDC hDC
, DWORD cPairs
,
2641 LPKERNINGPAIR kern_pairA
)
2646 DWORD i
, total_kern_pairs
, kern_pairs_copied
= 0;
2647 KERNINGPAIR
*kern_pairW
;
2649 if (!cPairs
&& kern_pairA
)
2651 SetLastError(ERROR_INVALID_PARAMETER
);
2655 charset
= GetTextCharset(hDC
);
2656 if (!TranslateCharsetInfo(ULongToPtr(charset
), &csi
, TCI_SRCCHARSET
))
2658 FIXME("Can't find codepage for charset %d\n", charset
);
2661 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2662 * to fail on an invalid character for CP_SYMBOL.
2664 cpi
.DefaultChar
[0] = 0;
2665 if (csi
.ciACP
!= CP_SYMBOL
&& !GetCPInfo(csi
.ciACP
, &cpi
))
2667 FIXME("Can't find codepage %u info\n", csi
.ciACP
);
2670 TRACE("charset %d => codepage %u\n", charset
, csi
.ciACP
);
2672 total_kern_pairs
= GetKerningPairsW(hDC
, 0, NULL
);
2673 if (!total_kern_pairs
) return 0;
2675 kern_pairW
= HeapAlloc(GetProcessHeap(), 0, total_kern_pairs
* sizeof(*kern_pairW
));
2676 GetKerningPairsW(hDC
, total_kern_pairs
, kern_pairW
);
2678 for (i
= 0; i
< total_kern_pairs
; i
++)
2682 if (!WideCharToMultiByte(csi
.ciACP
, 0, &kern_pairW
[i
].wFirst
, 1, &first
, 1, NULL
, NULL
))
2685 if (!WideCharToMultiByte(csi
.ciACP
, 0, &kern_pairW
[i
].wSecond
, 1, &second
, 1, NULL
, NULL
))
2688 if (first
== cpi
.DefaultChar
[0] || second
== cpi
.DefaultChar
[0])
2693 if (kern_pairs_copied
>= cPairs
) break;
2695 kern_pairA
->wFirst
= (BYTE
)first
;
2696 kern_pairA
->wSecond
= (BYTE
)second
;
2697 kern_pairA
->iKernAmount
= kern_pairW
[i
].iKernAmount
;
2700 kern_pairs_copied
++;
2703 HeapFree(GetProcessHeap(), 0, kern_pairW
);
2705 return kern_pairs_copied
;
2708 /*************************************************************************
2709 * GetKerningPairsW (GDI32.@)
2711 DWORD WINAPI
GetKerningPairsW( HDC hDC
, DWORD cPairs
,
2712 LPKERNINGPAIR lpKerningPairs
)
2717 TRACE("(%p,%d,%p)\n", hDC
, cPairs
, lpKerningPairs
);
2719 if (!cPairs
&& lpKerningPairs
)
2721 SetLastError(ERROR_INVALID_PARAMETER
);
2725 dc
= DC_GetDCPtr(hDC
);
2729 ret
= WineEngGetKerningPairs(dc
->gdiFont
, cPairs
, lpKerningPairs
);
2731 GDI_ReleaseObj(hDC
);
2735 /*************************************************************************
2736 * TranslateCharsetInfo [GDI32.@]
2738 * Fills a CHARSETINFO structure for a character set, code page, or
2739 * font. This allows making the correspondance between different labelings
2740 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2741 * of the same encoding.
2743 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2744 * only one codepage should be set in *lpSrc.
2747 * TRUE on success, FALSE on failure.
2750 BOOL WINAPI
TranslateCharsetInfo(
2751 LPDWORD lpSrc
, /* [in]
2752 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2753 if flags == TCI_SRCCHARSET: a character set value
2754 if flags == TCI_SRCCODEPAGE: a code page value
2756 LPCHARSETINFO lpCs
, /* [out] structure to receive charset information */
2757 DWORD flags
/* [in] determines interpretation of lpSrc */)
2761 case TCI_SRCFONTSIG
:
2762 while (!(*lpSrc
>>index
& 0x0001) && index
<MAXTCIINDEX
) index
++;
2764 case TCI_SRCCODEPAGE
:
2765 while (PtrToUlong(lpSrc
) != FONT_tci
[index
].ciACP
&& index
< MAXTCIINDEX
) index
++;
2767 case TCI_SRCCHARSET
:
2768 while (PtrToUlong(lpSrc
) != FONT_tci
[index
].ciCharset
&& index
< MAXTCIINDEX
) index
++;
2773 if (index
>= MAXTCIINDEX
|| FONT_tci
[index
].ciCharset
== DEFAULT_CHARSET
) return FALSE
;
2774 memcpy(lpCs
, &FONT_tci
[index
], sizeof(CHARSETINFO
));
2778 /*************************************************************************
2779 * GetFontLanguageInfo (GDI32.@)
2781 DWORD WINAPI
GetFontLanguageInfo(HDC hdc
)
2783 FONTSIGNATURE fontsig
;
2784 static const DWORD GCP_DBCS_MASK
=0x003F0000,
2785 GCP_DIACRITIC_MASK
=0x00000000,
2786 FLI_GLYPHS_MASK
=0x00000000,
2787 GCP_GLYPHSHAPE_MASK
=0x00000040,
2788 GCP_KASHIDA_MASK
=0x00000000,
2789 GCP_LIGATE_MASK
=0x00000000,
2790 GCP_USEKERNING_MASK
=0x00000000,
2791 GCP_REORDER_MASK
=0x00000060;
2795 GetTextCharsetInfo( hdc
, &fontsig
, 0 );
2796 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2798 if( (fontsig
.fsCsb
[0]&GCP_DBCS_MASK
)!=0 )
2801 if( (fontsig
.fsCsb
[0]&GCP_DIACRITIC_MASK
)!=0 )
2802 result
|=GCP_DIACRITIC
;
2804 if( (fontsig
.fsCsb
[0]&FLI_GLYPHS_MASK
)!=0 )
2807 if( (fontsig
.fsCsb
[0]&GCP_GLYPHSHAPE_MASK
)!=0 )
2808 result
|=GCP_GLYPHSHAPE
;
2810 if( (fontsig
.fsCsb
[0]&GCP_KASHIDA_MASK
)!=0 )
2811 result
|=GCP_KASHIDA
;
2813 if( (fontsig
.fsCsb
[0]&GCP_LIGATE_MASK
)!=0 )
2816 if( (fontsig
.fsCsb
[0]&GCP_USEKERNING_MASK
)!=0 )
2817 result
|=GCP_USEKERNING
;
2819 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2820 if( GetTextAlign( hdc
) & TA_RTLREADING
)
2821 if( (fontsig
.fsCsb
[0]&GCP_REORDER_MASK
)!=0 )
2822 result
|=GCP_REORDER
;
2828 /*************************************************************************
2829 * GetFontData [GDI32.@]
2831 * Retrieve data for TrueType font.
2835 * success: Number of bytes returned
2836 * failure: GDI_ERROR
2840 * Calls SetLastError()
2843 DWORD WINAPI
GetFontData(HDC hdc
, DWORD table
, DWORD offset
,
2844 LPVOID buffer
, DWORD length
)
2846 DC
*dc
= DC_GetDCPtr(hdc
);
2847 DWORD ret
= GDI_ERROR
;
2849 if(!dc
) return GDI_ERROR
;
2852 ret
= WineEngGetFontData(dc
->gdiFont
, table
, offset
, buffer
, length
);
2854 GDI_ReleaseObj(hdc
);
2858 /*************************************************************************
2859 * GetGlyphIndicesA [GDI32.@]
2861 DWORD WINAPI
GetGlyphIndicesA(HDC hdc
, LPCSTR lpstr
, INT count
,
2862 LPWORD pgi
, DWORD flags
)
2868 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2869 hdc
, debugstr_an(lpstr
, count
), count
, pgi
, flags
);
2871 lpstrW
= FONT_mbtowc(hdc
, lpstr
, count
, &countW
, NULL
);
2872 ret
= GetGlyphIndicesW(hdc
, lpstrW
, countW
, pgi
, flags
);
2873 HeapFree(GetProcessHeap(), 0, lpstrW
);
2878 /*************************************************************************
2879 * GetGlyphIndicesW [GDI32.@]
2881 DWORD WINAPI
GetGlyphIndicesW(HDC hdc
, LPCWSTR lpstr
, INT count
,
2882 LPWORD pgi
, DWORD flags
)
2884 DC
*dc
= DC_GetDCPtr(hdc
);
2885 DWORD ret
= GDI_ERROR
;
2887 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2888 hdc
, debugstr_wn(lpstr
, count
), count
, pgi
, flags
);
2890 if(!dc
) return GDI_ERROR
;
2893 ret
= WineEngGetGlyphIndices(dc
->gdiFont
, lpstr
, count
, pgi
, flags
);
2895 GDI_ReleaseObj(hdc
);
2899 /*************************************************************************
2900 * GetCharacterPlacementA [GDI32.@]
2902 * See GetCharacterPlacementW.
2905 * the web browser control of ie4 calls this with dwFlags=0
2908 GetCharacterPlacementA(HDC hdc
, LPCSTR lpString
, INT uCount
,
2909 INT nMaxExtent
, GCP_RESULTSA
*lpResults
,
2914 GCP_RESULTSW resultsW
;
2918 TRACE("%s, %d, %d, 0x%08x\n",
2919 debugstr_an(lpString
, uCount
), uCount
, nMaxExtent
, dwFlags
);
2921 /* both structs are equal in size */
2922 memcpy(&resultsW
, lpResults
, sizeof(resultsW
));
2924 lpStringW
= FONT_mbtowc(hdc
, lpString
, uCount
, &uCountW
, &font_cp
);
2925 if(lpResults
->lpOutString
)
2926 resultsW
.lpOutString
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*uCountW
);
2928 ret
= GetCharacterPlacementW(hdc
, lpStringW
, uCountW
, nMaxExtent
, &resultsW
, dwFlags
);
2930 lpResults
->nGlyphs
= resultsW
.nGlyphs
;
2931 lpResults
->nMaxFit
= resultsW
.nMaxFit
;
2933 if(lpResults
->lpOutString
) {
2934 WideCharToMultiByte(font_cp
, 0, resultsW
.lpOutString
, uCountW
,
2935 lpResults
->lpOutString
, uCount
, NULL
, NULL
);
2938 HeapFree(GetProcessHeap(), 0, lpStringW
);
2939 HeapFree(GetProcessHeap(), 0, resultsW
.lpOutString
);
2944 /*************************************************************************
2945 * GetCharacterPlacementW [GDI32.@]
2947 * Retrieve information about a string. This includes the width, reordering,
2948 * Glyphing and so on.
2952 * The width and height of the string if successful, 0 if failed.
2956 * All flags except GCP_REORDER are not yet implemented.
2957 * Reordering is not 100% complient to the Windows BiDi method.
2958 * Caret positioning is not yet implemented for BiDi.
2959 * Classes are not yet implemented.
2963 GetCharacterPlacementW(
2964 HDC hdc
, /* [in] Device context for which the rendering is to be done */
2965 LPCWSTR lpString
, /* [in] The string for which information is to be returned */
2966 INT uCount
, /* [in] Number of WORDS in string. */
2967 INT nMaxExtent
, /* [in] Maximum extent the string is to take (in HDC logical units) */
2968 GCP_RESULTSW
*lpResults
,/* [in/out] A pointer to a GCP_RESULTSW struct */
2969 DWORD dwFlags
/* [in] Flags specifying how to process the string */
2976 TRACE("%s, %d, %d, 0x%08x\n",
2977 debugstr_wn(lpString
, uCount
), uCount
, nMaxExtent
, dwFlags
);
2979 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2980 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2981 lpResults
->lStructSize
, lpResults
->lpOutString
, lpResults
->lpOrder
,
2982 lpResults
->lpDx
, lpResults
->lpCaretPos
, lpResults
->lpClass
,
2983 lpResults
->lpGlyphs
, lpResults
->nGlyphs
, lpResults
->nMaxFit
);
2985 if(dwFlags
&(~GCP_REORDER
)) FIXME("flags 0x%08x ignored\n", dwFlags
);
2986 if(lpResults
->lpClass
) FIXME("classes not implemented\n");
2987 if (lpResults
->lpCaretPos
&& (dwFlags
& GCP_REORDER
))
2988 FIXME("Caret positions for complex scripts not implemented\n");
2990 nSet
= (UINT
)uCount
;
2991 if(nSet
> lpResults
->nGlyphs
)
2992 nSet
= lpResults
->nGlyphs
;
2994 /* return number of initialized fields */
2995 lpResults
->nGlyphs
= nSet
;
2997 if((dwFlags
&GCP_REORDER
)==0 || !BidiAvail
)
2999 /* Treat the case where no special handling was requested in a fastpath way */
3000 /* copy will do if the GCP_REORDER flag is not set */
3001 if(lpResults
->lpOutString
)
3002 memcpy( lpResults
->lpOutString
, lpString
, nSet
* sizeof(WCHAR
));
3004 if(lpResults
->lpOrder
)
3006 for(i
= 0; i
< nSet
; i
++)
3007 lpResults
->lpOrder
[i
] = i
;
3011 BIDI_Reorder( lpString
, uCount
, dwFlags
, WINE_GCPW_FORCE_LTR
, lpResults
->lpOutString
,
3012 nSet
, lpResults
->lpOrder
);
3015 /* FIXME: Will use the placement chars */
3016 if (lpResults
->lpDx
)
3019 for (i
= 0; i
< nSet
; i
++)
3021 if (GetCharWidth32W(hdc
, lpString
[i
], lpString
[i
], &c
))
3022 lpResults
->lpDx
[i
]= c
;
3026 if (lpResults
->lpCaretPos
&& !(dwFlags
& GCP_REORDER
))
3030 lpResults
->lpCaretPos
[0] = 0;
3031 for (i
= 1; i
< nSet
; i
++)
3032 if (GetTextExtentPoint32W(hdc
, &(lpString
[i
- 1]), 1, &size
))
3033 lpResults
->lpCaretPos
[i
] = (pos
+= size
.cx
);
3036 if(lpResults
->lpGlyphs
)
3037 GetGlyphIndicesW(hdc
, lpString
, nSet
, lpResults
->lpGlyphs
, 0);
3039 if (GetTextExtentPoint32W(hdc
, lpString
, uCount
, &size
))
3040 ret
= MAKELONG(size
.cx
, size
.cy
);
3045 /*************************************************************************
3046 * GetCharABCWidthsFloatA [GDI32.@]
3048 * See GetCharABCWidthsFloatW.
3050 BOOL WINAPI
GetCharABCWidthsFloatA( HDC hdc
, UINT first
, UINT last
, LPABCFLOAT abcf
)
3052 INT i
, wlen
, count
= (INT
)(last
- first
+ 1);
3057 if (count
<= 0) return FALSE
;
3059 str
= HeapAlloc(GetProcessHeap(), 0, count
);
3061 for(i
= 0; i
< count
; i
++)
3062 str
[i
] = (BYTE
)(first
+ i
);
3064 wstr
= FONT_mbtowc( hdc
, str
, count
, &wlen
, NULL
);
3066 for (i
= 0; i
< wlen
; i
++)
3068 if (!GetCharABCWidthsFloatW( hdc
, wstr
[i
], wstr
[i
], abcf
))
3076 HeapFree( GetProcessHeap(), 0, str
);
3077 HeapFree( GetProcessHeap(), 0, wstr
);
3082 /*************************************************************************
3083 * GetCharABCWidthsFloatW [GDI32.@]
3085 * Retrieves widths of a range of characters.
3088 * hdc [I] Handle to device context.
3089 * first [I] First character in range to query.
3090 * last [I] Last character in range to query.
3091 * abcf [O] Array of LPABCFLOAT structures.
3098 * Only works with TrueType fonts. It also doesn't return real
3099 * floats but converted integers because it's implemented on
3100 * top of GetCharABCWidthsW.
3102 BOOL WINAPI
GetCharABCWidthsFloatW( HDC hdc
, UINT first
, UINT last
, LPABCFLOAT abcf
)
3105 unsigned int i
, size
= sizeof(ABC
) * (last
- first
+ 1);
3108 TRACE("%p, %d, %d, %p - partial stub\n", hdc
, first
, last
, abcf
);
3110 abc
= HeapAlloc( GetProcessHeap(), 0, size
);
3111 if (!abc
) return FALSE
;
3113 ret
= GetCharABCWidthsW( hdc
, first
, last
, abc
);
3116 for (i
= first
; i
<= last
; i
++, abc
++, abcf
++)
3118 abcf
->abcfA
= abc
->abcA
;
3119 abcf
->abcfB
= abc
->abcB
;
3120 abcf
->abcfC
= abc
->abcC
;
3123 HeapFree( GetProcessHeap(), 0, abc
);
3127 /*************************************************************************
3128 * GetCharWidthFloatA [GDI32.@]
3130 BOOL WINAPI
GetCharWidthFloatA(HDC hdc
, UINT iFirstChar
,
3131 UINT iLastChar
, PFLOAT pxBuffer
)
3133 FIXME("%p, %u, %u, %p: stub!\n", hdc
, iFirstChar
, iLastChar
, pxBuffer
);
3137 /*************************************************************************
3138 * GetCharWidthFloatW [GDI32.@]
3140 BOOL WINAPI
GetCharWidthFloatW(HDC hdc
, UINT iFirstChar
,
3141 UINT iLastChar
, PFLOAT pxBuffer
)
3143 FIXME("%p, %u, %u, %p: stub!\n", hdc
, iFirstChar
, iLastChar
, pxBuffer
);
3148 /***********************************************************************
3150 * Font Resource API *
3152 ***********************************************************************/
3154 /***********************************************************************
3155 * AddFontResourceA (GDI32.@)
3157 INT WINAPI
AddFontResourceA( LPCSTR str
)
3159 return AddFontResourceExA( str
, 0, NULL
);
3162 /***********************************************************************
3163 * AddFontResourceW (GDI32.@)
3165 INT WINAPI
AddFontResourceW( LPCWSTR str
)
3167 return AddFontResourceExW(str
, 0, NULL
);
3171 /***********************************************************************
3172 * AddFontResourceExA (GDI32.@)
3174 INT WINAPI
AddFontResourceExA( LPCSTR str
, DWORD fl
, PVOID pdv
)
3176 DWORD len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
3177 LPWSTR strW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3180 MultiByteToWideChar(CP_ACP
, 0, str
, -1, strW
, len
);
3181 ret
= AddFontResourceExW(strW
, fl
, pdv
);
3182 HeapFree(GetProcessHeap(), 0, strW
);
3186 /***********************************************************************
3187 * AddFontResourceExW (GDI32.@)
3189 INT WINAPI
AddFontResourceExW( LPCWSTR str
, DWORD fl
, PVOID pdv
)
3191 return WineEngAddFontResourceEx(str
, fl
, pdv
);
3194 /***********************************************************************
3195 * RemoveFontResourceA (GDI32.@)
3197 BOOL WINAPI
RemoveFontResourceA( LPCSTR str
)
3199 return RemoveFontResourceExA(str
, 0, 0);
3202 /***********************************************************************
3203 * RemoveFontResourceW (GDI32.@)
3205 BOOL WINAPI
RemoveFontResourceW( LPCWSTR str
)
3207 return RemoveFontResourceExW(str
, 0, 0);
3210 /***********************************************************************
3211 * AddFontMemResourceEx (GDI32.@)
3213 HANDLE WINAPI
AddFontMemResourceEx( PVOID pbFont
, DWORD cbFont
, PVOID pdv
, DWORD
*pcFonts
)
3215 FIXME("(%p,%08x,%p,%p): stub\n", pbFont
, cbFont
, pdv
, pcFonts
);
3219 /***********************************************************************
3220 * RemoveFontResourceExA (GDI32.@)
3222 BOOL WINAPI
RemoveFontResourceExA( LPCSTR str
, DWORD fl
, PVOID pdv
)
3224 DWORD len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
3225 LPWSTR strW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3228 MultiByteToWideChar(CP_ACP
, 0, str
, -1, strW
, len
);
3229 ret
= RemoveFontResourceExW(strW
, fl
, pdv
);
3230 HeapFree(GetProcessHeap(), 0, strW
);
3234 /***********************************************************************
3235 * RemoveFontResourceExW (GDI32.@)
3237 BOOL WINAPI
RemoveFontResourceExW( LPCWSTR str
, DWORD fl
, PVOID pdv
)
3239 return WineEngRemoveFontResourceEx(str
, fl
, pdv
);
3242 /***********************************************************************
3243 * GetTextCharset (GDI32.@)
3245 UINT WINAPI
GetTextCharset(HDC hdc
)
3247 /* MSDN docs say this is equivalent */
3248 return GetTextCharsetInfo(hdc
, NULL
, 0);
3251 /***********************************************************************
3252 * GetTextCharsetInfo (GDI32.@)
3254 UINT WINAPI
GetTextCharsetInfo(HDC hdc
, LPFONTSIGNATURE fs
, DWORD flags
)
3256 UINT ret
= DEFAULT_CHARSET
;
3257 DC
*dc
= DC_GetDCPtr(hdc
);
3262 ret
= WineEngGetTextCharsetInfo(dc
->gdiFont
, fs
, flags
);
3264 GDI_ReleaseObj(hdc
);
3267 if (ret
== DEFAULT_CHARSET
&& fs
)
3268 memset(fs
, 0, sizeof(FONTSIGNATURE
));
3272 /***********************************************************************
3273 * GdiGetCharDimensions (GDI32.@)
3275 * Gets the average width of the characters in the English alphabet.
3278 * hdc [I] Handle to the device context to measure on.
3279 * lptm [O] Pointer to memory to store the text metrics into.
3280 * height [O] On exit, the maximum height of characters in the English alphabet.
3283 * The average width of characters in the English alphabet.
3286 * This function is used by the dialog manager to get the size of a dialog
3287 * unit. It should also be used by other pieces of code that need to know
3288 * the size of a dialog unit in logical units without having access to the
3289 * window handle of the dialog.
3290 * Windows caches the font metrics from this function, but we don't and
3291 * there doesn't appear to be an immediate advantage to do so.
3294 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3296 LONG WINAPI
GdiGetCharDimensions(HDC hdc
, LPTEXTMETRICW lptm
, LONG
*height
)
3299 static const WCHAR alphabet
[] = {
3300 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3301 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3302 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3304 if(lptm
&& !GetTextMetricsW(hdc
, lptm
)) return 0;
3306 if(!GetTextExtentPointW(hdc
, alphabet
, 52, &sz
)) return 0;
3308 if (height
) *height
= sz
.cy
;
3309 return (sz
.cx
/ 26 + 1) / 2;
3312 BOOL WINAPI
EnableEUDC(BOOL fEnableEUDC
)
3314 FIXME("(%d): stub\n", fEnableEUDC
);
3318 /***********************************************************************
3319 * GetCharWidthI (GDI32.@)
3321 * Retrieve widths of characters.
3324 * hdc [I] Handle to a device context.
3325 * first [I] First glyph in range to query.
3326 * count [I] Number of glyph indices to query.
3327 * glyphs [I] Array of glyphs to query.
3328 * buffer [O] Buffer to receive character widths.
3331 * Only works with TrueType fonts.
3337 BOOL WINAPI
GetCharWidthI(HDC hdc
, UINT first
, UINT count
, LPWORD glyphs
, LPINT buffer
)
3342 TRACE("(%p, %d, %d, %p, %p)\n", hdc
, first
, count
, glyphs
, buffer
);
3344 if (!(abc
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(ABC
))))
3347 if (!GetCharABCWidthsI(hdc
, first
, count
, glyphs
, abc
))
3349 HeapFree(GetProcessHeap(), 0, abc
);
3353 for (i
= 0; i
< count
; i
++)
3354 buffer
[i
] = abc
->abcA
+ abc
->abcB
+ abc
->abcC
;
3356 HeapFree(GetProcessHeap(), 0, abc
);
3360 /***********************************************************************
3361 * GetFontUnicodeRanges (GDI32.@)
3363 * Retrieve a list of supported Unicode characters in a font.
3366 * hdc [I] Handle to a device context.
3367 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3370 * Success: Number of bytes written to the buffer pointed to by lpgs.
3374 DWORD WINAPI
GetFontUnicodeRanges(HDC hdc
, LPGLYPHSET lpgs
)
3376 return WineEngGetFontUnicodeRanges(hdc
, lpgs
);