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 /***********************************************************************
352 * Returns a Unicode translation of str using the charset of the
353 * currently selected font in hdc. If count is -1 then str is assumed
354 * to be '\0' terminated, otherwise it contains the number of bytes to
355 * convert. If plenW is non-NULL, on return it will point to the
356 * number of WCHARs that have been written. If pCP is non-NULL, on
357 * return it will point to the codepage used in the conversion. The
358 * caller should free the returned LPWSTR from the process heap
361 static LPWSTR
FONT_mbtowc(HDC hdc
, LPCSTR str
, INT count
, INT
*plenW
, UINT
*pCP
)
367 int charset
= GetTextCharset(hdc
);
369 /* Hmm, nicely designed api this one! */
370 if(TranslateCharsetInfo((DWORD
*)charset
, &csi
, TCI_SRCCHARSET
))
377 case DEFAULT_CHARSET
:
388 /* FIXME: These have no place here, but because x11drv
389 enumerates fonts with these (made up) charsets some apps
390 might use them and then the FIXME below would become
391 annoying. Now we could pick the intended codepage for
392 each of these, but since it's broken anyway we'll just
393 use CP_ACP and hope it'll go away...
399 FIXME("Can't find codepage for charset %d\n", charset
);
404 TRACE("charset %d => cp %d\n", charset
, cp
);
406 if(count
== -1) count
= strlen(str
);
407 lenW
= MultiByteToWideChar(cp
, 0, str
, count
, NULL
, 0);
408 strW
= HeapAlloc(GetProcessHeap(), 0, lenW
*sizeof(WCHAR
));
409 MultiByteToWideChar(cp
, 0, str
, count
, strW
, lenW
);
410 TRACE("mapped %s -> %s\n", debugstr_an(str
, count
), debugstr_wn(strW
, lenW
));
411 if(plenW
) *plenW
= lenW
;
417 /***********************************************************************
418 * CreateFontIndirectA (GDI32.@)
420 HFONT WINAPI
CreateFontIndirectA( const LOGFONTA
*plfA
)
425 FONT_LogFontAToW( plfA
, &lfW
);
426 return CreateFontIndirectW( &lfW
);
428 return CreateFontIndirectW( NULL
);
432 /***********************************************************************
433 * CreateFontIndirectW (GDI32.@)
435 HFONT WINAPI
CreateFontIndirectW( const LOGFONTW
*plf
)
442 if ((fontPtr
= GDI_AllocObject( sizeof(FONTOBJ
), FONT_MAGIC
,
443 (HGDIOBJ
*)&hFont
, &font_funcs
)))
445 static const WCHAR ItalicW
[] = {' ','I','t','a','l','i','c','\0'};
446 static const WCHAR BoldW
[] = {' ','B','o','l','d','\0'};
447 WCHAR
*pFaceNameItalicSuffix
, *pFaceNameBoldSuffix
;
448 WCHAR
* pFaceNameSuffix
= NULL
;
450 memcpy( &fontPtr
->logfont
, plf
, sizeof(LOGFONTW
) );
452 TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
453 plf
->lfHeight
, plf
->lfWidth
,
454 plf
->lfEscapement
, plf
->lfOrientation
,
455 plf
->lfPitchAndFamily
,
456 plf
->lfOutPrecision
, plf
->lfClipPrecision
,
457 plf
->lfQuality
, plf
->lfCharSet
,
458 debugstr_w(plf
->lfFaceName
),
459 plf
->lfWeight
> 400 ? "Bold" : "",
460 plf
->lfItalic
? "Italic" : "",
461 plf
->lfUnderline
? "Underline" : "", hFont
);
463 if (plf
->lfEscapement
!= plf
->lfOrientation
) {
464 /* this should really depend on whether GM_ADVANCED is set */
465 fontPtr
->logfont
.lfOrientation
= fontPtr
->logfont
.lfEscapement
;
466 WARN("orientation angle %f set to "
467 "escapement angle %f for new font %p\n",
468 plf
->lfOrientation
/10., plf
->lfEscapement
/10., hFont
);
471 pFaceNameItalicSuffix
= strstrW(fontPtr
->logfont
.lfFaceName
, ItalicW
);
472 if (pFaceNameItalicSuffix
) {
473 fontPtr
->logfont
.lfItalic
= TRUE
;
474 pFaceNameSuffix
= pFaceNameItalicSuffix
;
477 pFaceNameBoldSuffix
= strstrW(fontPtr
->logfont
.lfFaceName
, BoldW
);
478 if (pFaceNameBoldSuffix
) {
479 if (fontPtr
->logfont
.lfWeight
< FW_BOLD
) {
480 fontPtr
->logfont
.lfWeight
= FW_BOLD
;
482 if (!pFaceNameSuffix
||
483 (pFaceNameBoldSuffix
< pFaceNameSuffix
)) {
484 pFaceNameSuffix
= pFaceNameBoldSuffix
;
488 if (pFaceNameSuffix
) *pFaceNameSuffix
= 0;
490 GDI_ReleaseObj( hFont
);
493 else WARN("(NULL) => NULL\n");
498 /*************************************************************************
499 * CreateFontA (GDI32.@)
501 HFONT WINAPI
CreateFontA( INT height
, INT width
, INT esc
,
502 INT orient
, INT weight
, DWORD italic
,
503 DWORD underline
, DWORD strikeout
, DWORD charset
,
504 DWORD outpres
, DWORD clippres
, DWORD quality
,
505 DWORD pitch
, LPCSTR name
)
509 logfont
.lfHeight
= height
;
510 logfont
.lfWidth
= width
;
511 logfont
.lfEscapement
= esc
;
512 logfont
.lfOrientation
= orient
;
513 logfont
.lfWeight
= weight
;
514 logfont
.lfItalic
= italic
;
515 logfont
.lfUnderline
= underline
;
516 logfont
.lfStrikeOut
= strikeout
;
517 logfont
.lfCharSet
= charset
;
518 logfont
.lfOutPrecision
= outpres
;
519 logfont
.lfClipPrecision
= clippres
;
520 logfont
.lfQuality
= quality
;
521 logfont
.lfPitchAndFamily
= pitch
;
524 lstrcpynA(logfont
.lfFaceName
,name
,sizeof(logfont
.lfFaceName
));
526 logfont
.lfFaceName
[0] = '\0';
528 return CreateFontIndirectA( &logfont
);
531 /*************************************************************************
532 * CreateFontW (GDI32.@)
534 HFONT WINAPI
CreateFontW( INT height
, INT width
, INT esc
,
535 INT orient
, INT weight
, DWORD italic
,
536 DWORD underline
, DWORD strikeout
, DWORD charset
,
537 DWORD outpres
, DWORD clippres
, DWORD quality
,
538 DWORD pitch
, LPCWSTR name
)
542 logfont
.lfHeight
= height
;
543 logfont
.lfWidth
= width
;
544 logfont
.lfEscapement
= esc
;
545 logfont
.lfOrientation
= orient
;
546 logfont
.lfWeight
= weight
;
547 logfont
.lfItalic
= italic
;
548 logfont
.lfUnderline
= underline
;
549 logfont
.lfStrikeOut
= strikeout
;
550 logfont
.lfCharSet
= charset
;
551 logfont
.lfOutPrecision
= outpres
;
552 logfont
.lfClipPrecision
= clippres
;
553 logfont
.lfQuality
= quality
;
554 logfont
.lfPitchAndFamily
= pitch
;
557 lstrcpynW(logfont
.lfFaceName
, name
,
558 sizeof(logfont
.lfFaceName
) / sizeof(WCHAR
));
560 logfont
.lfFaceName
[0] = '\0';
562 return CreateFontIndirectW( &logfont
);
566 /***********************************************************************
569 * If the driver supports vector fonts we create a gdi font first and
570 * then call the driver to give it a chance to supply its own device
571 * font. If the driver wants to do this it returns TRUE and we can
572 * delete the gdi font, if the driver wants to use the gdi font it
573 * should return FALSE, to signal an error return GDI_ERROR. For
574 * drivers that don't support vector fonts they must supply their own
577 static HGDIOBJ
FONT_SelectObject( HGDIOBJ handle
, void *obj
, HDC hdc
)
580 DC
*dc
= DC_GetDCPtr( hdc
);
584 if (dc
->hFont
!= handle
|| dc
->gdiFont
== NULL
)
586 if(GetDeviceCaps(dc
->hSelf
, TEXTCAPS
) & TC_VA_ABLE
)
587 dc
->gdiFont
= WineEngCreateFontInstance(dc
, handle
);
590 if (dc
->funcs
->pSelectFont
) ret
= dc
->funcs
->pSelectFont( dc
->physDev
, handle
, dc
->gdiFont
);
592 if (ret
&& dc
->gdiFont
) dc
->gdiFont
= 0;
594 if (ret
== HGDI_ERROR
)
595 ret
= 0; /* SelectObject returns 0 on error */
601 GDI_ReleaseObj( hdc
);
606 /***********************************************************************
609 static INT
FONT_GetObject16( HGDIOBJ handle
, void *obj
, INT count
, LPVOID buffer
)
614 FONT_LogFontWTo16( &font
->logfont
, &lf16
);
616 if (count
> sizeof(LOGFONT16
)) count
= sizeof(LOGFONT16
);
617 memcpy( buffer
, &lf16
, count
);
621 /***********************************************************************
624 static INT
FONT_GetObjectA( HGDIOBJ handle
, void *obj
, INT count
, LPVOID buffer
)
631 FONT_LogFontWToA( &font
->logfont
, &lfA
);
633 if (count
> sizeof(lfA
)) count
= sizeof(lfA
);
634 memcpy( buffer
, &lfA
, count
);
638 /***********************************************************************
641 static INT
FONT_GetObjectW( HGDIOBJ handle
, void *obj
, INT count
, LPVOID buffer
)
645 return sizeof(LOGFONTW
);
646 if (count
> sizeof(LOGFONTW
)) count
= sizeof(LOGFONTW
);
647 memcpy( buffer
, &font
->logfont
, count
);
652 /***********************************************************************
655 static BOOL
FONT_DeleteObject( HGDIOBJ handle
, void *obj
)
657 WineEngDestroyFontInstance( handle
);
658 return GDI_FreeObject( handle
, obj
);
662 /***********************************************************************
663 * FONT_EnumInstance16
665 * Called by the device driver layer to pass font info
666 * down to the application.
668 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
669 * We have to use other types because of the FONTENUMPROCW definition.
671 static INT CALLBACK
FONT_EnumInstance16( const LOGFONTW
*plf
, const TEXTMETRICW
*ptm
,
672 DWORD fType
, LPARAM lp
)
674 fontEnum16
*pfe
= (fontEnum16
*)lp
;
678 if( pfe
->lpLogFontParam
->lfCharSet
== DEFAULT_CHARSET
||
679 pfe
->lpLogFontParam
->lfCharSet
== plf
->lfCharSet
)
684 FONT_EnumLogFontExWTo16((const ENUMLOGFONTEXW
*)plf
, pfe
->lpLogFont
);
685 FONT_NewTextMetricExWTo16((const NEWTEXTMETRICEXW
*)ptm
, pfe
->lpTextMetric
);
686 pfe
->dwFlags
|= ENUM_CALLED
;
687 GDI_ReleaseObj( pfe
->hdc
); /* release the GDI lock */
689 args
[6] = SELECTOROF(pfe
->segLogFont
);
690 args
[5] = OFFSETOF(pfe
->segLogFont
);
691 args
[4] = SELECTOROF(pfe
->segTextMetric
);
692 args
[3] = OFFSETOF(pfe
->segTextMetric
);
694 args
[1] = HIWORD(pfe
->lpData
);
695 args
[0] = LOWORD(pfe
->lpData
);
696 WOWCallback16Ex( (DWORD
)pfe
->lpEnumFunc
, WCB16_PASCAL
, sizeof(args
), args
, &result
);
697 ret
= LOWORD(result
);
699 /* get the lock again and make sure the DC is still valid */
700 dc
= DC_GetDCPtr( pfe
->hdc
);
701 if (!dc
|| dc
!= pfe
->dc
|| dc
->physDev
!= pfe
->physDev
)
703 if (dc
) GDI_ReleaseObj( pfe
->hdc
);
704 pfe
->hdc
= 0; /* make sure we don't try to release it later on */
711 /***********************************************************************
714 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
715 * We have to use other types because of the FONTENUMPROCW definition.
717 static INT CALLBACK
FONT_EnumInstance( const LOGFONTW
*plf
, const TEXTMETRICW
*ptm
,
718 DWORD fType
, LPARAM lp
)
720 fontEnum32
*pfe
= (fontEnum32
*)lp
;
724 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
725 if((pfe
->lpLogFontParam
->lfCharSet
== DEFAULT_CHARSET
||
726 pfe
->lpLogFontParam
->lfCharSet
== plf
->lfCharSet
) &&
727 (!(fType
& RASTER_FONTTYPE
) || GetDeviceCaps(pfe
->hdc
, TEXTCAPS
) & TC_RA_ABLE
) )
729 /* convert font metrics */
730 ENUMLOGFONTEXA logfont
;
731 NEWTEXTMETRICEXA tmA
;
733 pfe
->dwFlags
|= ENUM_CALLED
;
734 if (!(pfe
->dwFlags
& ENUM_UNICODE
))
736 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW
*)plf
, &logfont
);
737 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW
*)ptm
, &tmA
);
738 plf
= (LOGFONTW
*)&logfont
.elfLogFont
;
739 ptm
= (TEXTMETRICW
*)&tmA
;
741 GDI_ReleaseObj( pfe
->hdc
); /* release the GDI lock */
743 ret
= pfe
->lpEnumFunc( plf
, ptm
, fType
, pfe
->lpData
);
745 /* get the lock again and make sure the DC is still valid */
746 dc
= DC_GetDCPtr( pfe
->hdc
);
747 if (!dc
|| dc
!= pfe
->dc
|| dc
->physDev
!= pfe
->physDev
)
749 if (dc
) GDI_ReleaseObj( pfe
->hdc
);
750 pfe
->hdc
= 0; /* make sure we don't try to release it later on */
757 /***********************************************************************
758 * EnumFontFamiliesEx (GDI.613)
760 INT16 WINAPI
EnumFontFamiliesEx16( HDC16 hDC
, LPLOGFONT16 plf
,
761 FONTENUMPROC16 efproc
, LPARAM lParam
,
766 DC
* dc
= DC_GetDCPtr( HDC_32(hDC
) );
767 NEWTEXTMETRICEX16 tm16
;
768 ENUMLOGFONTEX16 lf16
;
773 FONT_LogFont16ToW(plf
, &lfW
);
775 fe16
.hdc
= HDC_32(hDC
);
777 fe16
.physDev
= dc
->physDev
;
778 fe16
.lpLogFontParam
= plf
;
779 fe16
.lpEnumFunc
= efproc
;
780 fe16
.lpData
= lParam
;
781 fe16
.lpTextMetric
= &tm16
;
782 fe16
.lpLogFont
= &lf16
;
783 fe16
.segTextMetric
= MapLS( &tm16
);
784 fe16
.segLogFont
= MapLS( &lf16
);
787 enum_gdi_fonts
= GetDeviceCaps(fe16
.hdc
, TEXTCAPS
) & TC_VA_ABLE
;
789 if (!dc
->funcs
->pEnumDeviceFonts
&& !enum_gdi_fonts
)
796 ret
= WineEngEnumFonts( &lfW
, FONT_EnumInstance16
, (LPARAM
)&fe16
);
797 fe16
.dwFlags
&= ~ENUM_CALLED
;
798 if (ret
&& dc
->funcs
->pEnumDeviceFonts
) {
799 ret2
= dc
->funcs
->pEnumDeviceFonts( dc
->physDev
, &lfW
, FONT_EnumInstance16
, (LPARAM
)&fe16
);
800 if(fe16
.dwFlags
& ENUM_CALLED
) /* update ret iff a font gets enumed */
804 UnMapLS( fe16
.segTextMetric
);
805 UnMapLS( fe16
.segLogFont
);
806 if (fe16
.hdc
) GDI_ReleaseObj( fe16
.hdc
);
810 /***********************************************************************
811 * FONT_EnumFontFamiliesEx
813 static INT
FONT_EnumFontFamiliesEx( HDC hDC
, LPLOGFONTW plf
,
814 FONTENUMPROCW efproc
,
815 LPARAM lParam
, DWORD dwUnicode
)
818 DC
*dc
= DC_GetDCPtr( hDC
);
824 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf
->lfFaceName
),
826 fe32
.lpLogFontParam
= plf
;
827 fe32
.lpEnumFunc
= efproc
;
828 fe32
.lpData
= lParam
;
829 fe32
.dwFlags
= dwUnicode
;
832 fe32
.physDev
= dc
->physDev
;
834 enum_gdi_fonts
= GetDeviceCaps(hDC
, TEXTCAPS
) & TC_VA_ABLE
;
836 if (!dc
->funcs
->pEnumDeviceFonts
&& !enum_gdi_fonts
)
843 ret
= WineEngEnumFonts( plf
, FONT_EnumInstance
, (LPARAM
)&fe32
);
844 fe32
.dwFlags
&= ~ENUM_CALLED
;
845 if (ret
&& dc
->funcs
->pEnumDeviceFonts
) {
846 ret2
= dc
->funcs
->pEnumDeviceFonts( dc
->physDev
, plf
, FONT_EnumInstance
, (LPARAM
)&fe32
);
847 if(fe32
.dwFlags
& ENUM_CALLED
) /* update ret iff a font gets enumed */
851 if (fe32
.hdc
) GDI_ReleaseObj( fe32
.hdc
);
855 /***********************************************************************
856 * EnumFontFamiliesExW (GDI32.@)
858 INT WINAPI
EnumFontFamiliesExW( HDC hDC
, LPLOGFONTW plf
,
859 FONTENUMPROCW efproc
,
860 LPARAM lParam
, DWORD dwFlags
)
862 return FONT_EnumFontFamiliesEx( hDC
, plf
, efproc
, lParam
, ENUM_UNICODE
);
865 /***********************************************************************
866 * EnumFontFamiliesExA (GDI32.@)
868 INT WINAPI
EnumFontFamiliesExA( HDC hDC
, LPLOGFONTA plf
,
869 FONTENUMPROCA efproc
,
870 LPARAM lParam
, DWORD dwFlags
)
873 FONT_LogFontAToW( plf
, &lfW
);
875 return FONT_EnumFontFamiliesEx( hDC
, &lfW
, (FONTENUMPROCW
)efproc
, lParam
, 0);
878 /***********************************************************************
879 * EnumFontFamilies (GDI.330)
881 INT16 WINAPI
EnumFontFamilies16( HDC16 hDC
, LPCSTR lpFamily
,
882 FONTENUMPROC16 efproc
, LPARAM lpData
)
886 lf
.lfCharSet
= DEFAULT_CHARSET
;
889 if (!*lpFamily
) return 1;
890 lstrcpynA( lf
.lfFaceName
, lpFamily
, LF_FACESIZE
);
892 else lf
.lfFaceName
[0] = '\0';
894 return EnumFontFamiliesEx16( hDC
, &lf
, efproc
, lpData
, 0 );
897 /***********************************************************************
898 * EnumFontFamiliesA (GDI32.@)
900 INT WINAPI
EnumFontFamiliesA( HDC hDC
, LPCSTR lpFamily
,
901 FONTENUMPROCA efproc
, LPARAM lpData
)
905 lf
.lfCharSet
= DEFAULT_CHARSET
;
908 if (!*lpFamily
) return 1;
909 lstrcpynA( lf
.lfFaceName
, lpFamily
, LF_FACESIZE
);
911 else lf
.lfFaceName
[0] = lf
.lfFaceName
[1] = '\0';
913 return EnumFontFamiliesExA( hDC
, &lf
, efproc
, lpData
, 0 );
916 /***********************************************************************
917 * EnumFontFamiliesW (GDI32.@)
919 INT WINAPI
EnumFontFamiliesW( HDC hDC
, LPCWSTR lpFamily
,
920 FONTENUMPROCW efproc
, LPARAM lpData
)
924 lf
.lfCharSet
= DEFAULT_CHARSET
;
927 if (!*lpFamily
) return 1;
928 lstrcpynW( lf
.lfFaceName
, lpFamily
, LF_FACESIZE
);
930 else lf
.lfFaceName
[0] = 0;
932 return EnumFontFamiliesExW( hDC
, &lf
, efproc
, lpData
, 0 );
935 /***********************************************************************
938 INT16 WINAPI
EnumFonts16( HDC16 hDC
, LPCSTR lpName
, FONTENUMPROC16 efproc
,
941 return EnumFontFamilies16( hDC
, lpName
, efproc
, lpData
);
944 /***********************************************************************
945 * EnumFontsA (GDI32.@)
947 INT WINAPI
EnumFontsA( HDC hDC
, LPCSTR lpName
, FONTENUMPROCA efproc
,
950 return EnumFontFamiliesA( hDC
, lpName
, efproc
, lpData
);
953 /***********************************************************************
954 * EnumFontsW (GDI32.@)
956 INT WINAPI
EnumFontsW( HDC hDC
, LPCWSTR lpName
, FONTENUMPROCW efproc
,
959 return EnumFontFamiliesW( hDC
, lpName
, efproc
, lpData
);
963 /***********************************************************************
964 * GetTextCharacterExtra (GDI32.@)
966 INT WINAPI
GetTextCharacterExtra( HDC hdc
)
969 DC
*dc
= DC_GetDCPtr( hdc
);
970 if (!dc
) return 0x80000000;
972 GDI_ReleaseObj( hdc
);
977 /***********************************************************************
978 * SetTextCharacterExtra (GDI32.@)
980 INT WINAPI
SetTextCharacterExtra( HDC hdc
, INT extra
)
983 DC
* dc
= DC_GetDCPtr( hdc
);
984 if (!dc
) return 0x80000000;
985 if (dc
->funcs
->pSetTextCharacterExtra
)
986 prev
= dc
->funcs
->pSetTextCharacterExtra( dc
->physDev
, extra
);
989 prev
= dc
->charExtra
;
990 dc
->charExtra
= extra
;
992 GDI_ReleaseObj( hdc
);
997 /***********************************************************************
998 * SetTextJustification (GDI32.@)
1000 BOOL WINAPI
SetTextJustification( HDC hdc
, INT extra
, INT breaks
)
1003 DC
* dc
= DC_GetDCPtr( hdc
);
1004 if (!dc
) return FALSE
;
1005 if (dc
->funcs
->pSetTextJustification
)
1006 ret
= dc
->funcs
->pSetTextJustification( dc
->physDev
, extra
, breaks
);
1009 extra
= abs((extra
* dc
->vportExtX
+ dc
->wndExtX
/ 2) / dc
->wndExtX
);
1010 if (!extra
) breaks
= 0;
1013 dc
->breakExtra
= extra
/ breaks
;
1014 dc
->breakRem
= extra
- (breaks
* dc
->breakExtra
);
1022 GDI_ReleaseObj( hdc
);
1027 /***********************************************************************
1028 * GetTextFaceA (GDI32.@)
1030 INT WINAPI
GetTextFaceA( HDC hdc
, INT count
, LPSTR name
)
1032 INT res
= GetTextFaceW(hdc
, 0, NULL
);
1033 LPWSTR nameW
= HeapAlloc( GetProcessHeap(), 0, res
* 2 );
1034 GetTextFaceW( hdc
, res
, nameW
);
1038 if (count
&& !WideCharToMultiByte( CP_ACP
, 0, nameW
, -1, name
, count
, NULL
, NULL
))
1043 res
= WideCharToMultiByte( CP_ACP
, 0, nameW
, -1, NULL
, 0, NULL
, NULL
);
1044 HeapFree( GetProcessHeap(), 0, nameW
);
1048 /***********************************************************************
1049 * GetTextFaceW (GDI32.@)
1051 INT WINAPI
GetTextFaceW( HDC hdc
, INT count
, LPWSTR name
)
1056 DC
* dc
= DC_GetDCPtr( hdc
);
1060 ret
= WineEngGetTextFace(dc
->gdiFont
, count
, name
);
1061 else if ((font
= (FONTOBJ
*) GDI_GetObjPtr( dc
->hFont
, FONT_MAGIC
)))
1065 lstrcpynW( name
, font
->logfont
.lfFaceName
, count
);
1066 ret
= strlenW(name
);
1068 else ret
= strlenW(font
->logfont
.lfFaceName
) + 1;
1069 GDI_ReleaseObj( dc
->hFont
);
1071 GDI_ReleaseObj( hdc
);
1076 /***********************************************************************
1077 * GetTextExtentPoint32A (GDI32.@)
1079 * See GetTextExtentPoint32W.
1081 BOOL WINAPI
GetTextExtentPoint32A( HDC hdc
, LPCSTR str
, INT count
,
1086 LPWSTR p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
1089 ret
= GetTextExtentPoint32W( hdc
, p
, wlen
, size
);
1090 HeapFree( GetProcessHeap(), 0, p
);
1093 TRACE("(%p %s %d %p): returning %d x %d\n",
1094 hdc
, debugstr_an (str
, count
), count
, size
, size
->cx
, size
->cy
);
1099 /***********************************************************************
1100 * GetTextExtentPoint32W [GDI32.@]
1102 * Computes width/height for a string.
1104 * Computes width and height of the specified string.
1110 BOOL WINAPI
GetTextExtentPoint32W(
1111 HDC hdc
, /* [in] Handle of device context */
1112 LPCWSTR str
, /* [in] Address of text string */
1113 INT count
, /* [in] Number of characters in string */
1114 LPSIZE size
) /* [out] Address of structure for string size */
1116 return GetTextExtentExPointW(hdc
, str
, count
, 0, NULL
, NULL
, size
);
1119 /***********************************************************************
1120 * GetTextExtentPointI [GDI32.@]
1122 * Computes width and height of the array of glyph indices.
1128 BOOL WINAPI
GetTextExtentPointI(
1129 HDC hdc
, /* [in] Handle of device context */
1130 const WORD
*indices
, /* [in] Address of glyph index array */
1131 INT count
, /* [in] Number of glyphs in array */
1132 LPSIZE size
) /* [out] Address of structure for string size */
1135 DC
* dc
= DC_GetDCPtr( hdc
);
1136 if (!dc
) return FALSE
;
1139 ret
= WineEngGetTextExtentPointI(dc
->gdiFont
, indices
, count
, size
);
1140 size
->cx
= abs(INTERNAL_XDSTOWS(dc
, size
->cx
));
1141 size
->cy
= abs(INTERNAL_YDSTOWS(dc
, size
->cy
));
1142 size
->cx
+= count
* dc
->charExtra
;
1144 else if(dc
->funcs
->pGetTextExtentExPoint
) {
1145 FIXME("calling GetTextExtentExPoint\n");
1146 ret
= dc
->funcs
->pGetTextExtentExPoint( dc
->physDev
, (LPCWSTR
)indices
,
1147 count
, 0, NULL
, NULL
, size
);
1150 GDI_ReleaseObj( hdc
);
1152 TRACE("(%p %p %d %p): returning %d x %d\n",
1153 hdc
, indices
, count
, size
, size
->cx
, size
->cy
);
1158 /***********************************************************************
1159 * GetTextExtentPointA (GDI32.@)
1161 BOOL WINAPI
GetTextExtentPointA( HDC hdc
, LPCSTR str
, INT count
,
1164 TRACE("not bug compatible.\n");
1165 return GetTextExtentPoint32A( hdc
, str
, count
, size
);
1168 /***********************************************************************
1169 * GetTextExtentPointW (GDI32.@)
1171 BOOL WINAPI
GetTextExtentPointW( HDC hdc
, LPCWSTR str
, INT count
,
1174 TRACE("not bug compatible.\n");
1175 return GetTextExtentPoint32W( hdc
, str
, count
, size
);
1179 /***********************************************************************
1180 * GetTextExtentExPointA (GDI32.@)
1182 BOOL WINAPI
GetTextExtentExPointA( HDC hdc
, LPCSTR str
, INT count
,
1183 INT maxExt
, LPINT lpnFit
,
1184 LPINT alpDx
, LPSIZE size
)
1192 NULL
== (walpDx
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(INT
))))
1195 p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
1196 ret
= GetTextExtentExPointW( hdc
, p
, wlen
, maxExt
, lpnFit
, walpDx
, size
);
1199 INT n
= lpnFit
? *lpnFit
: wlen
;
1201 for(i
= 0, j
= 0; i
< n
; i
++, j
++)
1203 alpDx
[j
] = walpDx
[i
];
1204 if (IsDBCSLeadByte(str
[j
])) alpDx
[++j
] = walpDx
[i
];
1207 if (lpnFit
) *lpnFit
= WideCharToMultiByte(CP_ACP
,0,p
,*lpnFit
,NULL
,0,NULL
,NULL
);
1208 HeapFree( GetProcessHeap(), 0, p
);
1209 HeapFree( GetProcessHeap(), 0, walpDx
);
1214 /***********************************************************************
1215 * GetTextExtentExPointW (GDI32.@)
1217 * Return the size of the string as it would be if it was output properly by
1220 * This should include
1221 * - Intercharacter spacing
1222 * - justification spacing (not yet done)
1223 * - kerning? see below
1225 * Kerning. Since kerning would be carried out by the rendering code it should
1226 * be done by the driver. However they don't support it yet. Also I am not
1227 * yet persuaded that (certainly under Win95) any kerning is actually done.
1229 * str: According to MSDN this should be null-terminated. That is not true; a
1230 * null will not terminate it early.
1231 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1232 * than count. I have seen it be either the size of the full string or
1233 * 1 less than the size of the full string. I have not seen it bear any
1234 * resemblance to the portion that would fit.
1235 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1236 * trailing intercharacter spacing and any trailing justification.
1239 * Currently we do this by measuring each character etc. We should do it by
1240 * passing the request to the driver, perhaps by extending the
1241 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1242 * thinking about kerning issues and rounding issues in the justification.
1245 BOOL WINAPI
GetTextExtentExPointW( HDC hdc
, LPCWSTR str
, INT count
,
1246 INT maxExt
, LPINT lpnFit
,
1247 LPINT alpDx
, LPSIZE size
)
1255 TRACE("(%p, %s, %d)\n",hdc
,debugstr_wn(str
,count
),maxExt
);
1257 dc
= DC_GetDCPtr(hdc
);
1261 GetTextMetricsW(hdc
, &tm
);
1263 /* If we need to calculate nFit, then we need the partial extents even if
1264 the user hasn't provided us with an array. */
1267 dxs
= alpDx
? alpDx
: HeapAlloc(GetProcessHeap(), 0, count
* sizeof alpDx
[0]);
1270 GDI_ReleaseObj(hdc
);
1271 SetLastError(ERROR_OUTOFMEMORY
);
1279 ret
= WineEngGetTextExtentExPoint(dc
->gdiFont
, str
, count
,
1280 0, NULL
, dxs
, size
);
1281 else if (dc
->funcs
->pGetTextExtentExPoint
)
1282 ret
= dc
->funcs
->pGetTextExtentExPoint(dc
->physDev
, str
, count
,
1283 0, NULL
, dxs
, size
);
1285 /* Perform device size to world size transformations. */
1288 INT extra
= dc
->charExtra
,
1289 breakExtra
= dc
->breakExtra
,
1290 breakRem
= dc
->breakRem
,
1295 for (i
= 0; i
< count
; ++i
)
1297 dxs
[i
] = abs(INTERNAL_XDSTOWS(dc
, dxs
[i
]));
1298 dxs
[i
] += (i
+1) * extra
;
1299 if (count
> 1 && (breakExtra
|| breakRem
) && str
[i
] == tm
.tmBreakChar
)
1301 dxs
[i
] += breakExtra
;
1308 if (dxs
[i
] <= maxExt
)
1311 breakRem
= dc
->breakRem
;
1313 size
->cx
= abs(INTERNAL_XDSTOWS(dc
, size
->cx
));
1314 size
->cy
= abs(INTERNAL_YDSTOWS(dc
, size
->cy
));
1316 if (!dxs
&& count
> 1 && (breakExtra
|| breakRem
))
1318 for (i
= 0; i
< count
; i
++)
1320 if (str
[i
] == tm
.tmBreakChar
)
1322 size
->cx
+= breakExtra
;
1337 HeapFree(GetProcessHeap(), 0, dxs
);
1339 GDI_ReleaseObj( hdc
);
1341 TRACE("returning %d %d x %d\n",nFit
,size
->cx
,size
->cy
);
1345 /***********************************************************************
1346 * GetTextMetricsA (GDI32.@)
1348 BOOL WINAPI
GetTextMetricsA( HDC hdc
, TEXTMETRICA
*metrics
)
1352 if (!GetTextMetricsW( hdc
, &tm32
)) return FALSE
;
1353 FONT_TextMetricWToA( &tm32
, metrics
);
1357 /***********************************************************************
1358 * GetTextMetricsW (GDI32.@)
1360 BOOL WINAPI
GetTextMetricsW( HDC hdc
, TEXTMETRICW
*metrics
)
1363 DC
* dc
= DC_GetDCPtr( hdc
);
1364 if (!dc
) return FALSE
;
1367 ret
= WineEngGetTextMetrics(dc
->gdiFont
, metrics
);
1368 else if (dc
->funcs
->pGetTextMetrics
)
1369 ret
= dc
->funcs
->pGetTextMetrics( dc
->physDev
, metrics
);
1373 /* device layer returns values in device units
1374 * therefore we have to convert them to logical */
1376 metrics
->tmDigitizedAspectX
= GetDeviceCaps(hdc
, LOGPIXELSX
);
1377 metrics
->tmDigitizedAspectY
= GetDeviceCaps(hdc
, LOGPIXELSY
);
1379 #define WDPTOLP(x) ((x<0)? \
1380 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1381 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1382 #define HDPTOLP(y) ((y<0)? \
1383 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1384 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1386 metrics
->tmHeight
= HDPTOLP(metrics
->tmHeight
);
1387 metrics
->tmAscent
= HDPTOLP(metrics
->tmAscent
);
1388 metrics
->tmDescent
= HDPTOLP(metrics
->tmDescent
);
1389 metrics
->tmInternalLeading
= HDPTOLP(metrics
->tmInternalLeading
);
1390 metrics
->tmExternalLeading
= HDPTOLP(metrics
->tmExternalLeading
);
1391 metrics
->tmAveCharWidth
= WDPTOLP(metrics
->tmAveCharWidth
);
1392 metrics
->tmMaxCharWidth
= WDPTOLP(metrics
->tmMaxCharWidth
);
1393 metrics
->tmOverhang
= WDPTOLP(metrics
->tmOverhang
);
1397 TRACE("text metrics:\n"
1398 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1399 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1400 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1401 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1402 " PitchAndFamily = %02x\n"
1403 " --------------------\n"
1404 " InternalLeading = %i\n"
1408 metrics
->tmWeight
, metrics
->tmFirstChar
, metrics
->tmAveCharWidth
,
1409 metrics
->tmItalic
, metrics
->tmLastChar
, metrics
->tmMaxCharWidth
,
1410 metrics
->tmUnderlined
, metrics
->tmDefaultChar
, metrics
->tmOverhang
,
1411 metrics
->tmStruckOut
, metrics
->tmBreakChar
, metrics
->tmCharSet
,
1412 metrics
->tmPitchAndFamily
,
1413 metrics
->tmInternalLeading
,
1416 metrics
->tmHeight
);
1418 GDI_ReleaseObj( hdc
);
1423 /***********************************************************************
1424 * GetOutlineTextMetrics [GDI.308] Gets metrics for TrueType fonts.
1427 * lpOTM should be LPOUTLINETEXTMETRIC
1430 * Success: Non-zero or size of required buffer
1433 UINT16 WINAPI
GetOutlineTextMetrics16(
1434 HDC16 hdc
, /* [in] Handle of device context */
1435 UINT16 cbData
, /* [in] Size of metric data array */
1436 LPOUTLINETEXTMETRIC16 lpOTM
) /* [out] Address of metric data array */
1438 FIXME("(%04x,%04x,%p): stub\n", hdc
,cbData
,lpOTM
);
1443 /***********************************************************************
1444 * GetOutlineTextMetricsA (GDI32.@)
1445 * Gets metrics for TrueType fonts.
1448 * If the supplied buffer isn't big enough Windows partially fills it up to
1449 * its given length and returns that length.
1452 * Success: Non-zero or size of required buffer
1455 UINT WINAPI
GetOutlineTextMetricsA(
1456 HDC hdc
, /* [in] Handle of device context */
1457 UINT cbData
, /* [in] Size of metric data array */
1458 LPOUTLINETEXTMETRICA lpOTM
) /* [out] Address of metric data array */
1460 char buf
[512], *ptr
;
1462 OUTLINETEXTMETRICW
*lpOTMW
= (OUTLINETEXTMETRICW
*)buf
;
1463 OUTLINETEXTMETRICA
*output
= lpOTM
;
1466 if((ret
= GetOutlineTextMetricsW(hdc
, 0, NULL
)) == 0)
1468 if(ret
> sizeof(buf
))
1469 lpOTMW
= HeapAlloc(GetProcessHeap(), 0, ret
);
1470 GetOutlineTextMetricsW(hdc
, ret
, lpOTMW
);
1472 needed
= sizeof(OUTLINETEXTMETRICA
);
1473 if(lpOTMW
->otmpFamilyName
)
1474 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1475 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFamilyName
), -1,
1476 NULL
, 0, NULL
, NULL
);
1477 if(lpOTMW
->otmpFaceName
)
1478 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1479 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFaceName
), -1,
1480 NULL
, 0, NULL
, NULL
);
1481 if(lpOTMW
->otmpStyleName
)
1482 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1483 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpStyleName
), -1,
1484 NULL
, 0, NULL
, NULL
);
1485 if(lpOTMW
->otmpFullName
)
1486 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1487 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFullName
), -1,
1488 NULL
, 0, NULL
, NULL
);
1495 TRACE("needed = %d\n", needed
);
1497 /* Since the supplied buffer isn't big enough, we'll alloc one
1498 that is and memcpy the first cbData bytes into the lpOTM at
1500 output
= HeapAlloc(GetProcessHeap(), 0, needed
);
1502 ret
= output
->otmSize
= min(needed
, cbData
);
1503 FONT_TextMetricWToA( &lpOTMW
->otmTextMetrics
, &output
->otmTextMetrics
);
1504 output
->otmFiller
= 0;
1505 output
->otmPanoseNumber
= lpOTMW
->otmPanoseNumber
;
1506 output
->otmfsSelection
= lpOTMW
->otmfsSelection
;
1507 output
->otmfsType
= lpOTMW
->otmfsType
;
1508 output
->otmsCharSlopeRise
= lpOTMW
->otmsCharSlopeRise
;
1509 output
->otmsCharSlopeRun
= lpOTMW
->otmsCharSlopeRun
;
1510 output
->otmItalicAngle
= lpOTMW
->otmItalicAngle
;
1511 output
->otmEMSquare
= lpOTMW
->otmEMSquare
;
1512 output
->otmAscent
= lpOTMW
->otmAscent
;
1513 output
->otmDescent
= lpOTMW
->otmDescent
;
1514 output
->otmLineGap
= lpOTMW
->otmLineGap
;
1515 output
->otmsCapEmHeight
= lpOTMW
->otmsCapEmHeight
;
1516 output
->otmsXHeight
= lpOTMW
->otmsXHeight
;
1517 output
->otmrcFontBox
= lpOTMW
->otmrcFontBox
;
1518 output
->otmMacAscent
= lpOTMW
->otmMacAscent
;
1519 output
->otmMacDescent
= lpOTMW
->otmMacDescent
;
1520 output
->otmMacLineGap
= lpOTMW
->otmMacLineGap
;
1521 output
->otmusMinimumPPEM
= lpOTMW
->otmusMinimumPPEM
;
1522 output
->otmptSubscriptSize
= lpOTMW
->otmptSubscriptSize
;
1523 output
->otmptSubscriptOffset
= lpOTMW
->otmptSubscriptOffset
;
1524 output
->otmptSuperscriptSize
= lpOTMW
->otmptSuperscriptSize
;
1525 output
->otmptSuperscriptOffset
= lpOTMW
->otmptSuperscriptOffset
;
1526 output
->otmsStrikeoutSize
= lpOTMW
->otmsStrikeoutSize
;
1527 output
->otmsStrikeoutPosition
= lpOTMW
->otmsStrikeoutPosition
;
1528 output
->otmsUnderscoreSize
= lpOTMW
->otmsUnderscoreSize
;
1529 output
->otmsUnderscorePosition
= lpOTMW
->otmsUnderscorePosition
;
1532 ptr
= (char*)(output
+ 1);
1533 left
= needed
- sizeof(*output
);
1535 if(lpOTMW
->otmpFamilyName
) {
1536 output
->otmpFamilyName
= (LPSTR
)(ptr
- (char*)output
);
1537 len
= WideCharToMultiByte(CP_ACP
, 0,
1538 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFamilyName
), -1,
1539 ptr
, left
, NULL
, NULL
);
1543 output
->otmpFamilyName
= 0;
1545 if(lpOTMW
->otmpFaceName
) {
1546 output
->otmpFaceName
= (LPSTR
)(ptr
- (char*)output
);
1547 len
= WideCharToMultiByte(CP_ACP
, 0,
1548 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFaceName
), -1,
1549 ptr
, left
, NULL
, NULL
);
1553 output
->otmpFaceName
= 0;
1555 if(lpOTMW
->otmpStyleName
) {
1556 output
->otmpStyleName
= (LPSTR
)(ptr
- (char*)output
);
1557 len
= WideCharToMultiByte(CP_ACP
, 0,
1558 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpStyleName
), -1,
1559 ptr
, left
, NULL
, NULL
);
1563 output
->otmpStyleName
= 0;
1565 if(lpOTMW
->otmpFullName
) {
1566 output
->otmpFullName
= (LPSTR
)(ptr
- (char*)output
);
1567 len
= WideCharToMultiByte(CP_ACP
, 0,
1568 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFullName
), -1,
1569 ptr
, left
, NULL
, NULL
);
1572 output
->otmpFullName
= 0;
1576 if(output
!= lpOTM
) {
1577 memcpy(lpOTM
, output
, cbData
);
1578 HeapFree(GetProcessHeap(), 0, output
);
1580 /* check if the string offsets really fit into the provided size */
1581 /* FIXME: should we check string length as well? */
1582 /* make sure that we don't read/write beyond the provided buffer */
1583 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFamilyName
) + sizeof(LPSTR
))
1585 if ((UINT_PTR
)lpOTM
->otmpFamilyName
>= lpOTM
->otmSize
)
1586 lpOTM
->otmpFamilyName
= 0; /* doesn't fit */
1589 /* make sure that we don't read/write beyond the provided buffer */
1590 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFaceName
) + sizeof(LPSTR
))
1592 if ((UINT_PTR
)lpOTM
->otmpFaceName
>= lpOTM
->otmSize
)
1593 lpOTM
->otmpFaceName
= 0; /* doesn't fit */
1596 /* make sure that we don't read/write beyond the provided buffer */
1597 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpStyleName
) + sizeof(LPSTR
))
1599 if ((UINT_PTR
)lpOTM
->otmpStyleName
>= lpOTM
->otmSize
)
1600 lpOTM
->otmpStyleName
= 0; /* doesn't fit */
1603 /* make sure that we don't read/write beyond the provided buffer */
1604 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFullName
) + sizeof(LPSTR
))
1606 if ((UINT_PTR
)lpOTM
->otmpFullName
>= lpOTM
->otmSize
)
1607 lpOTM
->otmpFullName
= 0; /* doesn't fit */
1612 if(lpOTMW
!= (OUTLINETEXTMETRICW
*)buf
)
1613 HeapFree(GetProcessHeap(), 0, lpOTMW
);
1619 /***********************************************************************
1620 * GetOutlineTextMetricsW [GDI32.@]
1622 UINT WINAPI
GetOutlineTextMetricsW(
1623 HDC hdc
, /* [in] Handle of device context */
1624 UINT cbData
, /* [in] Size of metric data array */
1625 LPOUTLINETEXTMETRICW lpOTM
) /* [out] Address of metric data array */
1627 DC
*dc
= DC_GetDCPtr( hdc
);
1628 OUTLINETEXTMETRICW
*output
= lpOTM
;
1631 TRACE("(%p,%d,%p)\n", hdc
, cbData
, lpOTM
);
1635 ret
= WineEngGetOutlineTextMetrics(dc
->gdiFont
, cbData
, output
);
1638 output
= HeapAlloc(GetProcessHeap(), 0, ret
);
1639 WineEngGetOutlineTextMetrics(dc
->gdiFont
, ret
, output
);
1642 #define WDPTOLP(x) ((x<0)? \
1643 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1644 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1645 #define HDPTOLP(y) ((y<0)? \
1646 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1647 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1649 output
->otmTextMetrics
.tmHeight
= HDPTOLP(output
->otmTextMetrics
.tmHeight
);
1650 output
->otmTextMetrics
.tmAscent
= HDPTOLP(output
->otmTextMetrics
.tmAscent
);
1651 output
->otmTextMetrics
.tmDescent
= HDPTOLP(output
->otmTextMetrics
.tmDescent
);
1652 output
->otmTextMetrics
.tmInternalLeading
= HDPTOLP(output
->otmTextMetrics
.tmInternalLeading
);
1653 output
->otmTextMetrics
.tmExternalLeading
= HDPTOLP(output
->otmTextMetrics
.tmExternalLeading
);
1654 output
->otmTextMetrics
.tmAveCharWidth
= WDPTOLP(output
->otmTextMetrics
.tmAveCharWidth
);
1655 output
->otmTextMetrics
.tmMaxCharWidth
= WDPTOLP(output
->otmTextMetrics
.tmMaxCharWidth
);
1656 output
->otmTextMetrics
.tmOverhang
= WDPTOLP(output
->otmTextMetrics
.tmOverhang
);
1657 output
->otmAscent
= HDPTOLP(output
->otmAscent
);
1658 output
->otmDescent
= HDPTOLP(output
->otmDescent
);
1659 output
->otmLineGap
= HDPTOLP(output
->otmLineGap
);
1660 output
->otmsCapEmHeight
= HDPTOLP(output
->otmsCapEmHeight
);
1661 output
->otmsXHeight
= HDPTOLP(output
->otmsXHeight
);
1662 output
->otmrcFontBox
.top
= HDPTOLP(output
->otmrcFontBox
.top
);
1663 output
->otmrcFontBox
.bottom
= HDPTOLP(output
->otmrcFontBox
.bottom
);
1664 output
->otmrcFontBox
.left
= WDPTOLP(output
->otmrcFontBox
.left
);
1665 output
->otmrcFontBox
.right
= WDPTOLP(output
->otmrcFontBox
.right
);
1666 output
->otmMacAscent
= HDPTOLP(output
->otmMacAscent
);
1667 output
->otmMacDescent
= HDPTOLP(output
->otmMacDescent
);
1668 output
->otmMacLineGap
= HDPTOLP(output
->otmMacLineGap
);
1669 output
->otmptSubscriptSize
.x
= WDPTOLP(output
->otmptSubscriptSize
.x
);
1670 output
->otmptSubscriptSize
.y
= HDPTOLP(output
->otmptSubscriptSize
.y
);
1671 output
->otmptSubscriptOffset
.x
= WDPTOLP(output
->otmptSubscriptOffset
.x
);
1672 output
->otmptSubscriptOffset
.y
= HDPTOLP(output
->otmptSubscriptOffset
.y
);
1673 output
->otmptSuperscriptSize
.x
= WDPTOLP(output
->otmptSuperscriptSize
.x
);
1674 output
->otmptSuperscriptSize
.y
= HDPTOLP(output
->otmptSuperscriptSize
.y
);
1675 output
->otmptSuperscriptOffset
.x
= WDPTOLP(output
->otmptSuperscriptOffset
.x
);
1676 output
->otmptSuperscriptOffset
.y
= HDPTOLP(output
->otmptSuperscriptOffset
.y
);
1677 output
->otmsStrikeoutSize
= HDPTOLP(output
->otmsStrikeoutSize
);
1678 output
->otmsStrikeoutPosition
= HDPTOLP(output
->otmsStrikeoutPosition
);
1679 output
->otmsUnderscoreSize
= HDPTOLP(output
->otmsUnderscoreSize
);
1680 output
->otmsUnderscorePosition
= HDPTOLP(output
->otmsUnderscorePosition
);
1683 if(output
!= lpOTM
) {
1684 memcpy(lpOTM
, output
, cbData
);
1685 HeapFree(GetProcessHeap(), 0, output
);
1691 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1692 but really this should just be a return 0. */
1694 ret
= sizeof(*lpOTM
);
1699 memset(lpOTM
, 0, ret
);
1700 lpOTM
->otmSize
= sizeof(*lpOTM
);
1701 GetTextMetricsW(hdc
, &lpOTM
->otmTextMetrics
);
1703 Further fill of the structure not implemented,
1704 Needs real values for the structure members
1709 GDI_ReleaseObj(hdc
);
1714 /***********************************************************************
1715 * GetCharWidthW (GDI32.@)
1716 * GetCharWidth32W (GDI32.@)
1718 BOOL WINAPI
GetCharWidth32W( HDC hdc
, UINT firstChar
, UINT lastChar
,
1723 DC
* dc
= DC_GetDCPtr( hdc
);
1724 if (!dc
) return FALSE
;
1727 ret
= WineEngGetCharWidth( dc
->gdiFont
, firstChar
, lastChar
, buffer
);
1728 else if (dc
->funcs
->pGetCharWidth
)
1729 ret
= dc
->funcs
->pGetCharWidth( dc
->physDev
, firstChar
, lastChar
, buffer
);
1733 /* convert device units to logical */
1734 for( i
= firstChar
; i
<= lastChar
; i
++, buffer
++ )
1735 *buffer
= INTERNAL_XDSTOWS(dc
, *buffer
);
1738 GDI_ReleaseObj( hdc
);
1743 /***********************************************************************
1744 * GetCharWidthA (GDI32.@)
1745 * GetCharWidth32A (GDI32.@)
1747 BOOL WINAPI
GetCharWidth32A( HDC hdc
, UINT firstChar
, UINT lastChar
,
1750 INT i
, wlen
, count
= (INT
)(lastChar
- firstChar
+ 1);
1755 if(count
<= 0) return FALSE
;
1757 str
= HeapAlloc(GetProcessHeap(), 0, count
);
1758 for(i
= 0; i
< count
; i
++)
1759 str
[i
] = (BYTE
)(firstChar
+ i
);
1761 wstr
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
1763 for(i
= 0; i
< wlen
; i
++)
1765 if(!GetCharWidth32W(hdc
, wstr
[i
], wstr
[i
], buffer
))
1773 HeapFree(GetProcessHeap(), 0, str
);
1774 HeapFree(GetProcessHeap(), 0, wstr
);
1780 /***********************************************************************
1781 * ExtTextOutA (GDI32.@)
1785 BOOL WINAPI
ExtTextOutA( HDC hdc
, INT x
, INT y
, UINT flags
,
1786 const RECT
*lprect
, LPCSTR str
, UINT count
, const INT
*lpDx
)
1794 if (flags
& ETO_GLYPH_INDEX
)
1795 return ExtTextOutW( hdc
, x
, y
, flags
, lprect
, (LPCWSTR
)str
, count
, lpDx
);
1797 p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, &codepage
);
1800 unsigned int i
= 0, j
= 0;
1802 lpDxW
= HeapAlloc( GetProcessHeap(), 0, wlen
*sizeof(INT
));
1804 if(IsDBCSLeadByteEx(codepage
, str
[i
])) {
1805 lpDxW
[j
++] = lpDx
[i
] + lpDx
[i
+1];
1808 lpDxW
[j
++] = lpDx
[i
];
1814 ret
= ExtTextOutW( hdc
, x
, y
, flags
, lprect
, p
, wlen
, lpDxW
);
1816 HeapFree( GetProcessHeap(), 0, p
);
1817 HeapFree( GetProcessHeap(), 0, lpDxW
);
1822 /***********************************************************************
1823 * ExtTextOutW (GDI32.@)
1825 * Draws text using the currently selected font, background color, and text color.
1829 * x,y [I] coordinates of string
1831 * ETO_GRAYED - undocumented on MSDN
1832 * ETO_OPAQUE - use background color for fill the rectangle
1833 * ETO_CLIPPED - clipping text to the rectangle
1834 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1835 * than encoded characters. Implies ETO_IGNORELANGUAGE
1836 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1837 * Affects BiDi ordering
1838 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1839 * ETO_PDY - unimplemented
1840 * ETO_NUMERICSLATIN - unimplemented always assumed -
1841 * do not translate numbers into locale representations
1842 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1843 * lprect [I] dimensions for clipping or/and opaquing
1844 * str [I] text string
1845 * count [I] number of symbols in string
1846 * lpDx [I] optional parameter with distance between drawing characters
1852 BOOL WINAPI
ExtTextOutW( HDC hdc
, INT x
, INT y
, UINT flags
,
1853 const RECT
*lprect
, LPCWSTR str
, UINT count
, const INT
*lpDx
)
1856 LPWSTR reordered_str
= (LPWSTR
)str
;
1857 WORD
*glyphs
= NULL
;
1858 UINT align
= GetTextAlign( hdc
);
1862 double cosEsc
, sinEsc
;
1863 INT
*deltas
= NULL
, char_extra
;
1866 BOOL done_extents
= FALSE
;
1867 INT width
= 0, xwidth
= 0, ywidth
= 0;
1869 DC
* dc
= DC_GetDCUpdate( hdc
);
1872 if (!dc
) return FALSE
;
1874 breakRem
= dc
->breakRem
;
1876 if (flags
& (ETO_NUMERICSLOCAL
| ETO_NUMERICSLATIN
| ETO_PDY
))
1877 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY unimplemented\n");
1879 if (!dc
->funcs
->pExtTextOut
&& !PATH_IsPathOpen(dc
->path
))
1881 GDI_ReleaseObj( hdc
);
1885 type
= GetObjectType(hdc
);
1886 if(type
== OBJ_METADC
|| type
== OBJ_ENHMETADC
)
1888 ret
= dc
->funcs
->pExtTextOut(dc
->physDev
, x
, y
, flags
, lprect
, str
, count
, lpDx
);
1889 GDI_ReleaseObj( hdc
);
1894 flags
&= ~ETO_CLIPPED
;
1896 if( !(flags
& (ETO_GLYPH_INDEX
| ETO_IGNORELANGUAGE
)) && BidiAvail
&& count
> 0 )
1898 reordered_str
= HeapAlloc(GetProcessHeap(), 0, count
*sizeof(WCHAR
));
1900 BIDI_Reorder( str
, count
, GCP_REORDER
,
1901 ((flags
&ETO_RTLREADING
)!=0 || (GetTextAlign(hdc
)&TA_RTLREADING
)!=0)?
1902 WINE_GCPW_FORCE_RTL
:WINE_GCPW_FORCE_LTR
,
1903 reordered_str
, count
, NULL
);
1905 flags
|= ETO_IGNORELANGUAGE
;
1908 TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc
, x
, y
, flags
,
1909 lprect
, debugstr_wn(str
, count
), count
, lpDx
);
1911 if(flags
& ETO_GLYPH_INDEX
)
1912 glyphs
= reordered_str
;
1915 TRACE("rect: %d,%d - %d,%d\n", lprect
->left
, lprect
->top
, lprect
->right
,
1917 TRACE("align = %x bkmode = %x mapmode = %x\n", align
, GetBkMode(hdc
), GetMapMode(hdc
));
1919 if(align
& TA_UPDATECP
)
1921 GetCurrentPositionEx( hdc
, &pt
);
1926 GetTextMetricsW(hdc
, &tm
);
1927 GetObjectW(GetCurrentObject(hdc
, OBJ_FONT
), sizeof(lf
), &lf
);
1929 if(!(tm
.tmPitchAndFamily
& TMPF_VECTOR
)) /* Non-scalable fonts shouldn't be rotated */
1930 lf
.lfEscapement
= 0;
1932 if(lf
.lfEscapement
!= 0)
1934 cosEsc
= cos(lf
.lfEscapement
* M_PI
/ 1800);
1935 sinEsc
= sin(lf
.lfEscapement
* M_PI
/ 1800);
1943 if(flags
& (ETO_CLIPPED
| ETO_OPAQUE
))
1947 if(flags
& ETO_GLYPH_INDEX
)
1948 GetTextExtentPointI(hdc
, glyphs
, count
, &sz
);
1950 GetTextExtentPointW(hdc
, reordered_str
, count
, &sz
);
1952 done_extents
= TRUE
;
1955 rc
.right
= x
+ sz
.cx
;
1956 rc
.bottom
= y
+ sz
.cy
;
1963 LPtoDP(hdc
, (POINT
*)&rc
, 2);
1965 if(rc
.left
> rc
.right
) {INT tmp
= rc
.left
; rc
.left
= rc
.right
; rc
.right
= tmp
;}
1966 if(rc
.top
> rc
.bottom
) {INT tmp
= rc
.top
; rc
.top
= rc
.bottom
; rc
.bottom
= tmp
;}
1969 if ((flags
& ETO_OPAQUE
) && !PATH_IsPathOpen(dc
->path
))
1970 dc
->funcs
->pExtTextOut(dc
->physDev
, 0, 0, ETO_OPAQUE
, &rc
, NULL
, 0, NULL
);
1980 LPtoDP(hdc
, &pt
, 1);
1984 char_extra
= GetTextCharacterExtra(hdc
);
1985 if(char_extra
|| dc
->breakExtra
|| breakRem
|| lpDx
)
1989 deltas
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(INT
));
1990 for(i
= 0; i
< count
; i
++)
1992 if(lpDx
&& (flags
& ETO_PDY
))
1993 deltas
[i
] = lpDx
[i
*2] + char_extra
;
1995 deltas
[i
] = lpDx
[i
] + char_extra
;
1998 if(flags
& ETO_GLYPH_INDEX
)
1999 GetTextExtentPointI(hdc
, glyphs
+ i
, 1, &tmpsz
);
2001 GetTextExtentPointW(hdc
, reordered_str
+ i
, 1, &tmpsz
);
2003 deltas
[i
] = tmpsz
.cx
;
2006 if (!(flags
& ETO_GLYPH_INDEX
) && (dc
->breakExtra
|| breakRem
) && reordered_str
[i
] == tm
.tmBreakChar
)
2008 deltas
[i
] = deltas
[i
] + dc
->breakExtra
;
2015 deltas
[i
] = INTERNAL_XWSTODS(dc
, deltas
[i
]);
2023 if(flags
& ETO_GLYPH_INDEX
)
2024 GetTextExtentPointI(hdc
, glyphs
, count
, &sz
);
2026 GetTextExtentPointW(hdc
, reordered_str
, count
, &sz
);
2027 done_extents
= TRUE
;
2029 width
= INTERNAL_XWSTODS(dc
, sz
.cx
);
2031 xwidth
= width
* cosEsc
;
2032 ywidth
= width
* sinEsc
;
2034 tm
.tmAscent
= abs(INTERNAL_YWSTODS(dc
, tm
.tmAscent
));
2035 tm
.tmDescent
= abs(INTERNAL_YWSTODS(dc
, tm
.tmDescent
));
2036 switch( align
& (TA_LEFT
| TA_RIGHT
| TA_CENTER
) )
2039 if (align
& TA_UPDATECP
)
2043 DPtoLP(hdc
, &pt
, 1);
2044 MoveToEx(hdc
, pt
.x
, pt
.y
, NULL
);
2056 if (align
& TA_UPDATECP
)
2060 DPtoLP(hdc
, &pt
, 1);
2061 MoveToEx(hdc
, pt
.x
, pt
.y
, NULL
);
2066 switch( align
& (TA_TOP
| TA_BOTTOM
| TA_BASELINE
) )
2069 y
+= tm
.tmAscent
* cosEsc
;
2070 x
+= tm
.tmAscent
* sinEsc
;
2074 y
-= tm
.tmDescent
* cosEsc
;
2075 x
-= tm
.tmDescent
* sinEsc
;
2082 if (GetBkMode(hdc
) != TRANSPARENT
&& !PATH_IsPathOpen(dc
->path
))
2084 if(!((flags
& ETO_CLIPPED
) && (flags
& ETO_OPAQUE
)))
2086 if(!(flags
& ETO_OPAQUE
) || x
< rc
.left
|| x
+ width
>= rc
.right
||
2087 y
- tm
.tmAscent
< rc
.top
|| y
+ tm
.tmDescent
>= rc
.bottom
)
2091 rc
.right
= x
+ width
;
2092 rc
.top
= y
- tm
.tmAscent
;
2093 rc
.bottom
= y
+ tm
.tmDescent
;
2094 dc
->funcs
->pExtTextOut(dc
->physDev
, 0, 0, ETO_OPAQUE
, &rc
, NULL
, 0, NULL
);
2099 if(FontIsLinked(hdc
) && !(flags
& ETO_GLYPH_INDEX
))
2101 HFONT orig_font
= dc
->hFont
, cur_font
;
2103 INT span
= 0, *offsets
= NULL
, i
;
2105 glyphs
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(WORD
));
2106 for(i
= 0; i
< count
; i
++)
2108 WineEngGetLinkedHFont(dc
, reordered_str
[i
], &cur_font
, &glyph
);
2109 if(cur_font
!= dc
->hFont
)
2114 offsets
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(*deltas
));
2119 for(j
= 1; j
< count
; j
++)
2121 GetTextExtentPointW(hdc
, reordered_str
+ j
- 1, 1, &tmpsz
);
2122 offsets
[j
] = offsets
[j
-1] + INTERNAL_XWSTODS(dc
, tmpsz
.cx
);
2127 for(j
= 1; j
< count
; j
++)
2128 offsets
[j
] = offsets
[j
-1] + deltas
[j
];
2133 if (PATH_IsPathOpen(dc
->path
))
2134 ret
= PATH_ExtTextOut(dc
, x
+ offsets
[i
- span
] * cosEsc
, y
- offsets
[i
- span
] * sinEsc
,
2135 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
,
2136 glyphs
, span
, deltas
? deltas
+ i
- span
: NULL
);
2138 dc
->funcs
->pExtTextOut(dc
->physDev
, x
+ offsets
[i
- span
] * cosEsc
, y
- offsets
[i
- span
] * sinEsc
,
2139 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
,
2140 glyphs
, span
, deltas
? deltas
+ i
- span
: NULL
);
2143 SelectObject(hdc
, cur_font
);
2145 glyphs
[span
++] = glyph
;
2149 if (PATH_IsPathOpen(dc
->path
))
2150 ret
= PATH_ExtTextOut(dc
, x
+ (offsets
? offsets
[count
- span
] * cosEsc
: 0),
2151 y
- (offsets
? offsets
[count
- span
] * sinEsc
: 0),
2152 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
,
2153 glyphs
, span
, deltas
? deltas
+ count
- span
: NULL
);
2155 ret
= dc
->funcs
->pExtTextOut(dc
->physDev
, x
+ (offsets
? offsets
[count
- span
] * cosEsc
: 0),
2156 y
- (offsets
? offsets
[count
- span
] * sinEsc
: 0),
2157 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
,
2158 glyphs
, span
, deltas
? deltas
+ count
- span
: NULL
);
2159 SelectObject(hdc
, orig_font
);
2160 HeapFree(GetProcessHeap(), 0, offsets
);
2166 if(!(flags
& ETO_GLYPH_INDEX
) && dc
->gdiFont
)
2168 glyphs
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(WORD
));
2169 GetGlyphIndicesW(hdc
, reordered_str
, count
, glyphs
, 0);
2170 flags
|= ETO_GLYPH_INDEX
;
2173 if (PATH_IsPathOpen(dc
->path
))
2174 ret
= PATH_ExtTextOut(dc
, x
, y
, (flags
& ~ETO_OPAQUE
), &rc
,
2175 glyphs
? glyphs
: reordered_str
, count
, deltas
);
2177 ret
= dc
->funcs
->pExtTextOut(dc
->physDev
, x
, y
, (flags
& ~ETO_OPAQUE
), &rc
,
2178 glyphs
? glyphs
: reordered_str
, count
, deltas
);
2182 HeapFree(GetProcessHeap(), 0, deltas
);
2183 if(glyphs
!= reordered_str
)
2184 HeapFree(GetProcessHeap(), 0, glyphs
);
2185 if(reordered_str
!= str
)
2186 HeapFree(GetProcessHeap(), 0, reordered_str
);
2188 GDI_ReleaseObj( hdc
);
2190 if (ret
&& (lf
.lfUnderline
|| lf
.lfStrikeOut
))
2192 int underlinePos
, strikeoutPos
;
2193 int underlineWidth
, strikeoutWidth
;
2194 UINT size
= GetOutlineTextMetricsW(hdc
, 0, NULL
);
2195 OUTLINETEXTMETRICW
* otm
= NULL
;
2200 underlineWidth
= tm
.tmAscent
/ 20 + 1;
2201 strikeoutPos
= tm
.tmAscent
/ 2;
2202 strikeoutWidth
= underlineWidth
;
2206 otm
= HeapAlloc(GetProcessHeap(), 0, size
);
2207 GetOutlineTextMetricsW(hdc
, size
, otm
);
2208 underlinePos
= otm
->otmsUnderscorePosition
;
2209 underlineWidth
= otm
->otmsUnderscoreSize
;
2210 strikeoutPos
= otm
->otmsStrikeoutPosition
;
2211 strikeoutWidth
= otm
->otmsStrikeoutSize
;
2212 HeapFree(GetProcessHeap(), 0, otm
);
2215 if (PATH_IsPathOpen(dc
->path
))
2219 HBRUSH hbrush
= CreateSolidBrush(GetTextColor(hdc
));
2221 hbrush
= SelectObject(hdc
, hbrush
);
2222 hpen
= SelectObject(hdc
, GetStockObject(NULL_PEN
));
2226 pts
[0].x
= x
- underlinePos
* sinEsc
;
2227 pts
[0].y
= y
- underlinePos
* cosEsc
;
2228 pts
[1].x
= x
+ xwidth
- underlinePos
* sinEsc
;
2229 pts
[1].y
= y
- ywidth
- underlinePos
* cosEsc
;
2230 pts
[2].x
= pts
[1].x
+ underlineWidth
* sinEsc
;
2231 pts
[2].y
= pts
[1].y
+ underlineWidth
* cosEsc
;
2232 pts
[3].x
= pts
[0].x
+ underlineWidth
* sinEsc
;
2233 pts
[3].y
= pts
[0].y
+ underlineWidth
* cosEsc
;
2234 pts
[4].x
= pts
[0].x
;
2235 pts
[4].y
= pts
[0].y
;
2236 DPtoLP(hdc
, pts
, 5);
2237 Polygon(hdc
, pts
, 5);
2242 pts
[0].x
= x
- strikeoutPos
* sinEsc
;
2243 pts
[0].y
= y
- strikeoutPos
* cosEsc
;
2244 pts
[1].x
= x
+ xwidth
- strikeoutPos
* sinEsc
;
2245 pts
[1].y
= y
- ywidth
- strikeoutPos
* cosEsc
;
2246 pts
[2].x
= pts
[1].x
+ strikeoutWidth
* sinEsc
;
2247 pts
[2].y
= pts
[1].y
+ strikeoutWidth
* cosEsc
;
2248 pts
[3].x
= pts
[0].x
+ strikeoutWidth
* sinEsc
;
2249 pts
[3].y
= pts
[0].y
+ strikeoutWidth
* cosEsc
;
2250 pts
[4].x
= pts
[0].x
;
2251 pts
[4].y
= pts
[0].y
;
2252 DPtoLP(hdc
, pts
, 5);
2253 Polygon(hdc
, pts
, 5);
2256 SelectObject(hdc
, hpen
);
2257 hbrush
= SelectObject(hdc
, hbrush
);
2258 DeleteObject(hbrush
);
2262 POINT pts
[2], oldpt
;
2267 hpen
= CreatePen(PS_SOLID
, underlineWidth
, GetTextColor(hdc
));
2268 hpen
= SelectObject(hdc
, hpen
);
2271 pts
[1].x
= x
+ xwidth
;
2272 pts
[1].y
= y
- ywidth
;
2273 DPtoLP(hdc
, pts
, 2);
2274 MoveToEx(hdc
, pts
[0].x
- underlinePos
* sinEsc
, pts
[0].y
- underlinePos
* cosEsc
, &oldpt
);
2275 LineTo(hdc
, pts
[1].x
- underlinePos
* sinEsc
, pts
[1].y
- underlinePos
* cosEsc
);
2276 MoveToEx(hdc
, oldpt
.x
, oldpt
.y
, NULL
);
2277 DeleteObject(SelectObject(hdc
, hpen
));
2282 hpen
= CreatePen(PS_SOLID
, strikeoutWidth
, GetTextColor(hdc
));
2283 hpen
= SelectObject(hdc
, hpen
);
2286 pts
[1].x
= x
+ xwidth
;
2287 pts
[1].y
= y
- ywidth
;
2288 DPtoLP(hdc
, pts
, 2);
2289 MoveToEx(hdc
, pts
[0].x
- strikeoutPos
* sinEsc
, pts
[0].y
- strikeoutPos
* cosEsc
, &oldpt
);
2290 LineTo(hdc
, pts
[1].x
- strikeoutPos
* sinEsc
, pts
[1].y
- strikeoutPos
* cosEsc
);
2291 MoveToEx(hdc
, oldpt
.x
, oldpt
.y
, NULL
);
2292 DeleteObject(SelectObject(hdc
, hpen
));
2301 /***********************************************************************
2302 * TextOutA (GDI32.@)
2304 BOOL WINAPI
TextOutA( HDC hdc
, INT x
, INT y
, LPCSTR str
, INT count
)
2306 return ExtTextOutA( hdc
, x
, y
, 0, NULL
, str
, count
, NULL
);
2310 /***********************************************************************
2311 * TextOutW (GDI32.@)
2313 BOOL WINAPI
TextOutW(HDC hdc
, INT x
, INT y
, LPCWSTR str
, INT count
)
2315 return ExtTextOutW( hdc
, x
, y
, 0, NULL
, str
, count
, NULL
);
2319 /***********************************************************************
2320 * PolyTextOutA (GDI32.@)
2324 BOOL WINAPI
PolyTextOutA ( HDC hdc
, /* [in] Handle to device context */
2325 PPOLYTEXTA pptxt
, /* [in] Array of strings */
2326 INT cStrings
) /* [in] Number of strings in array */
2328 for (; cStrings
>0; cStrings
--, pptxt
++)
2329 if (!ExtTextOutA( hdc
, pptxt
->x
, pptxt
->y
, pptxt
->uiFlags
, &pptxt
->rcl
, pptxt
->lpstr
, pptxt
->n
, pptxt
->pdx
))
2336 /***********************************************************************
2337 * PolyTextOutW (GDI32.@)
2339 * Draw several Strings
2345 BOOL WINAPI
PolyTextOutW ( HDC hdc
, /* [in] Handle to device context */
2346 PPOLYTEXTW pptxt
, /* [in] Array of strings */
2347 INT cStrings
) /* [in] Number of strings in array */
2349 for (; cStrings
>0; cStrings
--, pptxt
++)
2350 if (!ExtTextOutW( hdc
, pptxt
->x
, pptxt
->y
, pptxt
->uiFlags
, &pptxt
->rcl
, pptxt
->lpstr
, pptxt
->n
, pptxt
->pdx
))
2356 /* FIXME: all following APIs ******************************************/
2359 /***********************************************************************
2360 * SetMapperFlags (GDI32.@)
2362 DWORD WINAPI
SetMapperFlags( HDC hDC
, DWORD dwFlag
)
2364 DC
*dc
= DC_GetDCPtr( hDC
);
2367 if(dc
->funcs
->pSetMapperFlags
)
2369 ret
= dc
->funcs
->pSetMapperFlags( dc
->physDev
, dwFlag
);
2370 /* FIXME: ret is just a success flag, we should return a proper value */
2373 FIXME("(%p, 0x%08x): stub - harmless\n", hDC
, dwFlag
);
2374 GDI_ReleaseObj( hDC
);
2378 /***********************************************************************
2379 * GetAspectRatioFilterEx (GDI.486)
2381 BOOL16 WINAPI
GetAspectRatioFilterEx16( HDC16 hdc
, LPSIZE16 pAspectRatio
)
2383 FIXME("(%04x, %p): -- Empty Stub !\n", hdc
, pAspectRatio
);
2387 /***********************************************************************
2388 * GetAspectRatioFilterEx (GDI32.@)
2390 BOOL WINAPI
GetAspectRatioFilterEx( HDC hdc
, LPSIZE pAspectRatio
)
2392 FIXME("(%p, %p): -- Empty Stub !\n", hdc
, pAspectRatio
);
2397 /***********************************************************************
2398 * GetCharABCWidthsA (GDI32.@)
2400 * See GetCharABCWidthsW.
2402 BOOL WINAPI
GetCharABCWidthsA(HDC hdc
, UINT firstChar
, UINT lastChar
,
2405 INT i
, wlen
, count
= (INT
)(lastChar
- firstChar
+ 1);
2410 if(count
<= 0) return FALSE
;
2412 str
= HeapAlloc(GetProcessHeap(), 0, count
);
2413 for(i
= 0; i
< count
; i
++)
2414 str
[i
] = (BYTE
)(firstChar
+ i
);
2416 wstr
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
2418 for(i
= 0; i
< wlen
; i
++)
2420 if(!GetCharABCWidthsW(hdc
, wstr
[i
], wstr
[i
], abc
))
2428 HeapFree(GetProcessHeap(), 0, str
);
2429 HeapFree(GetProcessHeap(), 0, wstr
);
2435 /******************************************************************************
2436 * GetCharABCWidthsW [GDI32.@]
2438 * Retrieves widths of characters in range.
2441 * hdc [I] Handle of device context
2442 * firstChar [I] First character in range to query
2443 * lastChar [I] Last character in range to query
2444 * abc [O] Address of character-width structure
2447 * Only works with TrueType fonts
2453 BOOL WINAPI
GetCharABCWidthsW( HDC hdc
, UINT firstChar
, UINT lastChar
,
2456 DC
*dc
= DC_GetDCPtr(hdc
);
2460 if (!dc
) return FALSE
;
2463 ret
= WineEngGetCharABCWidths( dc
->gdiFont
, firstChar
, lastChar
, abc
);
2469 /* convert device units to logical */
2470 for( i
= firstChar
; i
<= lastChar
; i
++, abc
++ ) {
2471 abc
->abcA
= INTERNAL_XDSTOWS(dc
, abc
->abcA
);
2472 abc
->abcB
= INTERNAL_XDSTOWS(dc
, abc
->abcB
);
2473 abc
->abcC
= INTERNAL_XDSTOWS(dc
, abc
->abcC
);
2478 GDI_ReleaseObj(hdc
);
2483 /******************************************************************************
2484 * GetCharABCWidthsI [GDI32.@]
2486 * Retrieves widths of characters in range.
2489 * hdc [I] Handle of device context
2490 * firstChar [I] First glyphs in range to query
2491 * count [I] Last glyphs in range to query
2492 * pgi [i] Array of glyphs to query
2493 * abc [O] Address of character-width structure
2496 * Only works with TrueType fonts
2502 BOOL WINAPI
GetCharABCWidthsI( HDC hdc
, UINT firstChar
, UINT count
,
2503 LPWORD pgi
, LPABC abc
)
2505 DC
*dc
= DC_GetDCPtr(hdc
);
2509 if (!dc
) return FALSE
;
2512 ret
= WineEngGetCharABCWidthsI( dc
->gdiFont
, firstChar
, count
, pgi
, abc
);
2518 /* convert device units to logical */
2519 for( i
= 0; i
< count
; i
++, abc
++ ) {
2520 abc
->abcA
= INTERNAL_XDSTOWS(dc
, abc
->abcA
);
2521 abc
->abcB
= INTERNAL_XDSTOWS(dc
, abc
->abcB
);
2522 abc
->abcC
= INTERNAL_XDSTOWS(dc
, abc
->abcC
);
2527 GDI_ReleaseObj(hdc
);
2532 /***********************************************************************
2533 * GetGlyphOutlineA (GDI32.@)
2535 DWORD WINAPI
GetGlyphOutlineA( HDC hdc
, UINT uChar
, UINT fuFormat
,
2536 LPGLYPHMETRICS lpgm
, DWORD cbBuffer
,
2537 LPVOID lpBuffer
, const MAT2
*lpmat2
)
2543 if(!(fuFormat
& GGO_GLYPH_INDEX
)) {
2546 if(uChar
> 0xff) { /* but, 2 bytes character only */
2548 mbchs
[0] = (uChar
& 0xff00) >> 8;
2549 mbchs
[1] = (uChar
& 0xff);
2552 mbchs
[0] = (uChar
& 0xff);
2554 p
= FONT_mbtowc(hdc
, mbchs
, len
, NULL
, NULL
);
2558 ret
= GetGlyphOutlineW(hdc
, c
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
,
2560 HeapFree(GetProcessHeap(), 0, p
);
2564 /***********************************************************************
2565 * GetGlyphOutlineW (GDI32.@)
2567 DWORD WINAPI
GetGlyphOutlineW( HDC hdc
, UINT uChar
, UINT fuFormat
,
2568 LPGLYPHMETRICS lpgm
, DWORD cbBuffer
,
2569 LPVOID lpBuffer
, const MAT2
*lpmat2
)
2571 DC
*dc
= DC_GetDCPtr(hdc
);
2574 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2575 hdc
, uChar
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
, lpmat2
);
2577 if(!dc
) return GDI_ERROR
;
2580 ret
= WineEngGetGlyphOutline(dc
->gdiFont
, uChar
, fuFormat
, lpgm
,
2581 cbBuffer
, lpBuffer
, lpmat2
);
2585 GDI_ReleaseObj(hdc
);
2590 /***********************************************************************
2591 * CreateScalableFontResourceA (GDI32.@)
2593 BOOL WINAPI
CreateScalableFontResourceA( DWORD fHidden
,
2594 LPCSTR lpszResourceFile
,
2595 LPCSTR lpszFontFile
,
2596 LPCSTR lpszCurrentPath
)
2600 /* fHidden=1 - only visible for the calling app, read-only, not
2601 * enumbered with EnumFonts/EnumFontFamilies
2602 * lpszCurrentPath can be NULL
2604 FIXME("(%d,%s,%s,%s): stub\n",
2605 fHidden
, debugstr_a(lpszResourceFile
), debugstr_a(lpszFontFile
),
2606 debugstr_a(lpszCurrentPath
) );
2608 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2609 if ((f
= CreateFileA(lpszResourceFile
, 0, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, 0)) != INVALID_HANDLE_VALUE
) {
2611 SetLastError(ERROR_FILE_EXISTS
);
2614 return FALSE
; /* create failed */
2617 /***********************************************************************
2618 * CreateScalableFontResourceW (GDI32.@)
2620 BOOL WINAPI
CreateScalableFontResourceW( DWORD fHidden
,
2621 LPCWSTR lpszResourceFile
,
2622 LPCWSTR lpszFontFile
,
2623 LPCWSTR lpszCurrentPath
)
2625 FIXME("(%d,%p,%p,%p): stub\n",
2626 fHidden
, lpszResourceFile
, lpszFontFile
, lpszCurrentPath
);
2627 return FALSE
; /* create failed */
2630 /*************************************************************************
2631 * GetKerningPairsA (GDI32.@)
2633 DWORD WINAPI
GetKerningPairsA( HDC hDC
, DWORD cPairs
,
2634 LPKERNINGPAIR kern_pairA
)
2639 DWORD i
, total_kern_pairs
, kern_pairs_copied
= 0;
2640 KERNINGPAIR
*kern_pairW
;
2642 if (!cPairs
&& kern_pairA
)
2644 SetLastError(ERROR_INVALID_PARAMETER
);
2648 charset
= GetTextCharset(hDC
);
2649 if (!TranslateCharsetInfo((DWORD
*)charset
, &csi
, TCI_SRCCHARSET
))
2651 FIXME("Can't find codepage for charset %d\n", charset
);
2654 if (!GetCPInfo(csi
.ciACP
, &cpi
))
2656 FIXME("Can't find codepage %u info\n", csi
.ciACP
);
2659 TRACE("charset %d => codepage %u\n", charset
, csi
.ciACP
);
2661 total_kern_pairs
= GetKerningPairsW(hDC
, 0, NULL
);
2662 if (!total_kern_pairs
) return 0;
2664 kern_pairW
= HeapAlloc(GetProcessHeap(), 0, total_kern_pairs
* sizeof(*kern_pairW
));
2665 GetKerningPairsW(hDC
, total_kern_pairs
, kern_pairW
);
2667 for (i
= 0; i
< total_kern_pairs
; i
++)
2671 if (!WideCharToMultiByte(csi
.ciACP
, 0, &kern_pairW
[i
].wFirst
, 1, &first
, 1, NULL
, NULL
))
2674 if (!WideCharToMultiByte(csi
.ciACP
, 0, &kern_pairW
[i
].wSecond
, 1, &second
, 1, NULL
, NULL
))
2677 if (first
== cpi
.DefaultChar
[0] || second
== cpi
.DefaultChar
[0])
2682 if (kern_pairs_copied
>= cPairs
) break;
2684 kern_pairA
->wFirst
= (BYTE
)first
;
2685 kern_pairA
->wSecond
= (BYTE
)second
;
2686 kern_pairA
->iKernAmount
= kern_pairW
[i
].iKernAmount
;
2689 kern_pairs_copied
++;
2692 HeapFree(GetProcessHeap(), 0, kern_pairW
);
2694 return kern_pairs_copied
;
2697 /*************************************************************************
2698 * GetKerningPairsW (GDI32.@)
2700 DWORD WINAPI
GetKerningPairsW( HDC hDC
, DWORD cPairs
,
2701 LPKERNINGPAIR lpKerningPairs
)
2706 TRACE("(%p,%d,%p)\n", hDC
, cPairs
, lpKerningPairs
);
2708 if (!cPairs
&& lpKerningPairs
)
2710 SetLastError(ERROR_INVALID_PARAMETER
);
2714 dc
= DC_GetDCPtr(hDC
);
2718 ret
= WineEngGetKerningPairs(dc
->gdiFont
, cPairs
, lpKerningPairs
);
2720 GDI_ReleaseObj(hDC
);
2724 /*************************************************************************
2725 * TranslateCharsetInfo [GDI32.@]
2727 * Fills a CHARSETINFO structure for a character set, code page, or
2728 * font. This allows making the correspondance between different labelings
2729 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2730 * of the same encoding.
2732 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2733 * only one codepage should be set in *lpSrc.
2736 * TRUE on success, FALSE on failure.
2739 BOOL WINAPI
TranslateCharsetInfo(
2740 LPDWORD lpSrc
, /* [in]
2741 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2742 if flags == TCI_SRCCHARSET: a character set value
2743 if flags == TCI_SRCCODEPAGE: a code page value
2745 LPCHARSETINFO lpCs
, /* [out] structure to receive charset information */
2746 DWORD flags
/* [in] determines interpretation of lpSrc */)
2750 case TCI_SRCFONTSIG
:
2751 while (!(*lpSrc
>>index
& 0x0001) && index
<MAXTCIINDEX
) index
++;
2753 case TCI_SRCCODEPAGE
:
2754 while ((UINT
) (lpSrc
) != FONT_tci
[index
].ciACP
&& index
< MAXTCIINDEX
) index
++;
2756 case TCI_SRCCHARSET
:
2757 while ((UINT
) (lpSrc
) != FONT_tci
[index
].ciCharset
&& index
< MAXTCIINDEX
) index
++;
2762 if (index
>= MAXTCIINDEX
|| FONT_tci
[index
].ciCharset
== DEFAULT_CHARSET
) return FALSE
;
2763 memcpy(lpCs
, &FONT_tci
[index
], sizeof(CHARSETINFO
));
2767 /*************************************************************************
2768 * GetFontLanguageInfo (GDI32.@)
2770 DWORD WINAPI
GetFontLanguageInfo(HDC hdc
)
2772 FONTSIGNATURE fontsig
;
2773 static const DWORD GCP_DBCS_MASK
=0x003F0000,
2774 GCP_DIACRITIC_MASK
=0x00000000,
2775 FLI_GLYPHS_MASK
=0x00000000,
2776 GCP_GLYPHSHAPE_MASK
=0x00000040,
2777 GCP_KASHIDA_MASK
=0x00000000,
2778 GCP_LIGATE_MASK
=0x00000000,
2779 GCP_USEKERNING_MASK
=0x00000000,
2780 GCP_REORDER_MASK
=0x00000060;
2784 GetTextCharsetInfo( hdc
, &fontsig
, 0 );
2785 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2787 if( (fontsig
.fsCsb
[0]&GCP_DBCS_MASK
)!=0 )
2790 if( (fontsig
.fsCsb
[0]&GCP_DIACRITIC_MASK
)!=0 )
2791 result
|=GCP_DIACRITIC
;
2793 if( (fontsig
.fsCsb
[0]&FLI_GLYPHS_MASK
)!=0 )
2796 if( (fontsig
.fsCsb
[0]&GCP_GLYPHSHAPE_MASK
)!=0 )
2797 result
|=GCP_GLYPHSHAPE
;
2799 if( (fontsig
.fsCsb
[0]&GCP_KASHIDA_MASK
)!=0 )
2800 result
|=GCP_KASHIDA
;
2802 if( (fontsig
.fsCsb
[0]&GCP_LIGATE_MASK
)!=0 )
2805 if( (fontsig
.fsCsb
[0]&GCP_USEKERNING_MASK
)!=0 )
2806 result
|=GCP_USEKERNING
;
2808 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2809 if( GetTextAlign( hdc
) & TA_RTLREADING
)
2810 if( (fontsig
.fsCsb
[0]&GCP_REORDER_MASK
)!=0 )
2811 result
|=GCP_REORDER
;
2817 /*************************************************************************
2818 * GetFontData [GDI32.@]
2820 * Retrieve data for TrueType font.
2824 * success: Number of bytes returned
2825 * failure: GDI_ERROR
2829 * Calls SetLastError()
2832 DWORD WINAPI
GetFontData(HDC hdc
, DWORD table
, DWORD offset
,
2833 LPVOID buffer
, DWORD length
)
2835 DC
*dc
= DC_GetDCPtr(hdc
);
2836 DWORD ret
= GDI_ERROR
;
2838 if(!dc
) return GDI_ERROR
;
2841 ret
= WineEngGetFontData(dc
->gdiFont
, table
, offset
, buffer
, length
);
2843 GDI_ReleaseObj(hdc
);
2847 /*************************************************************************
2848 * GetGlyphIndicesA [GDI32.@]
2850 DWORD WINAPI
GetGlyphIndicesA(HDC hdc
, LPCSTR lpstr
, INT count
,
2851 LPWORD pgi
, DWORD flags
)
2857 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2858 hdc
, debugstr_an(lpstr
, count
), count
, pgi
, flags
);
2860 lpstrW
= FONT_mbtowc(hdc
, lpstr
, count
, &countW
, NULL
);
2861 ret
= GetGlyphIndicesW(hdc
, lpstrW
, countW
, pgi
, flags
);
2862 HeapFree(GetProcessHeap(), 0, lpstrW
);
2867 /*************************************************************************
2868 * GetGlyphIndicesW [GDI32.@]
2870 DWORD WINAPI
GetGlyphIndicesW(HDC hdc
, LPCWSTR lpstr
, INT count
,
2871 LPWORD pgi
, DWORD flags
)
2873 DC
*dc
= DC_GetDCPtr(hdc
);
2874 DWORD ret
= GDI_ERROR
;
2876 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2877 hdc
, debugstr_wn(lpstr
, count
), count
, pgi
, flags
);
2879 if(!dc
) return GDI_ERROR
;
2882 ret
= WineEngGetGlyphIndices(dc
->gdiFont
, lpstr
, count
, pgi
, flags
);
2884 GDI_ReleaseObj(hdc
);
2888 /*************************************************************************
2889 * GetCharacterPlacementA [GDI32.@]
2891 * See GetCharacterPlacementW.
2894 * the web browser control of ie4 calls this with dwFlags=0
2897 GetCharacterPlacementA(HDC hdc
, LPCSTR lpString
, INT uCount
,
2898 INT nMaxExtent
, GCP_RESULTSA
*lpResults
,
2903 GCP_RESULTSW resultsW
;
2907 TRACE("%s, %d, %d, 0x%08x\n",
2908 debugstr_an(lpString
, uCount
), uCount
, nMaxExtent
, dwFlags
);
2910 /* both structs are equal in size */
2911 memcpy(&resultsW
, lpResults
, sizeof(resultsW
));
2913 lpStringW
= FONT_mbtowc(hdc
, lpString
, uCount
, &uCountW
, &font_cp
);
2914 if(lpResults
->lpOutString
)
2915 resultsW
.lpOutString
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*uCountW
);
2917 ret
= GetCharacterPlacementW(hdc
, lpStringW
, uCountW
, nMaxExtent
, &resultsW
, dwFlags
);
2919 lpResults
->nGlyphs
= resultsW
.nGlyphs
;
2920 lpResults
->nMaxFit
= resultsW
.nMaxFit
;
2922 if(lpResults
->lpOutString
) {
2923 WideCharToMultiByte(font_cp
, 0, resultsW
.lpOutString
, uCountW
,
2924 lpResults
->lpOutString
, uCount
, NULL
, NULL
);
2927 HeapFree(GetProcessHeap(), 0, lpStringW
);
2928 HeapFree(GetProcessHeap(), 0, resultsW
.lpOutString
);
2933 /*************************************************************************
2934 * GetCharacterPlacementW [GDI32.@]
2936 * Retrieve information about a string. This includes the width, reordering,
2937 * Glyphing and so on.
2941 * The width and height of the string if successful, 0 if failed.
2945 * All flags except GCP_REORDER are not yet implemented.
2946 * Reordering is not 100% complient to the Windows BiDi method.
2947 * Caret positioning is not yet implemented for BiDi.
2948 * Classes are not yet implemented.
2952 GetCharacterPlacementW(
2953 HDC hdc
, /* [in] Device context for which the rendering is to be done */
2954 LPCWSTR lpString
, /* [in] The string for which information is to be returned */
2955 INT uCount
, /* [in] Number of WORDS in string. */
2956 INT nMaxExtent
, /* [in] Maximum extent the string is to take (in HDC logical units) */
2957 GCP_RESULTSW
*lpResults
,/* [in/out] A pointer to a GCP_RESULTSW struct */
2958 DWORD dwFlags
/* [in] Flags specifying how to process the string */
2965 TRACE("%s, %d, %d, 0x%08x\n",
2966 debugstr_wn(lpString
, uCount
), uCount
, nMaxExtent
, dwFlags
);
2968 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2969 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2970 lpResults
->lStructSize
, lpResults
->lpOutString
, lpResults
->lpOrder
,
2971 lpResults
->lpDx
, lpResults
->lpCaretPos
, lpResults
->lpClass
,
2972 lpResults
->lpGlyphs
, lpResults
->nGlyphs
, lpResults
->nMaxFit
);
2974 if(dwFlags
&(~GCP_REORDER
)) FIXME("flags 0x%08x ignored\n", dwFlags
);
2975 if(lpResults
->lpClass
) FIXME("classes not implemented\n");
2976 if (lpResults
->lpCaretPos
&& (dwFlags
& GCP_REORDER
))
2977 FIXME("Caret positions for complex scripts not implemented\n");
2979 nSet
= (UINT
)uCount
;
2980 if(nSet
> lpResults
->nGlyphs
)
2981 nSet
= lpResults
->nGlyphs
;
2983 /* return number of initialized fields */
2984 lpResults
->nGlyphs
= nSet
;
2986 if((dwFlags
&GCP_REORDER
)==0 || !BidiAvail
)
2988 /* Treat the case where no special handling was requested in a fastpath way */
2989 /* copy will do if the GCP_REORDER flag is not set */
2990 if(lpResults
->lpOutString
)
2991 memcpy( lpResults
->lpOutString
, lpString
, nSet
* sizeof(WCHAR
));
2993 if(lpResults
->lpOrder
)
2995 for(i
= 0; i
< nSet
; i
++)
2996 lpResults
->lpOrder
[i
] = i
;
3000 BIDI_Reorder( lpString
, uCount
, dwFlags
, WINE_GCPW_FORCE_LTR
, lpResults
->lpOutString
,
3001 nSet
, lpResults
->lpOrder
);
3004 /* FIXME: Will use the placement chars */
3005 if (lpResults
->lpDx
)
3008 for (i
= 0; i
< nSet
; i
++)
3010 if (GetCharWidth32W(hdc
, lpString
[i
], lpString
[i
], &c
))
3011 lpResults
->lpDx
[i
]= c
;
3015 if (lpResults
->lpCaretPos
&& !(dwFlags
& GCP_REORDER
))
3019 lpResults
->lpCaretPos
[0] = 0;
3020 for (i
= 1; i
< nSet
; i
++)
3021 if (GetTextExtentPoint32W(hdc
, &(lpString
[i
- 1]), 1, &size
))
3022 lpResults
->lpCaretPos
[i
] = (pos
+= size
.cx
);
3025 if(lpResults
->lpGlyphs
)
3026 GetGlyphIndicesW(hdc
, lpString
, nSet
, lpResults
->lpGlyphs
, 0);
3028 if (GetTextExtentPoint32W(hdc
, lpString
, uCount
, &size
))
3029 ret
= MAKELONG(size
.cx
, size
.cy
);
3034 /*************************************************************************
3035 * GetCharABCWidthsFloatA [GDI32.@]
3037 * See GetCharABCWidthsFloatW.
3039 BOOL WINAPI
GetCharABCWidthsFloatA( HDC hdc
, UINT first
, UINT last
, LPABCFLOAT abcf
)
3041 INT i
, wlen
, count
= (INT
)(last
- first
+ 1);
3046 if (count
<= 0) return FALSE
;
3048 str
= HeapAlloc(GetProcessHeap(), 0, count
);
3050 for(i
= 0; i
< count
; i
++)
3051 str
[i
] = (BYTE
)(first
+ i
);
3053 wstr
= FONT_mbtowc( hdc
, str
, count
, &wlen
, NULL
);
3055 for (i
= 0; i
< wlen
; i
++)
3057 if (!GetCharABCWidthsFloatW( hdc
, wstr
[i
], wstr
[i
], abcf
))
3065 HeapFree( GetProcessHeap(), 0, str
);
3066 HeapFree( GetProcessHeap(), 0, wstr
);
3071 /*************************************************************************
3072 * GetCharABCWidthsFloatW [GDI32.@]
3074 * Retrieves widths of a range of characters.
3077 * hdc [I] Handle to device context.
3078 * first [I] First character in range to query.
3079 * last [I] Last character in range to query.
3080 * abcf [O] Array of LPABCFLOAT structures.
3087 * Only works with TrueType fonts. It also doesn't return real
3088 * floats but converted integers because it's implemented on
3089 * top of GetCharABCWidthsW.
3091 BOOL WINAPI
GetCharABCWidthsFloatW( HDC hdc
, UINT first
, UINT last
, LPABCFLOAT abcf
)
3094 unsigned int i
, size
= sizeof(ABC
) * (last
- first
+ 1);
3097 TRACE("%p, %d, %d, %p - partial stub\n", hdc
, first
, last
, abcf
);
3099 abc
= HeapAlloc( GetProcessHeap(), 0, size
);
3100 if (!abc
) return FALSE
;
3102 ret
= GetCharABCWidthsW( hdc
, first
, last
, abc
);
3105 for (i
= first
; i
<= last
; i
++, abc
++, abcf
++)
3107 abcf
->abcfA
= abc
->abcA
;
3108 abcf
->abcfB
= abc
->abcB
;
3109 abcf
->abcfC
= abc
->abcC
;
3112 HeapFree( GetProcessHeap(), 0, abc
);
3116 /*************************************************************************
3117 * GetCharWidthFloatA [GDI32.@]
3119 BOOL WINAPI
GetCharWidthFloatA(HDC hdc
, UINT iFirstChar
,
3120 UINT iLastChar
, PFLOAT pxBuffer
)
3122 FIXME("%p, %u, %u, %p: stub!\n", hdc
, iFirstChar
, iLastChar
, pxBuffer
);
3126 /*************************************************************************
3127 * GetCharWidthFloatW [GDI32.@]
3129 BOOL WINAPI
GetCharWidthFloatW(HDC hdc
, UINT iFirstChar
,
3130 UINT iLastChar
, PFLOAT pxBuffer
)
3132 FIXME("%p, %u, %u, %p: stub!\n", hdc
, iFirstChar
, iLastChar
, pxBuffer
);
3137 /***********************************************************************
3139 * Font Resource API *
3141 ***********************************************************************/
3143 /***********************************************************************
3144 * AddFontResourceA (GDI32.@)
3146 INT WINAPI
AddFontResourceA( LPCSTR str
)
3148 return AddFontResourceExA( str
, 0, NULL
);
3151 /***********************************************************************
3152 * AddFontResourceW (GDI32.@)
3154 INT WINAPI
AddFontResourceW( LPCWSTR str
)
3156 return AddFontResourceExW(str
, 0, NULL
);
3160 /***********************************************************************
3161 * AddFontResourceExA (GDI32.@)
3163 INT WINAPI
AddFontResourceExA( LPCSTR str
, DWORD fl
, PVOID pdv
)
3165 DWORD len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
3166 LPWSTR strW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3169 MultiByteToWideChar(CP_ACP
, 0, str
, -1, strW
, len
);
3170 ret
= AddFontResourceExW(strW
, fl
, pdv
);
3171 HeapFree(GetProcessHeap(), 0, strW
);
3175 /***********************************************************************
3176 * AddFontResourceExW (GDI32.@)
3178 INT WINAPI
AddFontResourceExW( LPCWSTR str
, DWORD fl
, PVOID pdv
)
3180 return WineEngAddFontResourceEx(str
, fl
, pdv
);
3183 /***********************************************************************
3184 * RemoveFontResourceA (GDI32.@)
3186 BOOL WINAPI
RemoveFontResourceA( LPCSTR str
)
3188 return RemoveFontResourceExA(str
, 0, 0);
3191 /***********************************************************************
3192 * RemoveFontResourceW (GDI32.@)
3194 BOOL WINAPI
RemoveFontResourceW( LPCWSTR str
)
3196 return RemoveFontResourceExW(str
, 0, 0);
3199 /***********************************************************************
3200 * AddFontMemResourceEx (GDI32.@)
3202 HANDLE WINAPI
AddFontMemResourceEx( PVOID pbFont
, DWORD cbFont
, PVOID pdv
, DWORD
*pcFonts
)
3204 FIXME("(%p,%08x,%p,%p): stub\n", pbFont
, cbFont
, pdv
, pcFonts
);
3208 /***********************************************************************
3209 * RemoveFontResourceExA (GDI32.@)
3211 BOOL WINAPI
RemoveFontResourceExA( LPCSTR str
, DWORD fl
, PVOID pdv
)
3213 DWORD len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
3214 LPWSTR strW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3217 MultiByteToWideChar(CP_ACP
, 0, str
, -1, strW
, len
);
3218 ret
= RemoveFontResourceExW(strW
, fl
, pdv
);
3219 HeapFree(GetProcessHeap(), 0, strW
);
3223 /***********************************************************************
3224 * RemoveFontResourceExW (GDI32.@)
3226 BOOL WINAPI
RemoveFontResourceExW( LPCWSTR str
, DWORD fl
, PVOID pdv
)
3228 return WineEngRemoveFontResourceEx(str
, fl
, pdv
);
3231 /***********************************************************************
3232 * GetTextCharset (GDI32.@)
3234 UINT WINAPI
GetTextCharset(HDC hdc
)
3236 /* MSDN docs say this is equivalent */
3237 return GetTextCharsetInfo(hdc
, NULL
, 0);
3240 /***********************************************************************
3241 * GetTextCharsetInfo (GDI32.@)
3243 UINT WINAPI
GetTextCharsetInfo(HDC hdc
, LPFONTSIGNATURE fs
, DWORD flags
)
3245 UINT ret
= DEFAULT_CHARSET
;
3246 DC
*dc
= DC_GetDCPtr(hdc
);
3251 ret
= WineEngGetTextCharsetInfo(dc
->gdiFont
, fs
, flags
);
3253 GDI_ReleaseObj(hdc
);
3256 if (ret
== DEFAULT_CHARSET
&& fs
)
3257 memset(fs
, 0, sizeof(FONTSIGNATURE
));
3261 /***********************************************************************
3262 * GdiGetCharDimensions (GDI32.@)
3264 * Gets the average width of the characters in the English alphabet.
3267 * hdc [I] Handle to the device context to measure on.
3268 * lptm [O] Pointer to memory to store the text metrics into.
3269 * height [O] On exit, the maximum height of characters in the English alphabet.
3272 * The average width of characters in the English alphabet.
3275 * This function is used by the dialog manager to get the size of a dialog
3276 * unit. It should also be used by other pieces of code that need to know
3277 * the size of a dialog unit in logical units without having access to the
3278 * window handle of the dialog.
3279 * Windows caches the font metrics from this function, but we don't and
3280 * there doesn't appear to be an immediate advantage to do so.
3283 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3285 LONG WINAPI
GdiGetCharDimensions(HDC hdc
, LPTEXTMETRICW lptm
, LONG
*height
)
3288 static const WCHAR alphabet
[] = {
3289 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3290 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3291 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3293 if(lptm
&& !GetTextMetricsW(hdc
, lptm
)) return 0;
3295 if(!GetTextExtentPointW(hdc
, alphabet
, 52, &sz
)) return 0;
3297 if (height
) *height
= sz
.cy
;
3298 return (sz
.cx
/ 26 + 1) / 2;
3301 BOOL WINAPI
EnableEUDC(BOOL fEnableEUDC
)
3303 FIXME("(%d): stub\n", fEnableEUDC
);
3307 /***********************************************************************
3308 * GetCharWidthI (GDI32.@)
3310 * Retrieve widths of characters.
3313 * hdc [I] Handle to a device context.
3314 * first [I] First glyph in range to query.
3315 * count [I] Number of glyph indices to query.
3316 * glyphs [I] Array of glyphs to query.
3317 * buffer [O] Buffer to receive character widths.
3320 * Only works with TrueType fonts.
3326 BOOL WINAPI
GetCharWidthI(HDC hdc
, UINT first
, UINT count
, LPWORD glyphs
, LPINT buffer
)
3331 TRACE("(%p, %d, %d, %p, %p)\n", hdc
, first
, count
, glyphs
, buffer
);
3333 if (!(abc
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(ABC
))))
3336 if (!GetCharABCWidthsI(hdc
, first
, count
, glyphs
, abc
))
3338 HeapFree(GetProcessHeap(), 0, abc
);
3342 for (i
= 0; i
< count
; i
++)
3343 buffer
[i
] = abc
->abcA
+ abc
->abcB
+ abc
->abcC
;
3345 HeapFree(GetProcessHeap(), 0, abc
);
3349 /***********************************************************************
3350 * GetFontUnicodeRanges (GDI32.@)
3352 * Retrieve a list of supported Unicode characters in a font.
3355 * hdc [I] Handle to a device context.
3356 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3359 * Success: Number of bytes written to the buffer pointed to by lpgs.
3363 DWORD WINAPI
GetFontUnicodeRanges(HDC hdc
, LPGLYPHSET lpgs
)
3365 return WineEngGetFontUnicodeRanges(hdc
, lpgs
);