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 DC_ReleaseDCPtr( dc
);
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 DC_ReleaseDCPtr( pfe
->dc
); /* 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
) DC_ReleaseDCPtr( dc
);
715 pfe
->hdc
= 0; /* make sure we don't try to release it later on */
723 /***********************************************************************
726 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
727 * We have to use other types because of the FONTENUMPROCW definition.
729 static INT CALLBACK
FONT_EnumInstance( const LOGFONTW
*plf
, const TEXTMETRICW
*ptm
,
730 DWORD fType
, LPARAM lp
)
732 fontEnum32
*pfe
= (fontEnum32
*)lp
;
736 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
737 if((pfe
->lpLogFontParam
->lfCharSet
== DEFAULT_CHARSET
||
738 pfe
->lpLogFontParam
->lfCharSet
== plf
->lfCharSet
) &&
739 (!(fType
& RASTER_FONTTYPE
) || GetDeviceCaps(pfe
->hdc
, TEXTCAPS
) & TC_RA_ABLE
) )
741 /* convert font metrics */
742 ENUMLOGFONTEXA logfont
;
743 NEWTEXTMETRICEXA tmA
;
745 pfe
->dwFlags
|= ENUM_CALLED
;
746 if (!(pfe
->dwFlags
& ENUM_UNICODE
))
748 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW
*)plf
, &logfont
);
749 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW
*)ptm
, &tmA
);
750 plf
= (LOGFONTW
*)&logfont
.elfLogFont
;
751 ptm
= (TEXTMETRICW
*)&tmA
;
753 DC_ReleaseDCPtr( pfe
->dc
); /* release the GDI lock */
755 ret
= pfe
->lpEnumFunc( plf
, ptm
, fType
, pfe
->lpData
);
757 /* get the lock again and make sure the DC is still valid */
758 dc
= DC_GetDCPtr( pfe
->hdc
);
759 if (!dc
|| dc
!= pfe
->dc
|| dc
->physDev
!= pfe
->physDev
)
761 if (dc
) DC_ReleaseDCPtr( dc
);
762 pfe
->hdc
= 0; /* make sure we don't try to release it later on */
770 /***********************************************************************
771 * EnumFontFamiliesEx (GDI.613)
773 INT16 WINAPI
EnumFontFamiliesEx16( HDC16 hDC
, LPLOGFONT16 plf
,
774 FONTENUMPROC16 efproc
, LPARAM lParam
,
779 DC
* dc
= DC_GetDCPtr( HDC_32(hDC
) );
780 NEWTEXTMETRICEX16 tm16
;
781 ENUMLOGFONTEX16 lf16
;
786 FONT_LogFont16ToW(plf
, &lfW
);
788 fe16
.hdc
= HDC_32(hDC
);
790 fe16
.physDev
= dc
->physDev
;
791 fe16
.lpLogFontParam
= plf
;
792 fe16
.lpEnumFunc
= efproc
;
793 fe16
.lpData
= lParam
;
794 fe16
.lpTextMetric
= &tm16
;
795 fe16
.lpLogFont
= &lf16
;
796 fe16
.segTextMetric
= MapLS( &tm16
);
797 fe16
.segLogFont
= MapLS( &lf16
);
800 enum_gdi_fonts
= GetDeviceCaps(fe16
.hdc
, TEXTCAPS
) & TC_VA_ABLE
;
802 if (!dc
->funcs
->pEnumDeviceFonts
&& !enum_gdi_fonts
)
809 ret
= WineEngEnumFonts( &lfW
, FONT_EnumInstance16
, (LPARAM
)&fe16
);
810 fe16
.dwFlags
&= ~ENUM_CALLED
;
811 if (ret
&& dc
->funcs
->pEnumDeviceFonts
) {
812 ret2
= dc
->funcs
->pEnumDeviceFonts( dc
->physDev
, &lfW
, FONT_EnumInstance16
, (LPARAM
)&fe16
);
813 if(fe16
.dwFlags
& ENUM_CALLED
) /* update ret iff a font gets enumed */
817 UnMapLS( fe16
.segTextMetric
);
818 UnMapLS( fe16
.segLogFont
);
819 if (fe16
.dc
) DC_ReleaseDCPtr( fe16
.dc
);
823 /***********************************************************************
824 * FONT_EnumFontFamiliesEx
826 static INT
FONT_EnumFontFamiliesEx( HDC hDC
, LPLOGFONTW plf
,
827 FONTENUMPROCW efproc
,
828 LPARAM lParam
, DWORD dwUnicode
)
831 DC
*dc
= DC_GetDCPtr( hDC
);
837 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf
->lfFaceName
),
839 fe32
.lpLogFontParam
= plf
;
840 fe32
.lpEnumFunc
= efproc
;
841 fe32
.lpData
= lParam
;
842 fe32
.dwFlags
= dwUnicode
;
845 fe32
.physDev
= dc
->physDev
;
847 enum_gdi_fonts
= GetDeviceCaps(hDC
, TEXTCAPS
) & TC_VA_ABLE
;
849 if (!dc
->funcs
->pEnumDeviceFonts
&& !enum_gdi_fonts
)
856 ret
= WineEngEnumFonts( plf
, FONT_EnumInstance
, (LPARAM
)&fe32
);
857 fe32
.dwFlags
&= ~ENUM_CALLED
;
858 if (ret
&& dc
->funcs
->pEnumDeviceFonts
) {
859 ret2
= dc
->funcs
->pEnumDeviceFonts( dc
->physDev
, plf
, FONT_EnumInstance
, (LPARAM
)&fe32
);
860 if(fe32
.dwFlags
& ENUM_CALLED
) /* update ret iff a font gets enumed */
864 if (fe32
.dc
) DC_ReleaseDCPtr( fe32
.dc
);
868 /***********************************************************************
869 * EnumFontFamiliesExW (GDI32.@)
871 INT WINAPI
EnumFontFamiliesExW( HDC hDC
, LPLOGFONTW plf
,
872 FONTENUMPROCW efproc
,
873 LPARAM lParam
, DWORD dwFlags
)
875 return FONT_EnumFontFamiliesEx( hDC
, plf
, efproc
, lParam
, ENUM_UNICODE
);
878 /***********************************************************************
879 * EnumFontFamiliesExA (GDI32.@)
881 INT WINAPI
EnumFontFamiliesExA( HDC hDC
, LPLOGFONTA plf
,
882 FONTENUMPROCA efproc
,
883 LPARAM lParam
, DWORD dwFlags
)
886 FONT_LogFontAToW( plf
, &lfW
);
888 return FONT_EnumFontFamiliesEx( hDC
, &lfW
, (FONTENUMPROCW
)efproc
, lParam
, 0);
891 /***********************************************************************
892 * EnumFontFamilies (GDI.330)
894 INT16 WINAPI
EnumFontFamilies16( HDC16 hDC
, LPCSTR lpFamily
,
895 FONTENUMPROC16 efproc
, LPARAM lpData
)
899 lf
.lfCharSet
= DEFAULT_CHARSET
;
902 if (!*lpFamily
) return 1;
903 lstrcpynA( lf
.lfFaceName
, lpFamily
, LF_FACESIZE
);
905 else lf
.lfFaceName
[0] = '\0';
907 return EnumFontFamiliesEx16( hDC
, &lf
, efproc
, lpData
, 0 );
910 /***********************************************************************
911 * EnumFontFamiliesA (GDI32.@)
913 INT WINAPI
EnumFontFamiliesA( HDC hDC
, LPCSTR lpFamily
,
914 FONTENUMPROCA efproc
, LPARAM lpData
)
918 lf
.lfCharSet
= DEFAULT_CHARSET
;
921 if (!*lpFamily
) return 1;
922 lstrcpynA( lf
.lfFaceName
, lpFamily
, LF_FACESIZE
);
924 else lf
.lfFaceName
[0] = lf
.lfFaceName
[1] = '\0';
926 return EnumFontFamiliesExA( hDC
, &lf
, efproc
, lpData
, 0 );
929 /***********************************************************************
930 * EnumFontFamiliesW (GDI32.@)
932 INT WINAPI
EnumFontFamiliesW( HDC hDC
, LPCWSTR lpFamily
,
933 FONTENUMPROCW efproc
, LPARAM lpData
)
937 lf
.lfCharSet
= DEFAULT_CHARSET
;
940 if (!*lpFamily
) return 1;
941 lstrcpynW( lf
.lfFaceName
, lpFamily
, LF_FACESIZE
);
943 else lf
.lfFaceName
[0] = 0;
945 return EnumFontFamiliesExW( hDC
, &lf
, efproc
, lpData
, 0 );
948 /***********************************************************************
951 INT16 WINAPI
EnumFonts16( HDC16 hDC
, LPCSTR lpName
, FONTENUMPROC16 efproc
,
954 return EnumFontFamilies16( hDC
, lpName
, efproc
, lpData
);
957 /***********************************************************************
958 * EnumFontsA (GDI32.@)
960 INT WINAPI
EnumFontsA( HDC hDC
, LPCSTR lpName
, FONTENUMPROCA efproc
,
963 return EnumFontFamiliesA( hDC
, lpName
, efproc
, lpData
);
966 /***********************************************************************
967 * EnumFontsW (GDI32.@)
969 INT WINAPI
EnumFontsW( HDC hDC
, LPCWSTR lpName
, FONTENUMPROCW efproc
,
972 return EnumFontFamiliesW( hDC
, lpName
, efproc
, lpData
);
976 /***********************************************************************
977 * GetTextCharacterExtra (GDI32.@)
979 INT WINAPI
GetTextCharacterExtra( HDC hdc
)
982 DC
*dc
= DC_GetDCPtr( hdc
);
983 if (!dc
) return 0x80000000;
985 DC_ReleaseDCPtr( dc
);
990 /***********************************************************************
991 * SetTextCharacterExtra (GDI32.@)
993 INT WINAPI
SetTextCharacterExtra( HDC hdc
, INT extra
)
996 DC
* dc
= DC_GetDCPtr( hdc
);
997 if (!dc
) return 0x80000000;
998 if (dc
->funcs
->pSetTextCharacterExtra
)
999 prev
= dc
->funcs
->pSetTextCharacterExtra( dc
->physDev
, extra
);
1002 prev
= dc
->charExtra
;
1003 dc
->charExtra
= extra
;
1005 DC_ReleaseDCPtr( dc
);
1010 /***********************************************************************
1011 * SetTextJustification (GDI32.@)
1013 BOOL WINAPI
SetTextJustification( HDC hdc
, INT extra
, INT breaks
)
1016 DC
* dc
= DC_GetDCPtr( hdc
);
1017 if (!dc
) return FALSE
;
1018 if (dc
->funcs
->pSetTextJustification
)
1019 ret
= dc
->funcs
->pSetTextJustification( dc
->physDev
, extra
, breaks
);
1022 extra
= abs((extra
* dc
->vportExtX
+ dc
->wndExtX
/ 2) / dc
->wndExtX
);
1023 if (!extra
) breaks
= 0;
1026 dc
->breakExtra
= extra
/ breaks
;
1027 dc
->breakRem
= extra
- (breaks
* dc
->breakExtra
);
1035 DC_ReleaseDCPtr( dc
);
1040 /***********************************************************************
1041 * GetTextFaceA (GDI32.@)
1043 INT WINAPI
GetTextFaceA( HDC hdc
, INT count
, LPSTR name
)
1045 INT res
= GetTextFaceW(hdc
, 0, NULL
);
1046 LPWSTR nameW
= HeapAlloc( GetProcessHeap(), 0, res
* 2 );
1047 GetTextFaceW( hdc
, res
, nameW
);
1051 if (count
&& !WideCharToMultiByte( CP_ACP
, 0, nameW
, -1, name
, count
, NULL
, NULL
))
1056 res
= WideCharToMultiByte( CP_ACP
, 0, nameW
, -1, NULL
, 0, NULL
, NULL
);
1057 HeapFree( GetProcessHeap(), 0, nameW
);
1061 /***********************************************************************
1062 * GetTextFaceW (GDI32.@)
1064 INT WINAPI
GetTextFaceW( HDC hdc
, INT count
, LPWSTR name
)
1069 DC
* dc
= DC_GetDCPtr( hdc
);
1073 ret
= WineEngGetTextFace(dc
->gdiFont
, count
, name
);
1074 else if ((font
= (FONTOBJ
*) GDI_GetObjPtr( dc
->hFont
, FONT_MAGIC
)))
1078 lstrcpynW( name
, font
->logfont
.lfFaceName
, count
);
1079 ret
= strlenW(name
);
1081 else ret
= strlenW(font
->logfont
.lfFaceName
) + 1;
1082 GDI_ReleaseObj( dc
->hFont
);
1084 DC_ReleaseDCPtr( dc
);
1089 /***********************************************************************
1090 * GetTextExtentPoint32A (GDI32.@)
1092 * See GetTextExtentPoint32W.
1094 BOOL WINAPI
GetTextExtentPoint32A( HDC hdc
, LPCSTR str
, INT count
,
1099 LPWSTR p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
1102 ret
= GetTextExtentPoint32W( hdc
, p
, wlen
, size
);
1103 HeapFree( GetProcessHeap(), 0, p
);
1106 TRACE("(%p %s %d %p): returning %d x %d\n",
1107 hdc
, debugstr_an (str
, count
), count
, size
, size
->cx
, size
->cy
);
1112 /***********************************************************************
1113 * GetTextExtentPoint32W [GDI32.@]
1115 * Computes width/height for a string.
1117 * Computes width and height of the specified string.
1123 BOOL WINAPI
GetTextExtentPoint32W(
1124 HDC hdc
, /* [in] Handle of device context */
1125 LPCWSTR str
, /* [in] Address of text string */
1126 INT count
, /* [in] Number of characters in string */
1127 LPSIZE size
) /* [out] Address of structure for string size */
1129 return GetTextExtentExPointW(hdc
, str
, count
, 0, NULL
, NULL
, size
);
1132 /***********************************************************************
1133 * GetTextExtentPointI [GDI32.@]
1135 * Computes width and height of the array of glyph indices.
1141 BOOL WINAPI
GetTextExtentPointI(
1142 HDC hdc
, /* [in] Handle of device context */
1143 const WORD
*indices
, /* [in] Address of glyph index array */
1144 INT count
, /* [in] Number of glyphs in array */
1145 LPSIZE size
) /* [out] Address of structure for string size */
1148 DC
* dc
= DC_GetDCPtr( hdc
);
1149 if (!dc
) return FALSE
;
1152 ret
= WineEngGetTextExtentPointI(dc
->gdiFont
, indices
, count
, size
);
1153 size
->cx
= abs(INTERNAL_XDSTOWS(dc
, size
->cx
));
1154 size
->cy
= abs(INTERNAL_YDSTOWS(dc
, size
->cy
));
1155 size
->cx
+= count
* dc
->charExtra
;
1157 else if(dc
->funcs
->pGetTextExtentExPoint
) {
1158 FIXME("calling GetTextExtentExPoint\n");
1159 ret
= dc
->funcs
->pGetTextExtentExPoint( dc
->physDev
, (LPCWSTR
)indices
,
1160 count
, 0, NULL
, NULL
, size
);
1163 DC_ReleaseDCPtr( dc
);
1165 TRACE("(%p %p %d %p): returning %d x %d\n",
1166 hdc
, indices
, count
, size
, size
->cx
, size
->cy
);
1171 /***********************************************************************
1172 * GetTextExtentPointA (GDI32.@)
1174 BOOL WINAPI
GetTextExtentPointA( HDC hdc
, LPCSTR str
, INT count
,
1177 TRACE("not bug compatible.\n");
1178 return GetTextExtentPoint32A( hdc
, str
, count
, size
);
1181 /***********************************************************************
1182 * GetTextExtentPointW (GDI32.@)
1184 BOOL WINAPI
GetTextExtentPointW( HDC hdc
, LPCWSTR str
, INT count
,
1187 TRACE("not bug compatible.\n");
1188 return GetTextExtentPoint32W( hdc
, str
, count
, size
);
1192 /***********************************************************************
1193 * GetTextExtentExPointA (GDI32.@)
1195 BOOL WINAPI
GetTextExtentExPointA( HDC hdc
, LPCSTR str
, INT count
,
1196 INT maxExt
, LPINT lpnFit
,
1197 LPINT alpDx
, LPSIZE size
)
1205 NULL
== (walpDx
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(INT
))))
1208 p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
1209 ret
= GetTextExtentExPointW( hdc
, p
, wlen
, maxExt
, lpnFit
, walpDx
, size
);
1212 INT n
= lpnFit
? *lpnFit
: wlen
;
1214 for(i
= 0, j
= 0; i
< n
; i
++, j
++)
1216 alpDx
[j
] = walpDx
[i
];
1217 if (IsDBCSLeadByte(str
[j
])) alpDx
[++j
] = walpDx
[i
];
1220 if (lpnFit
) *lpnFit
= WideCharToMultiByte(CP_ACP
,0,p
,*lpnFit
,NULL
,0,NULL
,NULL
);
1221 HeapFree( GetProcessHeap(), 0, p
);
1222 HeapFree( GetProcessHeap(), 0, walpDx
);
1227 /***********************************************************************
1228 * GetTextExtentExPointW (GDI32.@)
1230 * Return the size of the string as it would be if it was output properly by
1233 * This should include
1234 * - Intercharacter spacing
1235 * - justification spacing (not yet done)
1236 * - kerning? see below
1238 * Kerning. Since kerning would be carried out by the rendering code it should
1239 * be done by the driver. However they don't support it yet. Also I am not
1240 * yet persuaded that (certainly under Win95) any kerning is actually done.
1242 * str: According to MSDN this should be null-terminated. That is not true; a
1243 * null will not terminate it early.
1244 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1245 * than count. I have seen it be either the size of the full string or
1246 * 1 less than the size of the full string. I have not seen it bear any
1247 * resemblance to the portion that would fit.
1248 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1249 * trailing intercharacter spacing and any trailing justification.
1252 * Currently we do this by measuring each character etc. We should do it by
1253 * passing the request to the driver, perhaps by extending the
1254 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1255 * thinking about kerning issues and rounding issues in the justification.
1258 BOOL WINAPI
GetTextExtentExPointW( HDC hdc
, LPCWSTR str
, INT count
,
1259 INT maxExt
, LPINT lpnFit
,
1260 LPINT alpDx
, LPSIZE size
)
1268 TRACE("(%p, %s, %d)\n",hdc
,debugstr_wn(str
,count
),maxExt
);
1270 dc
= DC_GetDCPtr(hdc
);
1274 GetTextMetricsW(hdc
, &tm
);
1276 /* If we need to calculate nFit, then we need the partial extents even if
1277 the user hasn't provided us with an array. */
1280 dxs
= alpDx
? alpDx
: HeapAlloc(GetProcessHeap(), 0, count
* sizeof alpDx
[0]);
1283 DC_ReleaseDCPtr(dc
);
1284 SetLastError(ERROR_OUTOFMEMORY
);
1292 ret
= WineEngGetTextExtentExPoint(dc
->gdiFont
, str
, count
,
1293 0, NULL
, dxs
, size
);
1294 else if (dc
->funcs
->pGetTextExtentExPoint
)
1295 ret
= dc
->funcs
->pGetTextExtentExPoint(dc
->physDev
, str
, count
,
1296 0, NULL
, dxs
, size
);
1298 /* Perform device size to world size transformations. */
1301 INT extra
= dc
->charExtra
,
1302 breakExtra
= dc
->breakExtra
,
1303 breakRem
= dc
->breakRem
,
1308 for (i
= 0; i
< count
; ++i
)
1310 dxs
[i
] = abs(INTERNAL_XDSTOWS(dc
, dxs
[i
]));
1311 dxs
[i
] += (i
+1) * extra
;
1312 if (count
> 1 && (breakExtra
|| breakRem
) && str
[i
] == tm
.tmBreakChar
)
1314 dxs
[i
] += breakExtra
;
1321 if (dxs
[i
] <= maxExt
)
1324 breakRem
= dc
->breakRem
;
1326 size
->cx
= abs(INTERNAL_XDSTOWS(dc
, size
->cx
));
1327 size
->cy
= abs(INTERNAL_YDSTOWS(dc
, size
->cy
));
1329 if (!dxs
&& count
> 1 && (breakExtra
|| breakRem
))
1331 for (i
= 0; i
< count
; i
++)
1333 if (str
[i
] == tm
.tmBreakChar
)
1335 size
->cx
+= breakExtra
;
1350 HeapFree(GetProcessHeap(), 0, dxs
);
1352 DC_ReleaseDCPtr( dc
);
1354 TRACE("returning %d %d x %d\n",nFit
,size
->cx
,size
->cy
);
1358 /***********************************************************************
1359 * GetTextMetricsA (GDI32.@)
1361 BOOL WINAPI
GetTextMetricsA( HDC hdc
, TEXTMETRICA
*metrics
)
1365 if (!GetTextMetricsW( hdc
, &tm32
)) return FALSE
;
1366 FONT_TextMetricWToA( &tm32
, metrics
);
1370 /***********************************************************************
1371 * GetTextMetricsW (GDI32.@)
1373 BOOL WINAPI
GetTextMetricsW( HDC hdc
, TEXTMETRICW
*metrics
)
1376 DC
* dc
= DC_GetDCPtr( hdc
);
1377 if (!dc
) return FALSE
;
1380 ret
= WineEngGetTextMetrics(dc
->gdiFont
, metrics
);
1381 else if (dc
->funcs
->pGetTextMetrics
)
1382 ret
= dc
->funcs
->pGetTextMetrics( dc
->physDev
, metrics
);
1386 /* device layer returns values in device units
1387 * therefore we have to convert them to logical */
1389 metrics
->tmDigitizedAspectX
= GetDeviceCaps(hdc
, LOGPIXELSX
);
1390 metrics
->tmDigitizedAspectY
= GetDeviceCaps(hdc
, LOGPIXELSY
);
1392 #define WDPTOLP(x) ((x<0)? \
1393 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1394 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1395 #define HDPTOLP(y) ((y<0)? \
1396 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1397 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1399 metrics
->tmHeight
= HDPTOLP(metrics
->tmHeight
);
1400 metrics
->tmAscent
= HDPTOLP(metrics
->tmAscent
);
1401 metrics
->tmDescent
= HDPTOLP(metrics
->tmDescent
);
1402 metrics
->tmInternalLeading
= HDPTOLP(metrics
->tmInternalLeading
);
1403 metrics
->tmExternalLeading
= HDPTOLP(metrics
->tmExternalLeading
);
1404 metrics
->tmAveCharWidth
= WDPTOLP(metrics
->tmAveCharWidth
);
1405 metrics
->tmMaxCharWidth
= WDPTOLP(metrics
->tmMaxCharWidth
);
1406 metrics
->tmOverhang
= WDPTOLP(metrics
->tmOverhang
);
1410 TRACE("text metrics:\n"
1411 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1412 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1413 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1414 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1415 " PitchAndFamily = %02x\n"
1416 " --------------------\n"
1417 " InternalLeading = %i\n"
1421 metrics
->tmWeight
, metrics
->tmFirstChar
, metrics
->tmAveCharWidth
,
1422 metrics
->tmItalic
, metrics
->tmLastChar
, metrics
->tmMaxCharWidth
,
1423 metrics
->tmUnderlined
, metrics
->tmDefaultChar
, metrics
->tmOverhang
,
1424 metrics
->tmStruckOut
, metrics
->tmBreakChar
, metrics
->tmCharSet
,
1425 metrics
->tmPitchAndFamily
,
1426 metrics
->tmInternalLeading
,
1429 metrics
->tmHeight
);
1431 DC_ReleaseDCPtr( dc
);
1436 /***********************************************************************
1437 * GetOutlineTextMetrics [GDI.308] Gets metrics for TrueType fonts.
1440 * lpOTM should be LPOUTLINETEXTMETRIC
1443 * Success: Non-zero or size of required buffer
1446 UINT16 WINAPI
GetOutlineTextMetrics16(
1447 HDC16 hdc
, /* [in] Handle of device context */
1448 UINT16 cbData
, /* [in] Size of metric data array */
1449 LPOUTLINETEXTMETRIC16 lpOTM
) /* [out] Address of metric data array */
1451 FIXME("(%04x,%04x,%p): stub\n", hdc
,cbData
,lpOTM
);
1456 /***********************************************************************
1457 * GetOutlineTextMetricsA (GDI32.@)
1458 * Gets metrics for TrueType fonts.
1461 * If the supplied buffer isn't big enough Windows partially fills it up to
1462 * its given length and returns that length.
1465 * Success: Non-zero or size of required buffer
1468 UINT WINAPI
GetOutlineTextMetricsA(
1469 HDC hdc
, /* [in] Handle of device context */
1470 UINT cbData
, /* [in] Size of metric data array */
1471 LPOUTLINETEXTMETRICA lpOTM
) /* [out] Address of metric data array */
1473 char buf
[512], *ptr
;
1475 OUTLINETEXTMETRICW
*lpOTMW
= (OUTLINETEXTMETRICW
*)buf
;
1476 OUTLINETEXTMETRICA
*output
= lpOTM
;
1479 if((ret
= GetOutlineTextMetricsW(hdc
, 0, NULL
)) == 0)
1481 if(ret
> sizeof(buf
))
1482 lpOTMW
= HeapAlloc(GetProcessHeap(), 0, ret
);
1483 GetOutlineTextMetricsW(hdc
, ret
, lpOTMW
);
1485 needed
= sizeof(OUTLINETEXTMETRICA
);
1486 if(lpOTMW
->otmpFamilyName
)
1487 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1488 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFamilyName
), -1,
1489 NULL
, 0, NULL
, NULL
);
1490 if(lpOTMW
->otmpFaceName
)
1491 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1492 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFaceName
), -1,
1493 NULL
, 0, NULL
, NULL
);
1494 if(lpOTMW
->otmpStyleName
)
1495 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1496 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpStyleName
), -1,
1497 NULL
, 0, NULL
, NULL
);
1498 if(lpOTMW
->otmpFullName
)
1499 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1500 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFullName
), -1,
1501 NULL
, 0, NULL
, NULL
);
1508 TRACE("needed = %d\n", needed
);
1510 /* Since the supplied buffer isn't big enough, we'll alloc one
1511 that is and memcpy the first cbData bytes into the lpOTM at
1513 output
= HeapAlloc(GetProcessHeap(), 0, needed
);
1515 ret
= output
->otmSize
= min(needed
, cbData
);
1516 FONT_TextMetricWToA( &lpOTMW
->otmTextMetrics
, &output
->otmTextMetrics
);
1517 output
->otmFiller
= 0;
1518 output
->otmPanoseNumber
= lpOTMW
->otmPanoseNumber
;
1519 output
->otmfsSelection
= lpOTMW
->otmfsSelection
;
1520 output
->otmfsType
= lpOTMW
->otmfsType
;
1521 output
->otmsCharSlopeRise
= lpOTMW
->otmsCharSlopeRise
;
1522 output
->otmsCharSlopeRun
= lpOTMW
->otmsCharSlopeRun
;
1523 output
->otmItalicAngle
= lpOTMW
->otmItalicAngle
;
1524 output
->otmEMSquare
= lpOTMW
->otmEMSquare
;
1525 output
->otmAscent
= lpOTMW
->otmAscent
;
1526 output
->otmDescent
= lpOTMW
->otmDescent
;
1527 output
->otmLineGap
= lpOTMW
->otmLineGap
;
1528 output
->otmsCapEmHeight
= lpOTMW
->otmsCapEmHeight
;
1529 output
->otmsXHeight
= lpOTMW
->otmsXHeight
;
1530 output
->otmrcFontBox
= lpOTMW
->otmrcFontBox
;
1531 output
->otmMacAscent
= lpOTMW
->otmMacAscent
;
1532 output
->otmMacDescent
= lpOTMW
->otmMacDescent
;
1533 output
->otmMacLineGap
= lpOTMW
->otmMacLineGap
;
1534 output
->otmusMinimumPPEM
= lpOTMW
->otmusMinimumPPEM
;
1535 output
->otmptSubscriptSize
= lpOTMW
->otmptSubscriptSize
;
1536 output
->otmptSubscriptOffset
= lpOTMW
->otmptSubscriptOffset
;
1537 output
->otmptSuperscriptSize
= lpOTMW
->otmptSuperscriptSize
;
1538 output
->otmptSuperscriptOffset
= lpOTMW
->otmptSuperscriptOffset
;
1539 output
->otmsStrikeoutSize
= lpOTMW
->otmsStrikeoutSize
;
1540 output
->otmsStrikeoutPosition
= lpOTMW
->otmsStrikeoutPosition
;
1541 output
->otmsUnderscoreSize
= lpOTMW
->otmsUnderscoreSize
;
1542 output
->otmsUnderscorePosition
= lpOTMW
->otmsUnderscorePosition
;
1545 ptr
= (char*)(output
+ 1);
1546 left
= needed
- sizeof(*output
);
1548 if(lpOTMW
->otmpFamilyName
) {
1549 output
->otmpFamilyName
= (LPSTR
)(ptr
- (char*)output
);
1550 len
= WideCharToMultiByte(CP_ACP
, 0,
1551 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFamilyName
), -1,
1552 ptr
, left
, NULL
, NULL
);
1556 output
->otmpFamilyName
= 0;
1558 if(lpOTMW
->otmpFaceName
) {
1559 output
->otmpFaceName
= (LPSTR
)(ptr
- (char*)output
);
1560 len
= WideCharToMultiByte(CP_ACP
, 0,
1561 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFaceName
), -1,
1562 ptr
, left
, NULL
, NULL
);
1566 output
->otmpFaceName
= 0;
1568 if(lpOTMW
->otmpStyleName
) {
1569 output
->otmpStyleName
= (LPSTR
)(ptr
- (char*)output
);
1570 len
= WideCharToMultiByte(CP_ACP
, 0,
1571 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpStyleName
), -1,
1572 ptr
, left
, NULL
, NULL
);
1576 output
->otmpStyleName
= 0;
1578 if(lpOTMW
->otmpFullName
) {
1579 output
->otmpFullName
= (LPSTR
)(ptr
- (char*)output
);
1580 len
= WideCharToMultiByte(CP_ACP
, 0,
1581 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFullName
), -1,
1582 ptr
, left
, NULL
, NULL
);
1585 output
->otmpFullName
= 0;
1589 if(output
!= lpOTM
) {
1590 memcpy(lpOTM
, output
, cbData
);
1591 HeapFree(GetProcessHeap(), 0, output
);
1593 /* check if the string offsets really fit into the provided size */
1594 /* FIXME: should we check string length as well? */
1595 /* make sure that we don't read/write beyond the provided buffer */
1596 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFamilyName
) + sizeof(LPSTR
))
1598 if ((UINT_PTR
)lpOTM
->otmpFamilyName
>= lpOTM
->otmSize
)
1599 lpOTM
->otmpFamilyName
= 0; /* doesn't fit */
1602 /* make sure that we don't read/write beyond the provided buffer */
1603 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFaceName
) + sizeof(LPSTR
))
1605 if ((UINT_PTR
)lpOTM
->otmpFaceName
>= lpOTM
->otmSize
)
1606 lpOTM
->otmpFaceName
= 0; /* doesn't fit */
1609 /* make sure that we don't read/write beyond the provided buffer */
1610 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpStyleName
) + sizeof(LPSTR
))
1612 if ((UINT_PTR
)lpOTM
->otmpStyleName
>= lpOTM
->otmSize
)
1613 lpOTM
->otmpStyleName
= 0; /* doesn't fit */
1616 /* make sure that we don't read/write beyond the provided buffer */
1617 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFullName
) + sizeof(LPSTR
))
1619 if ((UINT_PTR
)lpOTM
->otmpFullName
>= lpOTM
->otmSize
)
1620 lpOTM
->otmpFullName
= 0; /* doesn't fit */
1625 if(lpOTMW
!= (OUTLINETEXTMETRICW
*)buf
)
1626 HeapFree(GetProcessHeap(), 0, lpOTMW
);
1632 /***********************************************************************
1633 * GetOutlineTextMetricsW [GDI32.@]
1635 UINT WINAPI
GetOutlineTextMetricsW(
1636 HDC hdc
, /* [in] Handle of device context */
1637 UINT cbData
, /* [in] Size of metric data array */
1638 LPOUTLINETEXTMETRICW lpOTM
) /* [out] Address of metric data array */
1640 DC
*dc
= DC_GetDCPtr( hdc
);
1641 OUTLINETEXTMETRICW
*output
= lpOTM
;
1644 TRACE("(%p,%d,%p)\n", hdc
, cbData
, lpOTM
);
1648 ret
= WineEngGetOutlineTextMetrics(dc
->gdiFont
, cbData
, output
);
1651 output
= HeapAlloc(GetProcessHeap(), 0, ret
);
1652 WineEngGetOutlineTextMetrics(dc
->gdiFont
, ret
, output
);
1655 #define WDPTOLP(x) ((x<0)? \
1656 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1657 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1658 #define HDPTOLP(y) ((y<0)? \
1659 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1660 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1662 output
->otmTextMetrics
.tmHeight
= HDPTOLP(output
->otmTextMetrics
.tmHeight
);
1663 output
->otmTextMetrics
.tmAscent
= HDPTOLP(output
->otmTextMetrics
.tmAscent
);
1664 output
->otmTextMetrics
.tmDescent
= HDPTOLP(output
->otmTextMetrics
.tmDescent
);
1665 output
->otmTextMetrics
.tmInternalLeading
= HDPTOLP(output
->otmTextMetrics
.tmInternalLeading
);
1666 output
->otmTextMetrics
.tmExternalLeading
= HDPTOLP(output
->otmTextMetrics
.tmExternalLeading
);
1667 output
->otmTextMetrics
.tmAveCharWidth
= WDPTOLP(output
->otmTextMetrics
.tmAveCharWidth
);
1668 output
->otmTextMetrics
.tmMaxCharWidth
= WDPTOLP(output
->otmTextMetrics
.tmMaxCharWidth
);
1669 output
->otmTextMetrics
.tmOverhang
= WDPTOLP(output
->otmTextMetrics
.tmOverhang
);
1670 output
->otmAscent
= HDPTOLP(output
->otmAscent
);
1671 output
->otmDescent
= HDPTOLP(output
->otmDescent
);
1672 output
->otmLineGap
= HDPTOLP(output
->otmLineGap
);
1673 output
->otmsCapEmHeight
= HDPTOLP(output
->otmsCapEmHeight
);
1674 output
->otmsXHeight
= HDPTOLP(output
->otmsXHeight
);
1675 output
->otmrcFontBox
.top
= HDPTOLP(output
->otmrcFontBox
.top
);
1676 output
->otmrcFontBox
.bottom
= HDPTOLP(output
->otmrcFontBox
.bottom
);
1677 output
->otmrcFontBox
.left
= WDPTOLP(output
->otmrcFontBox
.left
);
1678 output
->otmrcFontBox
.right
= WDPTOLP(output
->otmrcFontBox
.right
);
1679 output
->otmMacAscent
= HDPTOLP(output
->otmMacAscent
);
1680 output
->otmMacDescent
= HDPTOLP(output
->otmMacDescent
);
1681 output
->otmMacLineGap
= HDPTOLP(output
->otmMacLineGap
);
1682 output
->otmptSubscriptSize
.x
= WDPTOLP(output
->otmptSubscriptSize
.x
);
1683 output
->otmptSubscriptSize
.y
= HDPTOLP(output
->otmptSubscriptSize
.y
);
1684 output
->otmptSubscriptOffset
.x
= WDPTOLP(output
->otmptSubscriptOffset
.x
);
1685 output
->otmptSubscriptOffset
.y
= HDPTOLP(output
->otmptSubscriptOffset
.y
);
1686 output
->otmptSuperscriptSize
.x
= WDPTOLP(output
->otmptSuperscriptSize
.x
);
1687 output
->otmptSuperscriptSize
.y
= HDPTOLP(output
->otmptSuperscriptSize
.y
);
1688 output
->otmptSuperscriptOffset
.x
= WDPTOLP(output
->otmptSuperscriptOffset
.x
);
1689 output
->otmptSuperscriptOffset
.y
= HDPTOLP(output
->otmptSuperscriptOffset
.y
);
1690 output
->otmsStrikeoutSize
= HDPTOLP(output
->otmsStrikeoutSize
);
1691 output
->otmsStrikeoutPosition
= HDPTOLP(output
->otmsStrikeoutPosition
);
1692 output
->otmsUnderscoreSize
= HDPTOLP(output
->otmsUnderscoreSize
);
1693 output
->otmsUnderscorePosition
= HDPTOLP(output
->otmsUnderscorePosition
);
1696 if(output
!= lpOTM
) {
1697 memcpy(lpOTM
, output
, cbData
);
1698 HeapFree(GetProcessHeap(), 0, output
);
1704 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1705 but really this should just be a return 0. */
1707 ret
= sizeof(*lpOTM
);
1712 memset(lpOTM
, 0, ret
);
1713 lpOTM
->otmSize
= sizeof(*lpOTM
);
1714 GetTextMetricsW(hdc
, &lpOTM
->otmTextMetrics
);
1716 Further fill of the structure not implemented,
1717 Needs real values for the structure members
1722 DC_ReleaseDCPtr(dc
);
1727 /***********************************************************************
1728 * GetCharWidthW (GDI32.@)
1729 * GetCharWidth32W (GDI32.@)
1731 BOOL WINAPI
GetCharWidth32W( HDC hdc
, UINT firstChar
, UINT lastChar
,
1736 DC
* dc
= DC_GetDCPtr( hdc
);
1737 if (!dc
) return FALSE
;
1740 ret
= WineEngGetCharWidth( dc
->gdiFont
, firstChar
, lastChar
, buffer
);
1741 else if (dc
->funcs
->pGetCharWidth
)
1742 ret
= dc
->funcs
->pGetCharWidth( dc
->physDev
, firstChar
, lastChar
, buffer
);
1746 /* convert device units to logical */
1747 for( i
= firstChar
; i
<= lastChar
; i
++, buffer
++ )
1748 *buffer
= INTERNAL_XDSTOWS(dc
, *buffer
);
1751 DC_ReleaseDCPtr( dc
);
1756 /***********************************************************************
1757 * GetCharWidthA (GDI32.@)
1758 * GetCharWidth32A (GDI32.@)
1760 BOOL WINAPI
GetCharWidth32A( HDC hdc
, UINT firstChar
, UINT lastChar
,
1763 INT i
, wlen
, count
= (INT
)(lastChar
- firstChar
+ 1);
1768 if(count
<= 0) return FALSE
;
1770 str
= HeapAlloc(GetProcessHeap(), 0, count
);
1771 for(i
= 0; i
< count
; i
++)
1772 str
[i
] = (BYTE
)(firstChar
+ i
);
1774 wstr
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
1776 for(i
= 0; i
< wlen
; i
++)
1778 if(!GetCharWidth32W(hdc
, wstr
[i
], wstr
[i
], buffer
))
1786 HeapFree(GetProcessHeap(), 0, str
);
1787 HeapFree(GetProcessHeap(), 0, wstr
);
1793 /***********************************************************************
1794 * ExtTextOutA (GDI32.@)
1798 BOOL WINAPI
ExtTextOutA( HDC hdc
, INT x
, INT y
, UINT flags
,
1799 const RECT
*lprect
, LPCSTR str
, UINT count
, const INT
*lpDx
)
1807 if (flags
& ETO_GLYPH_INDEX
)
1808 return ExtTextOutW( hdc
, x
, y
, flags
, lprect
, (LPCWSTR
)str
, count
, lpDx
);
1810 p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, &codepage
);
1813 unsigned int i
= 0, j
= 0;
1815 lpDxW
= HeapAlloc( GetProcessHeap(), 0, wlen
*sizeof(INT
));
1817 if(IsDBCSLeadByteEx(codepage
, str
[i
])) {
1818 lpDxW
[j
++] = lpDx
[i
] + lpDx
[i
+1];
1821 lpDxW
[j
++] = lpDx
[i
];
1827 ret
= ExtTextOutW( hdc
, x
, y
, flags
, lprect
, p
, wlen
, lpDxW
);
1829 HeapFree( GetProcessHeap(), 0, p
);
1830 HeapFree( GetProcessHeap(), 0, lpDxW
);
1835 /***********************************************************************
1836 * ExtTextOutW (GDI32.@)
1838 * Draws text using the currently selected font, background color, and text color.
1842 * x,y [I] coordinates of string
1844 * ETO_GRAYED - undocumented on MSDN
1845 * ETO_OPAQUE - use background color for fill the rectangle
1846 * ETO_CLIPPED - clipping text to the rectangle
1847 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1848 * than encoded characters. Implies ETO_IGNORELANGUAGE
1849 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1850 * Affects BiDi ordering
1851 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1852 * ETO_PDY - unimplemented
1853 * ETO_NUMERICSLATIN - unimplemented always assumed -
1854 * do not translate numbers into locale representations
1855 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1856 * lprect [I] dimensions for clipping or/and opaquing
1857 * str [I] text string
1858 * count [I] number of symbols in string
1859 * lpDx [I] optional parameter with distance between drawing characters
1865 BOOL WINAPI
ExtTextOutW( HDC hdc
, INT x
, INT y
, UINT flags
,
1866 const RECT
*lprect
, LPCWSTR str
, UINT count
, const INT
*lpDx
)
1869 LPWSTR reordered_str
= (LPWSTR
)str
;
1870 WORD
*glyphs
= NULL
;
1871 UINT align
= GetTextAlign( hdc
);
1875 double cosEsc
, sinEsc
;
1876 INT
*deltas
= NULL
, char_extra
;
1879 BOOL done_extents
= FALSE
;
1880 INT width
= 0, xwidth
= 0, ywidth
= 0;
1882 DC
* dc
= DC_GetDCUpdate( hdc
);
1885 if (!dc
) return FALSE
;
1887 breakRem
= dc
->breakRem
;
1889 if (flags
& (ETO_NUMERICSLOCAL
| ETO_NUMERICSLATIN
| ETO_PDY
))
1890 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY unimplemented\n");
1892 if (!dc
->funcs
->pExtTextOut
&& !PATH_IsPathOpen(dc
->path
))
1894 DC_ReleaseDCPtr( dc
);
1898 type
= GetObjectType(hdc
);
1899 if(type
== OBJ_METADC
|| type
== OBJ_ENHMETADC
)
1901 ret
= dc
->funcs
->pExtTextOut(dc
->physDev
, x
, y
, flags
, lprect
, str
, count
, lpDx
);
1902 DC_ReleaseDCPtr( dc
);
1907 flags
&= ~ETO_CLIPPED
;
1909 if( !(flags
& (ETO_GLYPH_INDEX
| ETO_IGNORELANGUAGE
)) && BidiAvail
&& count
> 0 )
1911 reordered_str
= HeapAlloc(GetProcessHeap(), 0, count
*sizeof(WCHAR
));
1913 BIDI_Reorder( str
, count
, GCP_REORDER
,
1914 ((flags
&ETO_RTLREADING
)!=0 || (GetTextAlign(hdc
)&TA_RTLREADING
)!=0)?
1915 WINE_GCPW_FORCE_RTL
:WINE_GCPW_FORCE_LTR
,
1916 reordered_str
, count
, NULL
);
1918 flags
|= ETO_IGNORELANGUAGE
;
1921 TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc
, x
, y
, flags
,
1922 lprect
, debugstr_wn(str
, count
), count
, lpDx
);
1924 if(flags
& ETO_GLYPH_INDEX
)
1925 glyphs
= reordered_str
;
1928 TRACE("rect: %d,%d - %d,%d\n", lprect
->left
, lprect
->top
, lprect
->right
,
1930 TRACE("align = %x bkmode = %x mapmode = %x\n", align
, GetBkMode(hdc
), GetMapMode(hdc
));
1932 if(align
& TA_UPDATECP
)
1934 GetCurrentPositionEx( hdc
, &pt
);
1939 GetTextMetricsW(hdc
, &tm
);
1940 GetObjectW(GetCurrentObject(hdc
, OBJ_FONT
), sizeof(lf
), &lf
);
1942 if(!(tm
.tmPitchAndFamily
& TMPF_VECTOR
)) /* Non-scalable fonts shouldn't be rotated */
1943 lf
.lfEscapement
= 0;
1945 if(lf
.lfEscapement
!= 0)
1947 cosEsc
= cos(lf
.lfEscapement
* M_PI
/ 1800);
1948 sinEsc
= sin(lf
.lfEscapement
* M_PI
/ 1800);
1956 if(flags
& (ETO_CLIPPED
| ETO_OPAQUE
))
1960 if(flags
& ETO_GLYPH_INDEX
)
1961 GetTextExtentPointI(hdc
, glyphs
, count
, &sz
);
1963 GetTextExtentPointW(hdc
, reordered_str
, count
, &sz
);
1965 done_extents
= TRUE
;
1968 rc
.right
= x
+ sz
.cx
;
1969 rc
.bottom
= y
+ sz
.cy
;
1976 LPtoDP(hdc
, (POINT
*)&rc
, 2);
1978 if(rc
.left
> rc
.right
) {INT tmp
= rc
.left
; rc
.left
= rc
.right
; rc
.right
= tmp
;}
1979 if(rc
.top
> rc
.bottom
) {INT tmp
= rc
.top
; rc
.top
= rc
.bottom
; rc
.bottom
= tmp
;}
1982 if ((flags
& ETO_OPAQUE
) && !PATH_IsPathOpen(dc
->path
))
1983 dc
->funcs
->pExtTextOut(dc
->physDev
, 0, 0, ETO_OPAQUE
, &rc
, NULL
, 0, NULL
);
1993 LPtoDP(hdc
, &pt
, 1);
1997 char_extra
= GetTextCharacterExtra(hdc
);
1998 if(char_extra
|| dc
->breakExtra
|| breakRem
|| lpDx
|| lf
.lfEscapement
!= 0)
2002 deltas
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(INT
));
2003 for(i
= 0; i
< count
; i
++)
2005 if(lpDx
&& (flags
& ETO_PDY
))
2006 deltas
[i
] = lpDx
[i
*2] + char_extra
;
2008 deltas
[i
] = lpDx
[i
] + char_extra
;
2011 if(flags
& ETO_GLYPH_INDEX
)
2012 GetTextExtentPointI(hdc
, glyphs
+ i
, 1, &tmpsz
);
2014 GetTextExtentPointW(hdc
, reordered_str
+ i
, 1, &tmpsz
);
2016 deltas
[i
] = tmpsz
.cx
;
2019 if (!(flags
& ETO_GLYPH_INDEX
) && (dc
->breakExtra
|| breakRem
) && reordered_str
[i
] == tm
.tmBreakChar
)
2021 deltas
[i
] = deltas
[i
] + dc
->breakExtra
;
2028 deltas
[i
] = INTERNAL_XWSTODS(dc
, deltas
[i
]);
2036 if(flags
& ETO_GLYPH_INDEX
)
2037 GetTextExtentPointI(hdc
, glyphs
, count
, &sz
);
2039 GetTextExtentPointW(hdc
, reordered_str
, count
, &sz
);
2040 done_extents
= TRUE
;
2042 width
= INTERNAL_XWSTODS(dc
, sz
.cx
);
2044 xwidth
= width
* cosEsc
;
2045 ywidth
= width
* sinEsc
;
2047 tm
.tmAscent
= abs(INTERNAL_YWSTODS(dc
, tm
.tmAscent
));
2048 tm
.tmDescent
= abs(INTERNAL_YWSTODS(dc
, tm
.tmDescent
));
2049 switch( align
& (TA_LEFT
| TA_RIGHT
| TA_CENTER
) )
2052 if (align
& TA_UPDATECP
)
2056 DPtoLP(hdc
, &pt
, 1);
2057 MoveToEx(hdc
, pt
.x
, pt
.y
, NULL
);
2069 if (align
& TA_UPDATECP
)
2073 DPtoLP(hdc
, &pt
, 1);
2074 MoveToEx(hdc
, pt
.x
, pt
.y
, NULL
);
2079 switch( align
& (TA_TOP
| TA_BOTTOM
| TA_BASELINE
) )
2082 y
+= tm
.tmAscent
* cosEsc
;
2083 x
+= tm
.tmAscent
* sinEsc
;
2087 y
-= tm
.tmDescent
* cosEsc
;
2088 x
-= tm
.tmDescent
* sinEsc
;
2095 if (GetBkMode(hdc
) != TRANSPARENT
&& !PATH_IsPathOpen(dc
->path
))
2097 if(!((flags
& ETO_CLIPPED
) && (flags
& ETO_OPAQUE
)))
2099 if(!(flags
& ETO_OPAQUE
) || x
< rc
.left
|| x
+ width
>= rc
.right
||
2100 y
- tm
.tmAscent
< rc
.top
|| y
+ tm
.tmDescent
>= rc
.bottom
)
2104 rc
.right
= x
+ width
;
2105 rc
.top
= y
- tm
.tmAscent
;
2106 rc
.bottom
= y
+ tm
.tmDescent
;
2107 dc
->funcs
->pExtTextOut(dc
->physDev
, 0, 0, ETO_OPAQUE
, &rc
, NULL
, 0, NULL
);
2112 if(FontIsLinked(hdc
) && !(flags
& ETO_GLYPH_INDEX
))
2114 HFONT orig_font
= dc
->hFont
, cur_font
;
2116 INT span
= 0, *offsets
= NULL
, i
;
2118 glyphs
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(WORD
));
2119 for(i
= 0; i
< count
; i
++)
2121 WineEngGetLinkedHFont(dc
, reordered_str
[i
], &cur_font
, &glyph
);
2122 if(cur_font
!= dc
->hFont
)
2127 offsets
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(*deltas
));
2132 for(j
= 1; j
< count
; j
++)
2134 GetTextExtentPointW(hdc
, reordered_str
+ j
- 1, 1, &tmpsz
);
2135 offsets
[j
] = offsets
[j
-1] + INTERNAL_XWSTODS(dc
, tmpsz
.cx
);
2140 for(j
= 1; j
< count
; j
++)
2141 offsets
[j
] = offsets
[j
-1] + deltas
[j
];
2146 if (PATH_IsPathOpen(dc
->path
))
2147 ret
= PATH_ExtTextOut(dc
, x
+ offsets
[i
- span
] * cosEsc
, y
- offsets
[i
- span
] * sinEsc
,
2148 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
,
2149 glyphs
, span
, deltas
? deltas
+ i
- span
: NULL
);
2151 dc
->funcs
->pExtTextOut(dc
->physDev
, x
+ offsets
[i
- span
] * cosEsc
, y
- offsets
[i
- span
] * sinEsc
,
2152 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
,
2153 glyphs
, span
, deltas
? deltas
+ i
- span
: NULL
);
2156 SelectObject(hdc
, cur_font
);
2158 glyphs
[span
++] = glyph
;
2162 if (PATH_IsPathOpen(dc
->path
))
2163 ret
= PATH_ExtTextOut(dc
, x
+ (offsets
? offsets
[count
- span
] * cosEsc
: 0),
2164 y
- (offsets
? offsets
[count
- span
] * sinEsc
: 0),
2165 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
,
2166 glyphs
, span
, deltas
? deltas
+ count
- span
: NULL
);
2168 ret
= dc
->funcs
->pExtTextOut(dc
->physDev
, x
+ (offsets
? offsets
[count
- span
] * cosEsc
: 0),
2169 y
- (offsets
? offsets
[count
- span
] * sinEsc
: 0),
2170 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
,
2171 glyphs
, span
, deltas
? deltas
+ count
- span
: NULL
);
2172 SelectObject(hdc
, orig_font
);
2173 HeapFree(GetProcessHeap(), 0, offsets
);
2179 if(!(flags
& ETO_GLYPH_INDEX
) && dc
->gdiFont
)
2181 glyphs
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(WORD
));
2182 GetGlyphIndicesW(hdc
, reordered_str
, count
, glyphs
, 0);
2183 flags
|= ETO_GLYPH_INDEX
;
2186 if (PATH_IsPathOpen(dc
->path
))
2187 ret
= PATH_ExtTextOut(dc
, x
, y
, (flags
& ~ETO_OPAQUE
), &rc
,
2188 glyphs
? glyphs
: reordered_str
, count
, deltas
);
2190 ret
= dc
->funcs
->pExtTextOut(dc
->physDev
, x
, y
, (flags
& ~ETO_OPAQUE
), &rc
,
2191 glyphs
? glyphs
: reordered_str
, count
, deltas
);
2195 HeapFree(GetProcessHeap(), 0, deltas
);
2196 if(glyphs
!= reordered_str
)
2197 HeapFree(GetProcessHeap(), 0, glyphs
);
2198 if(reordered_str
!= str
)
2199 HeapFree(GetProcessHeap(), 0, reordered_str
);
2201 DC_ReleaseDCPtr( dc
);
2203 if (ret
&& (lf
.lfUnderline
|| lf
.lfStrikeOut
))
2205 int underlinePos
, strikeoutPos
;
2206 int underlineWidth
, strikeoutWidth
;
2207 UINT size
= GetOutlineTextMetricsW(hdc
, 0, NULL
);
2208 OUTLINETEXTMETRICW
* otm
= NULL
;
2213 underlineWidth
= tm
.tmAscent
/ 20 + 1;
2214 strikeoutPos
= tm
.tmAscent
/ 2;
2215 strikeoutWidth
= underlineWidth
;
2219 otm
= HeapAlloc(GetProcessHeap(), 0, size
);
2220 GetOutlineTextMetricsW(hdc
, size
, otm
);
2221 underlinePos
= otm
->otmsUnderscorePosition
;
2222 underlineWidth
= otm
->otmsUnderscoreSize
;
2223 strikeoutPos
= otm
->otmsStrikeoutPosition
;
2224 strikeoutWidth
= otm
->otmsStrikeoutSize
;
2225 HeapFree(GetProcessHeap(), 0, otm
);
2228 if (PATH_IsPathOpen(dc
->path
))
2232 HBRUSH hbrush
= CreateSolidBrush(GetTextColor(hdc
));
2234 hbrush
= SelectObject(hdc
, hbrush
);
2235 hpen
= SelectObject(hdc
, GetStockObject(NULL_PEN
));
2239 pts
[0].x
= x
- underlinePos
* sinEsc
;
2240 pts
[0].y
= y
- underlinePos
* cosEsc
;
2241 pts
[1].x
= x
+ xwidth
- underlinePos
* sinEsc
;
2242 pts
[1].y
= y
- ywidth
- underlinePos
* cosEsc
;
2243 pts
[2].x
= pts
[1].x
+ underlineWidth
* sinEsc
;
2244 pts
[2].y
= pts
[1].y
+ underlineWidth
* cosEsc
;
2245 pts
[3].x
= pts
[0].x
+ underlineWidth
* sinEsc
;
2246 pts
[3].y
= pts
[0].y
+ underlineWidth
* cosEsc
;
2247 pts
[4].x
= pts
[0].x
;
2248 pts
[4].y
= pts
[0].y
;
2249 DPtoLP(hdc
, pts
, 5);
2250 Polygon(hdc
, pts
, 5);
2255 pts
[0].x
= x
- strikeoutPos
* sinEsc
;
2256 pts
[0].y
= y
- strikeoutPos
* cosEsc
;
2257 pts
[1].x
= x
+ xwidth
- strikeoutPos
* sinEsc
;
2258 pts
[1].y
= y
- ywidth
- strikeoutPos
* cosEsc
;
2259 pts
[2].x
= pts
[1].x
+ strikeoutWidth
* sinEsc
;
2260 pts
[2].y
= pts
[1].y
+ strikeoutWidth
* cosEsc
;
2261 pts
[3].x
= pts
[0].x
+ strikeoutWidth
* sinEsc
;
2262 pts
[3].y
= pts
[0].y
+ strikeoutWidth
* cosEsc
;
2263 pts
[4].x
= pts
[0].x
;
2264 pts
[4].y
= pts
[0].y
;
2265 DPtoLP(hdc
, pts
, 5);
2266 Polygon(hdc
, pts
, 5);
2269 SelectObject(hdc
, hpen
);
2270 hbrush
= SelectObject(hdc
, hbrush
);
2271 DeleteObject(hbrush
);
2275 POINT pts
[2], oldpt
;
2280 hpen
= CreatePen(PS_SOLID
, underlineWidth
, GetTextColor(hdc
));
2281 hpen
= SelectObject(hdc
, hpen
);
2284 pts
[1].x
= x
+ xwidth
;
2285 pts
[1].y
= y
- ywidth
;
2286 DPtoLP(hdc
, pts
, 2);
2287 MoveToEx(hdc
, pts
[0].x
- underlinePos
* sinEsc
, pts
[0].y
- underlinePos
* cosEsc
, &oldpt
);
2288 LineTo(hdc
, pts
[1].x
- underlinePos
* sinEsc
, pts
[1].y
- underlinePos
* cosEsc
);
2289 MoveToEx(hdc
, oldpt
.x
, oldpt
.y
, NULL
);
2290 DeleteObject(SelectObject(hdc
, hpen
));
2295 hpen
= CreatePen(PS_SOLID
, strikeoutWidth
, GetTextColor(hdc
));
2296 hpen
= SelectObject(hdc
, hpen
);
2299 pts
[1].x
= x
+ xwidth
;
2300 pts
[1].y
= y
- ywidth
;
2301 DPtoLP(hdc
, pts
, 2);
2302 MoveToEx(hdc
, pts
[0].x
- strikeoutPos
* sinEsc
, pts
[0].y
- strikeoutPos
* cosEsc
, &oldpt
);
2303 LineTo(hdc
, pts
[1].x
- strikeoutPos
* sinEsc
, pts
[1].y
- strikeoutPos
* cosEsc
);
2304 MoveToEx(hdc
, oldpt
.x
, oldpt
.y
, NULL
);
2305 DeleteObject(SelectObject(hdc
, hpen
));
2314 /***********************************************************************
2315 * TextOutA (GDI32.@)
2317 BOOL WINAPI
TextOutA( HDC hdc
, INT x
, INT y
, LPCSTR str
, INT count
)
2319 return ExtTextOutA( hdc
, x
, y
, 0, NULL
, str
, count
, NULL
);
2323 /***********************************************************************
2324 * TextOutW (GDI32.@)
2326 BOOL WINAPI
TextOutW(HDC hdc
, INT x
, INT y
, LPCWSTR str
, INT count
)
2328 return ExtTextOutW( hdc
, x
, y
, 0, NULL
, str
, count
, NULL
);
2332 /***********************************************************************
2333 * PolyTextOutA (GDI32.@)
2337 BOOL WINAPI
PolyTextOutA( HDC hdc
, const POLYTEXTA
*pptxt
, INT cStrings
)
2339 for (; cStrings
>0; cStrings
--, pptxt
++)
2340 if (!ExtTextOutA( hdc
, pptxt
->x
, pptxt
->y
, pptxt
->uiFlags
, &pptxt
->rcl
, pptxt
->lpstr
, pptxt
->n
, pptxt
->pdx
))
2347 /***********************************************************************
2348 * PolyTextOutW (GDI32.@)
2350 * Draw several Strings
2356 BOOL WINAPI
PolyTextOutW( HDC hdc
, const POLYTEXTW
*pptxt
, INT cStrings
)
2358 for (; cStrings
>0; cStrings
--, pptxt
++)
2359 if (!ExtTextOutW( hdc
, pptxt
->x
, pptxt
->y
, pptxt
->uiFlags
, &pptxt
->rcl
, pptxt
->lpstr
, pptxt
->n
, pptxt
->pdx
))
2365 /* FIXME: all following APIs ******************************************/
2368 /***********************************************************************
2369 * SetMapperFlags (GDI32.@)
2371 DWORD WINAPI
SetMapperFlags( HDC hDC
, DWORD dwFlag
)
2373 DC
*dc
= DC_GetDCPtr( hDC
);
2376 if(dc
->funcs
->pSetMapperFlags
)
2378 ret
= dc
->funcs
->pSetMapperFlags( dc
->physDev
, dwFlag
);
2379 /* FIXME: ret is just a success flag, we should return a proper value */
2382 FIXME("(%p, 0x%08x): stub - harmless\n", hDC
, dwFlag
);
2383 DC_ReleaseDCPtr( dc
);
2387 /***********************************************************************
2388 * GetAspectRatioFilterEx (GDI.486)
2390 BOOL16 WINAPI
GetAspectRatioFilterEx16( HDC16 hdc
, LPSIZE16 pAspectRatio
)
2392 FIXME("(%04x, %p): -- Empty Stub !\n", hdc
, pAspectRatio
);
2396 /***********************************************************************
2397 * GetAspectRatioFilterEx (GDI32.@)
2399 BOOL WINAPI
GetAspectRatioFilterEx( HDC hdc
, LPSIZE pAspectRatio
)
2401 FIXME("(%p, %p): -- Empty Stub !\n", hdc
, pAspectRatio
);
2406 /***********************************************************************
2407 * GetCharABCWidthsA (GDI32.@)
2409 * See GetCharABCWidthsW.
2411 BOOL WINAPI
GetCharABCWidthsA(HDC hdc
, UINT firstChar
, UINT lastChar
,
2414 INT i
, wlen
, count
= (INT
)(lastChar
- firstChar
+ 1);
2419 if(count
<= 0) return FALSE
;
2421 str
= HeapAlloc(GetProcessHeap(), 0, count
);
2422 for(i
= 0; i
< count
; i
++)
2423 str
[i
] = (BYTE
)(firstChar
+ i
);
2425 wstr
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
2427 for(i
= 0; i
< wlen
; i
++)
2429 if(!GetCharABCWidthsW(hdc
, wstr
[i
], wstr
[i
], abc
))
2437 HeapFree(GetProcessHeap(), 0, str
);
2438 HeapFree(GetProcessHeap(), 0, wstr
);
2444 /******************************************************************************
2445 * GetCharABCWidthsW [GDI32.@]
2447 * Retrieves widths of characters in range.
2450 * hdc [I] Handle of device context
2451 * firstChar [I] First character in range to query
2452 * lastChar [I] Last character in range to query
2453 * abc [O] Address of character-width structure
2456 * Only works with TrueType fonts
2462 BOOL WINAPI
GetCharABCWidthsW( HDC hdc
, UINT firstChar
, UINT lastChar
,
2465 DC
*dc
= DC_GetDCPtr(hdc
);
2469 if (!dc
) return FALSE
;
2472 ret
= WineEngGetCharABCWidths( dc
->gdiFont
, firstChar
, lastChar
, abc
);
2478 /* convert device units to logical */
2479 for( i
= firstChar
; i
<= lastChar
; i
++, abc
++ ) {
2480 abc
->abcA
= INTERNAL_XDSTOWS(dc
, abc
->abcA
);
2481 abc
->abcB
= INTERNAL_XDSTOWS(dc
, abc
->abcB
);
2482 abc
->abcC
= INTERNAL_XDSTOWS(dc
, abc
->abcC
);
2487 DC_ReleaseDCPtr( dc
);
2492 /******************************************************************************
2493 * GetCharABCWidthsI [GDI32.@]
2495 * Retrieves widths of characters in range.
2498 * hdc [I] Handle of device context
2499 * firstChar [I] First glyphs in range to query
2500 * count [I] Last glyphs in range to query
2501 * pgi [i] Array of glyphs to query
2502 * abc [O] Address of character-width structure
2505 * Only works with TrueType fonts
2511 BOOL WINAPI
GetCharABCWidthsI( HDC hdc
, UINT firstChar
, UINT count
,
2512 LPWORD pgi
, LPABC abc
)
2514 DC
*dc
= DC_GetDCPtr(hdc
);
2518 if (!dc
) return FALSE
;
2521 ret
= WineEngGetCharABCWidthsI( dc
->gdiFont
, firstChar
, count
, pgi
, abc
);
2527 /* convert device units to logical */
2528 for( i
= 0; i
< count
; i
++, abc
++ ) {
2529 abc
->abcA
= INTERNAL_XDSTOWS(dc
, abc
->abcA
);
2530 abc
->abcB
= INTERNAL_XDSTOWS(dc
, abc
->abcB
);
2531 abc
->abcC
= INTERNAL_XDSTOWS(dc
, abc
->abcC
);
2536 DC_ReleaseDCPtr( dc
);
2541 /***********************************************************************
2542 * GetGlyphOutlineA (GDI32.@)
2544 DWORD WINAPI
GetGlyphOutlineA( HDC hdc
, UINT uChar
, UINT fuFormat
,
2545 LPGLYPHMETRICS lpgm
, DWORD cbBuffer
,
2546 LPVOID lpBuffer
, const MAT2
*lpmat2
)
2552 if(!(fuFormat
& GGO_GLYPH_INDEX
)) {
2555 if(uChar
> 0xff) { /* but, 2 bytes character only */
2557 mbchs
[0] = (uChar
& 0xff00) >> 8;
2558 mbchs
[1] = (uChar
& 0xff);
2561 mbchs
[0] = (uChar
& 0xff);
2563 p
= FONT_mbtowc(hdc
, mbchs
, len
, NULL
, NULL
);
2567 ret
= GetGlyphOutlineW(hdc
, c
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
,
2569 HeapFree(GetProcessHeap(), 0, p
);
2573 /***********************************************************************
2574 * GetGlyphOutlineW (GDI32.@)
2576 DWORD WINAPI
GetGlyphOutlineW( HDC hdc
, UINT uChar
, UINT fuFormat
,
2577 LPGLYPHMETRICS lpgm
, DWORD cbBuffer
,
2578 LPVOID lpBuffer
, const MAT2
*lpmat2
)
2580 DC
*dc
= DC_GetDCPtr(hdc
);
2583 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2584 hdc
, uChar
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
, lpmat2
);
2586 if(!dc
) return GDI_ERROR
;
2589 ret
= WineEngGetGlyphOutline(dc
->gdiFont
, uChar
, fuFormat
, lpgm
,
2590 cbBuffer
, lpBuffer
, lpmat2
);
2594 DC_ReleaseDCPtr( dc
);
2599 /***********************************************************************
2600 * CreateScalableFontResourceA (GDI32.@)
2602 BOOL WINAPI
CreateScalableFontResourceA( DWORD fHidden
,
2603 LPCSTR lpszResourceFile
,
2604 LPCSTR lpszFontFile
,
2605 LPCSTR lpszCurrentPath
)
2609 /* fHidden=1 - only visible for the calling app, read-only, not
2610 * enumbered with EnumFonts/EnumFontFamilies
2611 * lpszCurrentPath can be NULL
2613 FIXME("(%d,%s,%s,%s): stub\n",
2614 fHidden
, debugstr_a(lpszResourceFile
), debugstr_a(lpszFontFile
),
2615 debugstr_a(lpszCurrentPath
) );
2617 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2618 if ((f
= CreateFileA(lpszResourceFile
, 0, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, 0)) != INVALID_HANDLE_VALUE
) {
2620 SetLastError(ERROR_FILE_EXISTS
);
2623 return FALSE
; /* create failed */
2626 /***********************************************************************
2627 * CreateScalableFontResourceW (GDI32.@)
2629 BOOL WINAPI
CreateScalableFontResourceW( DWORD fHidden
,
2630 LPCWSTR lpszResourceFile
,
2631 LPCWSTR lpszFontFile
,
2632 LPCWSTR lpszCurrentPath
)
2634 FIXME("(%d,%p,%p,%p): stub\n",
2635 fHidden
, lpszResourceFile
, lpszFontFile
, lpszCurrentPath
);
2636 return FALSE
; /* create failed */
2639 /*************************************************************************
2640 * GetKerningPairsA (GDI32.@)
2642 DWORD WINAPI
GetKerningPairsA( HDC hDC
, DWORD cPairs
,
2643 LPKERNINGPAIR kern_pairA
)
2648 DWORD i
, total_kern_pairs
, kern_pairs_copied
= 0;
2649 KERNINGPAIR
*kern_pairW
;
2651 if (!cPairs
&& kern_pairA
)
2653 SetLastError(ERROR_INVALID_PARAMETER
);
2657 charset
= GetTextCharset(hDC
);
2658 if (!TranslateCharsetInfo(ULongToPtr(charset
), &csi
, TCI_SRCCHARSET
))
2660 FIXME("Can't find codepage for charset %d\n", charset
);
2663 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2664 * to fail on an invalid character for CP_SYMBOL.
2666 cpi
.DefaultChar
[0] = 0;
2667 if (csi
.ciACP
!= CP_SYMBOL
&& !GetCPInfo(csi
.ciACP
, &cpi
))
2669 FIXME("Can't find codepage %u info\n", csi
.ciACP
);
2672 TRACE("charset %d => codepage %u\n", charset
, csi
.ciACP
);
2674 total_kern_pairs
= GetKerningPairsW(hDC
, 0, NULL
);
2675 if (!total_kern_pairs
) return 0;
2677 kern_pairW
= HeapAlloc(GetProcessHeap(), 0, total_kern_pairs
* sizeof(*kern_pairW
));
2678 GetKerningPairsW(hDC
, total_kern_pairs
, kern_pairW
);
2680 for (i
= 0; i
< total_kern_pairs
; i
++)
2684 if (!WideCharToMultiByte(csi
.ciACP
, 0, &kern_pairW
[i
].wFirst
, 1, &first
, 1, NULL
, NULL
))
2687 if (!WideCharToMultiByte(csi
.ciACP
, 0, &kern_pairW
[i
].wSecond
, 1, &second
, 1, NULL
, NULL
))
2690 if (first
== cpi
.DefaultChar
[0] || second
== cpi
.DefaultChar
[0])
2695 if (kern_pairs_copied
>= cPairs
) break;
2697 kern_pairA
->wFirst
= (BYTE
)first
;
2698 kern_pairA
->wSecond
= (BYTE
)second
;
2699 kern_pairA
->iKernAmount
= kern_pairW
[i
].iKernAmount
;
2702 kern_pairs_copied
++;
2705 HeapFree(GetProcessHeap(), 0, kern_pairW
);
2707 return kern_pairs_copied
;
2710 /*************************************************************************
2711 * GetKerningPairsW (GDI32.@)
2713 DWORD WINAPI
GetKerningPairsW( HDC hDC
, DWORD cPairs
,
2714 LPKERNINGPAIR lpKerningPairs
)
2719 TRACE("(%p,%d,%p)\n", hDC
, cPairs
, lpKerningPairs
);
2721 if (!cPairs
&& lpKerningPairs
)
2723 SetLastError(ERROR_INVALID_PARAMETER
);
2727 dc
= DC_GetDCPtr(hDC
);
2731 ret
= WineEngGetKerningPairs(dc
->gdiFont
, cPairs
, lpKerningPairs
);
2733 DC_ReleaseDCPtr( dc
);
2737 /*************************************************************************
2738 * TranslateCharsetInfo [GDI32.@]
2740 * Fills a CHARSETINFO structure for a character set, code page, or
2741 * font. This allows making the correspondance between different labelings
2742 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2743 * of the same encoding.
2745 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2746 * only one codepage should be set in *lpSrc.
2749 * TRUE on success, FALSE on failure.
2752 BOOL WINAPI
TranslateCharsetInfo(
2753 LPDWORD lpSrc
, /* [in]
2754 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2755 if flags == TCI_SRCCHARSET: a character set value
2756 if flags == TCI_SRCCODEPAGE: a code page value
2758 LPCHARSETINFO lpCs
, /* [out] structure to receive charset information */
2759 DWORD flags
/* [in] determines interpretation of lpSrc */)
2763 case TCI_SRCFONTSIG
:
2764 while (!(*lpSrc
>>index
& 0x0001) && index
<MAXTCIINDEX
) index
++;
2766 case TCI_SRCCODEPAGE
:
2767 while (PtrToUlong(lpSrc
) != FONT_tci
[index
].ciACP
&& index
< MAXTCIINDEX
) index
++;
2769 case TCI_SRCCHARSET
:
2770 while (PtrToUlong(lpSrc
) != FONT_tci
[index
].ciCharset
&& index
< MAXTCIINDEX
) index
++;
2775 if (index
>= MAXTCIINDEX
|| FONT_tci
[index
].ciCharset
== DEFAULT_CHARSET
) return FALSE
;
2776 memcpy(lpCs
, &FONT_tci
[index
], sizeof(CHARSETINFO
));
2780 /*************************************************************************
2781 * GetFontLanguageInfo (GDI32.@)
2783 DWORD WINAPI
GetFontLanguageInfo(HDC hdc
)
2785 FONTSIGNATURE fontsig
;
2786 static const DWORD GCP_DBCS_MASK
=0x003F0000,
2787 GCP_DIACRITIC_MASK
=0x00000000,
2788 FLI_GLYPHS_MASK
=0x00000000,
2789 GCP_GLYPHSHAPE_MASK
=0x00000040,
2790 GCP_KASHIDA_MASK
=0x00000000,
2791 GCP_LIGATE_MASK
=0x00000000,
2792 GCP_USEKERNING_MASK
=0x00000000,
2793 GCP_REORDER_MASK
=0x00000060;
2797 GetTextCharsetInfo( hdc
, &fontsig
, 0 );
2798 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2800 if( (fontsig
.fsCsb
[0]&GCP_DBCS_MASK
)!=0 )
2803 if( (fontsig
.fsCsb
[0]&GCP_DIACRITIC_MASK
)!=0 )
2804 result
|=GCP_DIACRITIC
;
2806 if( (fontsig
.fsCsb
[0]&FLI_GLYPHS_MASK
)!=0 )
2809 if( (fontsig
.fsCsb
[0]&GCP_GLYPHSHAPE_MASK
)!=0 )
2810 result
|=GCP_GLYPHSHAPE
;
2812 if( (fontsig
.fsCsb
[0]&GCP_KASHIDA_MASK
)!=0 )
2813 result
|=GCP_KASHIDA
;
2815 if( (fontsig
.fsCsb
[0]&GCP_LIGATE_MASK
)!=0 )
2818 if( (fontsig
.fsCsb
[0]&GCP_USEKERNING_MASK
)!=0 )
2819 result
|=GCP_USEKERNING
;
2821 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2822 if( GetTextAlign( hdc
) & TA_RTLREADING
)
2823 if( (fontsig
.fsCsb
[0]&GCP_REORDER_MASK
)!=0 )
2824 result
|=GCP_REORDER
;
2830 /*************************************************************************
2831 * GetFontData [GDI32.@]
2833 * Retrieve data for TrueType font.
2837 * success: Number of bytes returned
2838 * failure: GDI_ERROR
2842 * Calls SetLastError()
2845 DWORD WINAPI
GetFontData(HDC hdc
, DWORD table
, DWORD offset
,
2846 LPVOID buffer
, DWORD length
)
2848 DC
*dc
= DC_GetDCPtr(hdc
);
2849 DWORD ret
= GDI_ERROR
;
2851 if(!dc
) return GDI_ERROR
;
2854 ret
= WineEngGetFontData(dc
->gdiFont
, table
, offset
, buffer
, length
);
2856 DC_ReleaseDCPtr( dc
);
2860 /*************************************************************************
2861 * GetGlyphIndicesA [GDI32.@]
2863 DWORD WINAPI
GetGlyphIndicesA(HDC hdc
, LPCSTR lpstr
, INT count
,
2864 LPWORD pgi
, DWORD flags
)
2870 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2871 hdc
, debugstr_an(lpstr
, count
), count
, pgi
, flags
);
2873 lpstrW
= FONT_mbtowc(hdc
, lpstr
, count
, &countW
, NULL
);
2874 ret
= GetGlyphIndicesW(hdc
, lpstrW
, countW
, pgi
, flags
);
2875 HeapFree(GetProcessHeap(), 0, lpstrW
);
2880 /*************************************************************************
2881 * GetGlyphIndicesW [GDI32.@]
2883 DWORD WINAPI
GetGlyphIndicesW(HDC hdc
, LPCWSTR lpstr
, INT count
,
2884 LPWORD pgi
, DWORD flags
)
2886 DC
*dc
= DC_GetDCPtr(hdc
);
2887 DWORD ret
= GDI_ERROR
;
2889 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2890 hdc
, debugstr_wn(lpstr
, count
), count
, pgi
, flags
);
2892 if(!dc
) return GDI_ERROR
;
2895 ret
= WineEngGetGlyphIndices(dc
->gdiFont
, lpstr
, count
, pgi
, flags
);
2897 DC_ReleaseDCPtr( dc
);
2901 /*************************************************************************
2902 * GetCharacterPlacementA [GDI32.@]
2904 * See GetCharacterPlacementW.
2907 * the web browser control of ie4 calls this with dwFlags=0
2910 GetCharacterPlacementA(HDC hdc
, LPCSTR lpString
, INT uCount
,
2911 INT nMaxExtent
, GCP_RESULTSA
*lpResults
,
2916 GCP_RESULTSW resultsW
;
2920 TRACE("%s, %d, %d, 0x%08x\n",
2921 debugstr_an(lpString
, uCount
), uCount
, nMaxExtent
, dwFlags
);
2923 /* both structs are equal in size */
2924 memcpy(&resultsW
, lpResults
, sizeof(resultsW
));
2926 lpStringW
= FONT_mbtowc(hdc
, lpString
, uCount
, &uCountW
, &font_cp
);
2927 if(lpResults
->lpOutString
)
2928 resultsW
.lpOutString
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*uCountW
);
2930 ret
= GetCharacterPlacementW(hdc
, lpStringW
, uCountW
, nMaxExtent
, &resultsW
, dwFlags
);
2932 lpResults
->nGlyphs
= resultsW
.nGlyphs
;
2933 lpResults
->nMaxFit
= resultsW
.nMaxFit
;
2935 if(lpResults
->lpOutString
) {
2936 WideCharToMultiByte(font_cp
, 0, resultsW
.lpOutString
, uCountW
,
2937 lpResults
->lpOutString
, uCount
, NULL
, NULL
);
2940 HeapFree(GetProcessHeap(), 0, lpStringW
);
2941 HeapFree(GetProcessHeap(), 0, resultsW
.lpOutString
);
2946 /*************************************************************************
2947 * GetCharacterPlacementW [GDI32.@]
2949 * Retrieve information about a string. This includes the width, reordering,
2950 * Glyphing and so on.
2954 * The width and height of the string if successful, 0 if failed.
2958 * All flags except GCP_REORDER are not yet implemented.
2959 * Reordering is not 100% complient to the Windows BiDi method.
2960 * Caret positioning is not yet implemented for BiDi.
2961 * Classes are not yet implemented.
2965 GetCharacterPlacementW(
2966 HDC hdc
, /* [in] Device context for which the rendering is to be done */
2967 LPCWSTR lpString
, /* [in] The string for which information is to be returned */
2968 INT uCount
, /* [in] Number of WORDS in string. */
2969 INT nMaxExtent
, /* [in] Maximum extent the string is to take (in HDC logical units) */
2970 GCP_RESULTSW
*lpResults
,/* [in/out] A pointer to a GCP_RESULTSW struct */
2971 DWORD dwFlags
/* [in] Flags specifying how to process the string */
2978 TRACE("%s, %d, %d, 0x%08x\n",
2979 debugstr_wn(lpString
, uCount
), uCount
, nMaxExtent
, dwFlags
);
2981 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2982 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2983 lpResults
->lStructSize
, lpResults
->lpOutString
, lpResults
->lpOrder
,
2984 lpResults
->lpDx
, lpResults
->lpCaretPos
, lpResults
->lpClass
,
2985 lpResults
->lpGlyphs
, lpResults
->nGlyphs
, lpResults
->nMaxFit
);
2987 if(dwFlags
&(~GCP_REORDER
)) FIXME("flags 0x%08x ignored\n", dwFlags
);
2988 if(lpResults
->lpClass
) FIXME("classes not implemented\n");
2989 if (lpResults
->lpCaretPos
&& (dwFlags
& GCP_REORDER
))
2990 FIXME("Caret positions for complex scripts not implemented\n");
2992 nSet
= (UINT
)uCount
;
2993 if(nSet
> lpResults
->nGlyphs
)
2994 nSet
= lpResults
->nGlyphs
;
2996 /* return number of initialized fields */
2997 lpResults
->nGlyphs
= nSet
;
2999 if((dwFlags
&GCP_REORDER
)==0 || !BidiAvail
)
3001 /* Treat the case where no special handling was requested in a fastpath way */
3002 /* copy will do if the GCP_REORDER flag is not set */
3003 if(lpResults
->lpOutString
)
3004 memcpy( lpResults
->lpOutString
, lpString
, nSet
* sizeof(WCHAR
));
3006 if(lpResults
->lpOrder
)
3008 for(i
= 0; i
< nSet
; i
++)
3009 lpResults
->lpOrder
[i
] = i
;
3013 BIDI_Reorder( lpString
, uCount
, dwFlags
, WINE_GCPW_FORCE_LTR
, lpResults
->lpOutString
,
3014 nSet
, lpResults
->lpOrder
);
3017 /* FIXME: Will use the placement chars */
3018 if (lpResults
->lpDx
)
3021 for (i
= 0; i
< nSet
; i
++)
3023 if (GetCharWidth32W(hdc
, lpString
[i
], lpString
[i
], &c
))
3024 lpResults
->lpDx
[i
]= c
;
3028 if (lpResults
->lpCaretPos
&& !(dwFlags
& GCP_REORDER
))
3032 lpResults
->lpCaretPos
[0] = 0;
3033 for (i
= 1; i
< nSet
; i
++)
3034 if (GetTextExtentPoint32W(hdc
, &(lpString
[i
- 1]), 1, &size
))
3035 lpResults
->lpCaretPos
[i
] = (pos
+= size
.cx
);
3038 if(lpResults
->lpGlyphs
)
3039 GetGlyphIndicesW(hdc
, lpString
, nSet
, lpResults
->lpGlyphs
, 0);
3041 if (GetTextExtentPoint32W(hdc
, lpString
, uCount
, &size
))
3042 ret
= MAKELONG(size
.cx
, size
.cy
);
3047 /*************************************************************************
3048 * GetCharABCWidthsFloatA [GDI32.@]
3050 * See GetCharABCWidthsFloatW.
3052 BOOL WINAPI
GetCharABCWidthsFloatA( HDC hdc
, UINT first
, UINT last
, LPABCFLOAT abcf
)
3054 INT i
, wlen
, count
= (INT
)(last
- first
+ 1);
3059 if (count
<= 0) return FALSE
;
3061 str
= HeapAlloc(GetProcessHeap(), 0, count
);
3063 for(i
= 0; i
< count
; i
++)
3064 str
[i
] = (BYTE
)(first
+ i
);
3066 wstr
= FONT_mbtowc( hdc
, str
, count
, &wlen
, NULL
);
3068 for (i
= 0; i
< wlen
; i
++)
3070 if (!GetCharABCWidthsFloatW( hdc
, wstr
[i
], wstr
[i
], abcf
))
3078 HeapFree( GetProcessHeap(), 0, str
);
3079 HeapFree( GetProcessHeap(), 0, wstr
);
3084 /*************************************************************************
3085 * GetCharABCWidthsFloatW [GDI32.@]
3087 * Retrieves widths of a range of characters.
3090 * hdc [I] Handle to device context.
3091 * first [I] First character in range to query.
3092 * last [I] Last character in range to query.
3093 * abcf [O] Array of LPABCFLOAT structures.
3100 * Only works with TrueType fonts. It also doesn't return real
3101 * floats but converted integers because it's implemented on
3102 * top of GetCharABCWidthsW.
3104 BOOL WINAPI
GetCharABCWidthsFloatW( HDC hdc
, UINT first
, UINT last
, LPABCFLOAT abcf
)
3107 unsigned int i
, size
= sizeof(ABC
) * (last
- first
+ 1);
3110 TRACE("%p, %d, %d, %p - partial stub\n", hdc
, first
, last
, abcf
);
3112 abc
= HeapAlloc( GetProcessHeap(), 0, size
);
3113 if (!abc
) return FALSE
;
3115 ret
= GetCharABCWidthsW( hdc
, first
, last
, abc
);
3118 for (i
= first
; i
<= last
; i
++, abc
++, abcf
++)
3120 abcf
->abcfA
= abc
->abcA
;
3121 abcf
->abcfB
= abc
->abcB
;
3122 abcf
->abcfC
= abc
->abcC
;
3125 HeapFree( GetProcessHeap(), 0, abc
);
3129 /*************************************************************************
3130 * GetCharWidthFloatA [GDI32.@]
3132 BOOL WINAPI
GetCharWidthFloatA(HDC hdc
, UINT iFirstChar
,
3133 UINT iLastChar
, PFLOAT pxBuffer
)
3135 FIXME("%p, %u, %u, %p: stub!\n", hdc
, iFirstChar
, iLastChar
, pxBuffer
);
3139 /*************************************************************************
3140 * GetCharWidthFloatW [GDI32.@]
3142 BOOL WINAPI
GetCharWidthFloatW(HDC hdc
, UINT iFirstChar
,
3143 UINT iLastChar
, PFLOAT pxBuffer
)
3145 FIXME("%p, %u, %u, %p: stub!\n", hdc
, iFirstChar
, iLastChar
, pxBuffer
);
3150 /***********************************************************************
3152 * Font Resource API *
3154 ***********************************************************************/
3156 /***********************************************************************
3157 * AddFontResourceA (GDI32.@)
3159 INT WINAPI
AddFontResourceA( LPCSTR str
)
3161 return AddFontResourceExA( str
, 0, NULL
);
3164 /***********************************************************************
3165 * AddFontResourceW (GDI32.@)
3167 INT WINAPI
AddFontResourceW( LPCWSTR str
)
3169 return AddFontResourceExW(str
, 0, NULL
);
3173 /***********************************************************************
3174 * AddFontResourceExA (GDI32.@)
3176 INT WINAPI
AddFontResourceExA( LPCSTR str
, DWORD fl
, PVOID pdv
)
3178 DWORD len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
3179 LPWSTR strW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3182 MultiByteToWideChar(CP_ACP
, 0, str
, -1, strW
, len
);
3183 ret
= AddFontResourceExW(strW
, fl
, pdv
);
3184 HeapFree(GetProcessHeap(), 0, strW
);
3188 static BOOL CALLBACK
load_enumed_resource(HMODULE hModule
, LPCWSTR type
, LPWSTR name
, LONG_PTR lParam
)
3190 HRSRC rsrc
= FindResourceW(hModule
, name
, type
);
3191 HGLOBAL hMem
= LoadResource(hModule
, rsrc
);
3192 LPVOID
*pMem
= LockResource(hMem
);
3193 int *num_total
= (int *)lParam
;
3196 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type
));
3197 if (!AddFontMemResourceEx(pMem
, SizeofResource(hModule
, rsrc
), NULL
, &num_in_res
))
3199 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule
, hMem
);
3203 *num_total
+= num_in_res
;
3207 /***********************************************************************
3208 * AddFontResourceExW (GDI32.@)
3210 INT WINAPI
AddFontResourceExW( LPCWSTR str
, DWORD fl
, PVOID pdv
)
3212 int ret
= WineEngAddFontResourceEx(str
, fl
, pdv
);
3215 /* Freetype <2.3.5 have problems reading resources wrapped in PE files. */
3216 HMODULE hModule
= LoadLibraryExW(str
, NULL
, LOAD_LIBRARY_AS_DATAFILE
);
3217 if (hModule
!= NULL
)
3219 int num_resources
= 0;
3220 LPWSTR rt_font
= (LPWSTR
)((ULONG_PTR
)8); /* we don't want to include winuser.h */
3222 TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manualy\n",
3223 wine_dbgstr_w(str
));
3224 if (EnumResourceNamesW(hModule
, rt_font
, load_enumed_resource
, (LONG_PTR
)&num_resources
))
3225 ret
= num_resources
;
3226 FreeLibrary(hModule
);
3232 /***********************************************************************
3233 * RemoveFontResourceA (GDI32.@)
3235 BOOL WINAPI
RemoveFontResourceA( LPCSTR str
)
3237 return RemoveFontResourceExA(str
, 0, 0);
3240 /***********************************************************************
3241 * RemoveFontResourceW (GDI32.@)
3243 BOOL WINAPI
RemoveFontResourceW( LPCWSTR str
)
3245 return RemoveFontResourceExW(str
, 0, 0);
3248 /***********************************************************************
3249 * AddFontMemResourceEx (GDI32.@)
3251 HANDLE WINAPI
AddFontMemResourceEx( PVOID pbFont
, DWORD cbFont
, PVOID pdv
, DWORD
*pcFonts
)
3253 return WineEngAddFontMemResourceEx(pbFont
, cbFont
, pdv
, pcFonts
);
3256 /***********************************************************************
3257 * RemoveFontResourceExA (GDI32.@)
3259 BOOL WINAPI
RemoveFontResourceExA( LPCSTR str
, DWORD fl
, PVOID pdv
)
3261 DWORD len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
3262 LPWSTR strW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3265 MultiByteToWideChar(CP_ACP
, 0, str
, -1, strW
, len
);
3266 ret
= RemoveFontResourceExW(strW
, fl
, pdv
);
3267 HeapFree(GetProcessHeap(), 0, strW
);
3271 /***********************************************************************
3272 * RemoveFontResourceExW (GDI32.@)
3274 BOOL WINAPI
RemoveFontResourceExW( LPCWSTR str
, DWORD fl
, PVOID pdv
)
3276 return WineEngRemoveFontResourceEx(str
, fl
, pdv
);
3279 /***********************************************************************
3280 * GetTextCharset (GDI32.@)
3282 UINT WINAPI
GetTextCharset(HDC hdc
)
3284 /* MSDN docs say this is equivalent */
3285 return GetTextCharsetInfo(hdc
, NULL
, 0);
3288 /***********************************************************************
3289 * GetTextCharsetInfo (GDI32.@)
3291 UINT WINAPI
GetTextCharsetInfo(HDC hdc
, LPFONTSIGNATURE fs
, DWORD flags
)
3293 UINT ret
= DEFAULT_CHARSET
;
3294 DC
*dc
= DC_GetDCPtr(hdc
);
3299 ret
= WineEngGetTextCharsetInfo(dc
->gdiFont
, fs
, flags
);
3301 DC_ReleaseDCPtr( dc
);
3304 if (ret
== DEFAULT_CHARSET
&& fs
)
3305 memset(fs
, 0, sizeof(FONTSIGNATURE
));
3309 /***********************************************************************
3310 * GdiGetCharDimensions (GDI32.@)
3312 * Gets the average width of the characters in the English alphabet.
3315 * hdc [I] Handle to the device context to measure on.
3316 * lptm [O] Pointer to memory to store the text metrics into.
3317 * height [O] On exit, the maximum height of characters in the English alphabet.
3320 * The average width of characters in the English alphabet.
3323 * This function is used by the dialog manager to get the size of a dialog
3324 * unit. It should also be used by other pieces of code that need to know
3325 * the size of a dialog unit in logical units without having access to the
3326 * window handle of the dialog.
3327 * Windows caches the font metrics from this function, but we don't and
3328 * there doesn't appear to be an immediate advantage to do so.
3331 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3333 LONG WINAPI
GdiGetCharDimensions(HDC hdc
, LPTEXTMETRICW lptm
, LONG
*height
)
3336 static const WCHAR alphabet
[] = {
3337 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3338 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3339 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3341 if(lptm
&& !GetTextMetricsW(hdc
, lptm
)) return 0;
3343 if(!GetTextExtentPointW(hdc
, alphabet
, 52, &sz
)) return 0;
3345 if (height
) *height
= sz
.cy
;
3346 return (sz
.cx
/ 26 + 1) / 2;
3349 BOOL WINAPI
EnableEUDC(BOOL fEnableEUDC
)
3351 FIXME("(%d): stub\n", fEnableEUDC
);
3355 /***********************************************************************
3356 * GetCharWidthI (GDI32.@)
3358 * Retrieve widths of characters.
3361 * hdc [I] Handle to a device context.
3362 * first [I] First glyph in range to query.
3363 * count [I] Number of glyph indices to query.
3364 * glyphs [I] Array of glyphs to query.
3365 * buffer [O] Buffer to receive character widths.
3368 * Only works with TrueType fonts.
3374 BOOL WINAPI
GetCharWidthI(HDC hdc
, UINT first
, UINT count
, LPWORD glyphs
, LPINT buffer
)
3379 TRACE("(%p, %d, %d, %p, %p)\n", hdc
, first
, count
, glyphs
, buffer
);
3381 if (!(abc
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(ABC
))))
3384 if (!GetCharABCWidthsI(hdc
, first
, count
, glyphs
, abc
))
3386 HeapFree(GetProcessHeap(), 0, abc
);
3390 for (i
= 0; i
< count
; i
++)
3391 buffer
[i
] = abc
->abcA
+ abc
->abcB
+ abc
->abcC
;
3393 HeapFree(GetProcessHeap(), 0, abc
);
3397 /***********************************************************************
3398 * GetFontUnicodeRanges (GDI32.@)
3400 * Retrieve a list of supported Unicode characters in a font.
3403 * hdc [I] Handle to a device context.
3404 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3407 * Success: Number of bytes written to the buffer pointed to by lpgs.
3411 DWORD WINAPI
GetFontUnicodeRanges(HDC hdc
, LPGLYPHSET lpgs
)
3413 return WineEngGetFontUnicodeRanges(hdc
, lpgs
);