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((DWORD
*)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(GetDeviceCaps(dc
->hSelf
, TEXTCAPS
) & TC_VA_ABLE
)
596 dc
->gdiFont
= WineEngCreateFontInstance(dc
, handle
);
598 if (dc
->funcs
->pSelectFont
) ret
= dc
->funcs
->pSelectFont( dc
->physDev
, handle
, dc
->gdiFont
);
600 if (ret
&& dc
->gdiFont
) dc
->gdiFont
= 0;
602 if (ret
== HGDI_ERROR
)
603 ret
= 0; /* SelectObject returns 0 on error */
609 GDI_ReleaseObj( hdc
);
614 /***********************************************************************
617 static INT
FONT_GetObject16( HGDIOBJ handle
, void *obj
, INT count
, LPVOID buffer
)
622 FONT_LogFontWTo16( &font
->logfont
, &lf16
);
624 if (count
> sizeof(LOGFONT16
)) count
= sizeof(LOGFONT16
);
625 memcpy( buffer
, &lf16
, count
);
629 /***********************************************************************
632 static INT
FONT_GetObjectA( HGDIOBJ handle
, void *obj
, INT count
, LPVOID buffer
)
639 FONT_LogFontWToA( &font
->logfont
, &lfA
);
641 if (count
> sizeof(lfA
)) count
= sizeof(lfA
);
642 memcpy( buffer
, &lfA
, count
);
646 /***********************************************************************
649 static INT
FONT_GetObjectW( HGDIOBJ handle
, void *obj
, INT count
, LPVOID buffer
)
653 return sizeof(LOGFONTW
);
654 if (count
> sizeof(LOGFONTW
)) count
= sizeof(LOGFONTW
);
655 memcpy( buffer
, &font
->logfont
, count
);
660 /***********************************************************************
663 static BOOL
FONT_DeleteObject( HGDIOBJ handle
, void *obj
)
665 WineEngDestroyFontInstance( handle
);
666 return GDI_FreeObject( handle
, obj
);
670 /***********************************************************************
671 * FONT_EnumInstance16
673 * Called by the device driver layer to pass font info
674 * down to the application.
676 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
677 * We have to use other types because of the FONTENUMPROCW definition.
679 static INT CALLBACK
FONT_EnumInstance16( const LOGFONTW
*plf
, const TEXTMETRICW
*ptm
,
680 DWORD fType
, LPARAM lp
)
682 fontEnum16
*pfe
= (fontEnum16
*)lp
;
686 if( pfe
->lpLogFontParam
->lfCharSet
== DEFAULT_CHARSET
||
687 pfe
->lpLogFontParam
->lfCharSet
== plf
->lfCharSet
)
692 FONT_EnumLogFontExWTo16((const ENUMLOGFONTEXW
*)plf
, pfe
->lpLogFont
);
693 FONT_NewTextMetricExWTo16((const NEWTEXTMETRICEXW
*)ptm
, pfe
->lpTextMetric
);
694 pfe
->dwFlags
|= ENUM_CALLED
;
695 GDI_ReleaseObj( pfe
->hdc
); /* release the GDI lock */
697 args
[6] = SELECTOROF(pfe
->segLogFont
);
698 args
[5] = OFFSETOF(pfe
->segLogFont
);
699 args
[4] = SELECTOROF(pfe
->segTextMetric
);
700 args
[3] = OFFSETOF(pfe
->segTextMetric
);
702 args
[1] = HIWORD(pfe
->lpData
);
703 args
[0] = LOWORD(pfe
->lpData
);
704 WOWCallback16Ex( (DWORD
)pfe
->lpEnumFunc
, WCB16_PASCAL
, sizeof(args
), args
, &result
);
705 ret
= LOWORD(result
);
707 /* get the lock again and make sure the DC is still valid */
708 dc
= DC_GetDCPtr( pfe
->hdc
);
709 if (!dc
|| dc
!= pfe
->dc
|| dc
->physDev
!= pfe
->physDev
)
711 if (dc
) GDI_ReleaseObj( pfe
->hdc
);
712 pfe
->hdc
= 0; /* make sure we don't try to release it later on */
719 /***********************************************************************
722 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
723 * We have to use other types because of the FONTENUMPROCW definition.
725 static INT CALLBACK
FONT_EnumInstance( const LOGFONTW
*plf
, const TEXTMETRICW
*ptm
,
726 DWORD fType
, LPARAM lp
)
728 fontEnum32
*pfe
= (fontEnum32
*)lp
;
732 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
733 if((pfe
->lpLogFontParam
->lfCharSet
== DEFAULT_CHARSET
||
734 pfe
->lpLogFontParam
->lfCharSet
== plf
->lfCharSet
) &&
735 (!(fType
& RASTER_FONTTYPE
) || GetDeviceCaps(pfe
->hdc
, TEXTCAPS
) & TC_RA_ABLE
) )
737 /* convert font metrics */
738 ENUMLOGFONTEXA logfont
;
739 NEWTEXTMETRICEXA tmA
;
741 pfe
->dwFlags
|= ENUM_CALLED
;
742 if (!(pfe
->dwFlags
& ENUM_UNICODE
))
744 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW
*)plf
, &logfont
);
745 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW
*)ptm
, &tmA
);
746 plf
= (LOGFONTW
*)&logfont
.elfLogFont
;
747 ptm
= (TEXTMETRICW
*)&tmA
;
749 GDI_ReleaseObj( pfe
->hdc
); /* release the GDI lock */
751 ret
= pfe
->lpEnumFunc( plf
, ptm
, fType
, pfe
->lpData
);
753 /* get the lock again and make sure the DC is still valid */
754 dc
= DC_GetDCPtr( pfe
->hdc
);
755 if (!dc
|| dc
!= pfe
->dc
|| dc
->physDev
!= pfe
->physDev
)
757 if (dc
) GDI_ReleaseObj( pfe
->hdc
);
758 pfe
->hdc
= 0; /* make sure we don't try to release it later on */
765 /***********************************************************************
766 * EnumFontFamiliesEx (GDI.613)
768 INT16 WINAPI
EnumFontFamiliesEx16( HDC16 hDC
, LPLOGFONT16 plf
,
769 FONTENUMPROC16 efproc
, LPARAM lParam
,
774 DC
* dc
= DC_GetDCPtr( HDC_32(hDC
) );
775 NEWTEXTMETRICEX16 tm16
;
776 ENUMLOGFONTEX16 lf16
;
781 FONT_LogFont16ToW(plf
, &lfW
);
783 fe16
.hdc
= HDC_32(hDC
);
785 fe16
.physDev
= dc
->physDev
;
786 fe16
.lpLogFontParam
= plf
;
787 fe16
.lpEnumFunc
= efproc
;
788 fe16
.lpData
= lParam
;
789 fe16
.lpTextMetric
= &tm16
;
790 fe16
.lpLogFont
= &lf16
;
791 fe16
.segTextMetric
= MapLS( &tm16
);
792 fe16
.segLogFont
= MapLS( &lf16
);
795 enum_gdi_fonts
= GetDeviceCaps(fe16
.hdc
, TEXTCAPS
) & TC_VA_ABLE
;
797 if (!dc
->funcs
->pEnumDeviceFonts
&& !enum_gdi_fonts
)
804 ret
= WineEngEnumFonts( &lfW
, FONT_EnumInstance16
, (LPARAM
)&fe16
);
805 fe16
.dwFlags
&= ~ENUM_CALLED
;
806 if (ret
&& dc
->funcs
->pEnumDeviceFonts
) {
807 ret2
= dc
->funcs
->pEnumDeviceFonts( dc
->physDev
, &lfW
, FONT_EnumInstance16
, (LPARAM
)&fe16
);
808 if(fe16
.dwFlags
& ENUM_CALLED
) /* update ret iff a font gets enumed */
812 UnMapLS( fe16
.segTextMetric
);
813 UnMapLS( fe16
.segLogFont
);
814 if (fe16
.hdc
) GDI_ReleaseObj( fe16
.hdc
);
818 /***********************************************************************
819 * FONT_EnumFontFamiliesEx
821 static INT
FONT_EnumFontFamiliesEx( HDC hDC
, LPLOGFONTW plf
,
822 FONTENUMPROCW efproc
,
823 LPARAM lParam
, DWORD dwUnicode
)
826 DC
*dc
= DC_GetDCPtr( hDC
);
832 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf
->lfFaceName
),
834 fe32
.lpLogFontParam
= plf
;
835 fe32
.lpEnumFunc
= efproc
;
836 fe32
.lpData
= lParam
;
837 fe32
.dwFlags
= dwUnicode
;
840 fe32
.physDev
= dc
->physDev
;
842 enum_gdi_fonts
= GetDeviceCaps(hDC
, TEXTCAPS
) & TC_VA_ABLE
;
844 if (!dc
->funcs
->pEnumDeviceFonts
&& !enum_gdi_fonts
)
851 ret
= WineEngEnumFonts( plf
, FONT_EnumInstance
, (LPARAM
)&fe32
);
852 fe32
.dwFlags
&= ~ENUM_CALLED
;
853 if (ret
&& dc
->funcs
->pEnumDeviceFonts
) {
854 ret2
= dc
->funcs
->pEnumDeviceFonts( dc
->physDev
, plf
, FONT_EnumInstance
, (LPARAM
)&fe32
);
855 if(fe32
.dwFlags
& ENUM_CALLED
) /* update ret iff a font gets enumed */
859 if (fe32
.hdc
) GDI_ReleaseObj( fe32
.hdc
);
863 /***********************************************************************
864 * EnumFontFamiliesExW (GDI32.@)
866 INT WINAPI
EnumFontFamiliesExW( HDC hDC
, LPLOGFONTW plf
,
867 FONTENUMPROCW efproc
,
868 LPARAM lParam
, DWORD dwFlags
)
870 return FONT_EnumFontFamiliesEx( hDC
, plf
, efproc
, lParam
, ENUM_UNICODE
);
873 /***********************************************************************
874 * EnumFontFamiliesExA (GDI32.@)
876 INT WINAPI
EnumFontFamiliesExA( HDC hDC
, LPLOGFONTA plf
,
877 FONTENUMPROCA efproc
,
878 LPARAM lParam
, DWORD dwFlags
)
881 FONT_LogFontAToW( plf
, &lfW
);
883 return FONT_EnumFontFamiliesEx( hDC
, &lfW
, (FONTENUMPROCW
)efproc
, lParam
, 0);
886 /***********************************************************************
887 * EnumFontFamilies (GDI.330)
889 INT16 WINAPI
EnumFontFamilies16( HDC16 hDC
, LPCSTR lpFamily
,
890 FONTENUMPROC16 efproc
, LPARAM lpData
)
894 lf
.lfCharSet
= DEFAULT_CHARSET
;
897 if (!*lpFamily
) return 1;
898 lstrcpynA( lf
.lfFaceName
, lpFamily
, LF_FACESIZE
);
900 else lf
.lfFaceName
[0] = '\0';
902 return EnumFontFamiliesEx16( hDC
, &lf
, efproc
, lpData
, 0 );
905 /***********************************************************************
906 * EnumFontFamiliesA (GDI32.@)
908 INT WINAPI
EnumFontFamiliesA( HDC hDC
, LPCSTR lpFamily
,
909 FONTENUMPROCA efproc
, LPARAM lpData
)
913 lf
.lfCharSet
= DEFAULT_CHARSET
;
916 if (!*lpFamily
) return 1;
917 lstrcpynA( lf
.lfFaceName
, lpFamily
, LF_FACESIZE
);
919 else lf
.lfFaceName
[0] = lf
.lfFaceName
[1] = '\0';
921 return EnumFontFamiliesExA( hDC
, &lf
, efproc
, lpData
, 0 );
924 /***********************************************************************
925 * EnumFontFamiliesW (GDI32.@)
927 INT WINAPI
EnumFontFamiliesW( HDC hDC
, LPCWSTR lpFamily
,
928 FONTENUMPROCW efproc
, LPARAM lpData
)
932 lf
.lfCharSet
= DEFAULT_CHARSET
;
935 if (!*lpFamily
) return 1;
936 lstrcpynW( lf
.lfFaceName
, lpFamily
, LF_FACESIZE
);
938 else lf
.lfFaceName
[0] = 0;
940 return EnumFontFamiliesExW( hDC
, &lf
, efproc
, lpData
, 0 );
943 /***********************************************************************
946 INT16 WINAPI
EnumFonts16( HDC16 hDC
, LPCSTR lpName
, FONTENUMPROC16 efproc
,
949 return EnumFontFamilies16( hDC
, lpName
, efproc
, lpData
);
952 /***********************************************************************
953 * EnumFontsA (GDI32.@)
955 INT WINAPI
EnumFontsA( HDC hDC
, LPCSTR lpName
, FONTENUMPROCA efproc
,
958 return EnumFontFamiliesA( hDC
, lpName
, efproc
, lpData
);
961 /***********************************************************************
962 * EnumFontsW (GDI32.@)
964 INT WINAPI
EnumFontsW( HDC hDC
, LPCWSTR lpName
, FONTENUMPROCW efproc
,
967 return EnumFontFamiliesW( hDC
, lpName
, efproc
, lpData
);
971 /***********************************************************************
972 * GetTextCharacterExtra (GDI32.@)
974 INT WINAPI
GetTextCharacterExtra( HDC hdc
)
977 DC
*dc
= DC_GetDCPtr( hdc
);
978 if (!dc
) return 0x80000000;
980 GDI_ReleaseObj( hdc
);
985 /***********************************************************************
986 * SetTextCharacterExtra (GDI32.@)
988 INT WINAPI
SetTextCharacterExtra( HDC hdc
, INT extra
)
991 DC
* dc
= DC_GetDCPtr( hdc
);
992 if (!dc
) return 0x80000000;
993 if (dc
->funcs
->pSetTextCharacterExtra
)
994 prev
= dc
->funcs
->pSetTextCharacterExtra( dc
->physDev
, extra
);
997 prev
= dc
->charExtra
;
998 dc
->charExtra
= extra
;
1000 GDI_ReleaseObj( hdc
);
1005 /***********************************************************************
1006 * SetTextJustification (GDI32.@)
1008 BOOL WINAPI
SetTextJustification( HDC hdc
, INT extra
, INT breaks
)
1011 DC
* dc
= DC_GetDCPtr( hdc
);
1012 if (!dc
) return FALSE
;
1013 if (dc
->funcs
->pSetTextJustification
)
1014 ret
= dc
->funcs
->pSetTextJustification( dc
->physDev
, extra
, breaks
);
1017 extra
= abs((extra
* dc
->vportExtX
+ dc
->wndExtX
/ 2) / dc
->wndExtX
);
1018 if (!extra
) breaks
= 0;
1021 dc
->breakExtra
= extra
/ breaks
;
1022 dc
->breakRem
= extra
- (breaks
* dc
->breakExtra
);
1030 GDI_ReleaseObj( hdc
);
1035 /***********************************************************************
1036 * GetTextFaceA (GDI32.@)
1038 INT WINAPI
GetTextFaceA( HDC hdc
, INT count
, LPSTR name
)
1040 INT res
= GetTextFaceW(hdc
, 0, NULL
);
1041 LPWSTR nameW
= HeapAlloc( GetProcessHeap(), 0, res
* 2 );
1042 GetTextFaceW( hdc
, res
, nameW
);
1046 if (count
&& !WideCharToMultiByte( CP_ACP
, 0, nameW
, -1, name
, count
, NULL
, NULL
))
1051 res
= WideCharToMultiByte( CP_ACP
, 0, nameW
, -1, NULL
, 0, NULL
, NULL
);
1052 HeapFree( GetProcessHeap(), 0, nameW
);
1056 /***********************************************************************
1057 * GetTextFaceW (GDI32.@)
1059 INT WINAPI
GetTextFaceW( HDC hdc
, INT count
, LPWSTR name
)
1064 DC
* dc
= DC_GetDCPtr( hdc
);
1068 ret
= WineEngGetTextFace(dc
->gdiFont
, count
, name
);
1069 else if ((font
= (FONTOBJ
*) GDI_GetObjPtr( dc
->hFont
, FONT_MAGIC
)))
1073 lstrcpynW( name
, font
->logfont
.lfFaceName
, count
);
1074 ret
= strlenW(name
);
1076 else ret
= strlenW(font
->logfont
.lfFaceName
) + 1;
1077 GDI_ReleaseObj( dc
->hFont
);
1079 GDI_ReleaseObj( hdc
);
1084 /***********************************************************************
1085 * GetTextExtentPoint32A (GDI32.@)
1087 * See GetTextExtentPoint32W.
1089 BOOL WINAPI
GetTextExtentPoint32A( HDC hdc
, LPCSTR str
, INT count
,
1096 if(count
< 0) return FALSE
;
1098 p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
1100 ret
= GetTextExtentPoint32W( hdc
, p
, wlen
, size
);
1101 HeapFree( GetProcessHeap(), 0, p
);
1104 TRACE("(%p %s %d %p): returning %d x %d\n",
1105 hdc
, debugstr_an (str
, count
), count
, size
, size
->cx
, size
->cy
);
1110 /***********************************************************************
1111 * GetTextExtentPoint32W [GDI32.@]
1113 * Computes width/height for a string.
1115 * Computes width and height of the specified string.
1121 BOOL WINAPI
GetTextExtentPoint32W(
1122 HDC hdc
, /* [in] Handle of device context */
1123 LPCWSTR str
, /* [in] Address of text string */
1124 INT count
, /* [in] Number of characters in string */
1125 LPSIZE size
) /* [out] Address of structure for string size */
1127 return GetTextExtentExPointW(hdc
, str
, count
, 0, NULL
, NULL
, size
);
1130 /***********************************************************************
1131 * GetTextExtentPointI [GDI32.@]
1133 * Computes width and height of the array of glyph indices.
1139 BOOL WINAPI
GetTextExtentPointI(
1140 HDC hdc
, /* [in] Handle of device context */
1141 const WORD
*indices
, /* [in] Address of glyph index array */
1142 INT count
, /* [in] Number of glyphs in array */
1143 LPSIZE size
) /* [out] Address of structure for string size */
1148 if (count
< 0) return FALSE
;
1150 dc
= DC_GetDCPtr( hdc
);
1151 if (!dc
) return FALSE
;
1154 ret
= WineEngGetTextExtentPointI(dc
->gdiFont
, indices
, count
, size
);
1155 size
->cx
= abs(INTERNAL_XDSTOWS(dc
, size
->cx
));
1156 size
->cy
= abs(INTERNAL_YDSTOWS(dc
, size
->cy
));
1157 size
->cx
+= count
* dc
->charExtra
;
1159 else if(dc
->funcs
->pGetTextExtentExPoint
) {
1160 FIXME("calling GetTextExtentExPoint\n");
1161 ret
= dc
->funcs
->pGetTextExtentExPoint( dc
->physDev
, (LPCWSTR
)indices
,
1162 count
, 0, NULL
, NULL
, size
);
1165 GDI_ReleaseObj( hdc
);
1167 TRACE("(%p %p %d %p): returning %d x %d\n",
1168 hdc
, indices
, count
, size
, size
->cx
, size
->cy
);
1173 /***********************************************************************
1174 * GetTextExtentPointA (GDI32.@)
1176 BOOL WINAPI
GetTextExtentPointA( HDC hdc
, LPCSTR str
, INT count
,
1179 TRACE("not bug compatible.\n");
1180 return GetTextExtentPoint32A( hdc
, str
, count
, size
);
1183 /***********************************************************************
1184 * GetTextExtentPointW (GDI32.@)
1186 BOOL WINAPI
GetTextExtentPointW( HDC hdc
, LPCWSTR str
, INT count
,
1189 TRACE("not bug compatible.\n");
1190 return GetTextExtentPoint32W( hdc
, str
, count
, size
);
1194 /***********************************************************************
1195 * GetTextExtentExPointA (GDI32.@)
1197 BOOL WINAPI
GetTextExtentExPointA( HDC hdc
, LPCSTR str
, INT count
,
1198 INT maxExt
, LPINT lpnFit
,
1199 LPINT alpDx
, LPSIZE size
)
1207 NULL
== (walpDx
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(INT
))))
1210 p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
1211 ret
= GetTextExtentExPointW( hdc
, p
, wlen
, maxExt
, lpnFit
, walpDx
, size
);
1214 INT n
= lpnFit
? *lpnFit
: wlen
;
1216 for(i
= 0, j
= 0; i
< n
; i
++, j
++)
1218 alpDx
[j
] = walpDx
[i
];
1219 if (IsDBCSLeadByte(str
[j
])) alpDx
[++j
] = walpDx
[i
];
1222 if (lpnFit
) *lpnFit
= WideCharToMultiByte(CP_ACP
,0,p
,*lpnFit
,NULL
,0,NULL
,NULL
);
1223 HeapFree( GetProcessHeap(), 0, p
);
1224 HeapFree( GetProcessHeap(), 0, walpDx
);
1229 /***********************************************************************
1230 * GetTextExtentExPointW (GDI32.@)
1232 * Return the size of the string as it would be if it was output properly by
1235 * This should include
1236 * - Intercharacter spacing
1237 * - justification spacing (not yet done)
1238 * - kerning? see below
1240 * Kerning. Since kerning would be carried out by the rendering code it should
1241 * be done by the driver. However they don't support it yet. Also I am not
1242 * yet persuaded that (certainly under Win95) any kerning is actually done.
1244 * str: According to MSDN this should be null-terminated. That is not true; a
1245 * null will not terminate it early.
1246 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1247 * than count. I have seen it be either the size of the full string or
1248 * 1 less than the size of the full string. I have not seen it bear any
1249 * resemblance to the portion that would fit.
1250 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1251 * trailing intercharacter spacing and any trailing justification.
1254 * Currently we do this by measuring each character etc. We should do it by
1255 * passing the request to the driver, perhaps by extending the
1256 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1257 * thinking about kerning issues and rounding issues in the justification.
1260 BOOL WINAPI
GetTextExtentExPointW( HDC hdc
, LPCWSTR str
, INT count
,
1261 INT maxExt
, LPINT lpnFit
,
1262 LPINT alpDx
, LPSIZE size
)
1270 if (count
< 0) return FALSE
;
1272 TRACE("(%p, %s, %d)\n",hdc
,debugstr_wn(str
,count
),maxExt
);
1274 dc
= DC_GetDCPtr(hdc
);
1278 GetTextMetricsW(hdc
, &tm
);
1280 /* If we need to calculate nFit, then we need the partial extents even if
1281 the user hasn't provided us with an array. */
1284 dxs
= alpDx
? alpDx
: HeapAlloc(GetProcessHeap(), 0, count
* sizeof alpDx
[0]);
1287 GDI_ReleaseObj(hdc
);
1288 SetLastError(ERROR_OUTOFMEMORY
);
1296 ret
= WineEngGetTextExtentExPoint(dc
->gdiFont
, str
, count
,
1297 0, NULL
, dxs
, size
);
1298 else if (dc
->funcs
->pGetTextExtentExPoint
)
1299 ret
= dc
->funcs
->pGetTextExtentExPoint(dc
->physDev
, str
, count
,
1300 0, NULL
, dxs
, size
);
1302 /* Perform device size to world size transformations. */
1305 INT extra
= dc
->charExtra
,
1306 breakExtra
= dc
->breakExtra
,
1307 breakRem
= dc
->breakRem
,
1312 for (i
= 0; i
< count
; ++i
)
1314 dxs
[i
] = abs(INTERNAL_XDSTOWS(dc
, dxs
[i
]));
1315 dxs
[i
] += (i
+1) * extra
;
1316 if (count
> 1 && (breakExtra
|| breakRem
) && str
[i
] == tm
.tmBreakChar
)
1318 dxs
[i
] += breakExtra
;
1325 if (dxs
[i
] <= maxExt
)
1328 breakRem
= dc
->breakRem
;
1330 size
->cx
= abs(INTERNAL_XDSTOWS(dc
, size
->cx
));
1331 size
->cy
= abs(INTERNAL_YDSTOWS(dc
, size
->cy
));
1333 if (!dxs
&& count
> 1 && (breakExtra
|| breakRem
))
1335 for (i
= 0; i
< count
; i
++)
1337 if (str
[i
] == tm
.tmBreakChar
)
1339 size
->cx
+= breakExtra
;
1354 HeapFree(GetProcessHeap(), 0, dxs
);
1356 GDI_ReleaseObj( hdc
);
1358 TRACE("returning %d %d x %d\n",nFit
,size
->cx
,size
->cy
);
1362 /***********************************************************************
1363 * GetTextMetricsA (GDI32.@)
1365 BOOL WINAPI
GetTextMetricsA( HDC hdc
, TEXTMETRICA
*metrics
)
1369 if (!GetTextMetricsW( hdc
, &tm32
)) return FALSE
;
1370 FONT_TextMetricWToA( &tm32
, metrics
);
1374 /***********************************************************************
1375 * GetTextMetricsW (GDI32.@)
1377 BOOL WINAPI
GetTextMetricsW( HDC hdc
, TEXTMETRICW
*metrics
)
1380 DC
* dc
= DC_GetDCPtr( hdc
);
1381 if (!dc
) return FALSE
;
1384 ret
= WineEngGetTextMetrics(dc
->gdiFont
, metrics
);
1385 else if (dc
->funcs
->pGetTextMetrics
)
1386 ret
= dc
->funcs
->pGetTextMetrics( dc
->physDev
, metrics
);
1390 /* device layer returns values in device units
1391 * therefore we have to convert them to logical */
1393 metrics
->tmDigitizedAspectX
= GetDeviceCaps(hdc
, LOGPIXELSX
);
1394 metrics
->tmDigitizedAspectY
= GetDeviceCaps(hdc
, LOGPIXELSY
);
1396 #define WDPTOLP(x) ((x<0)? \
1397 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1398 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1399 #define HDPTOLP(y) ((y<0)? \
1400 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1401 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1403 metrics
->tmHeight
= HDPTOLP(metrics
->tmHeight
);
1404 metrics
->tmAscent
= HDPTOLP(metrics
->tmAscent
);
1405 metrics
->tmDescent
= HDPTOLP(metrics
->tmDescent
);
1406 metrics
->tmInternalLeading
= HDPTOLP(metrics
->tmInternalLeading
);
1407 metrics
->tmExternalLeading
= HDPTOLP(metrics
->tmExternalLeading
);
1408 metrics
->tmAveCharWidth
= WDPTOLP(metrics
->tmAveCharWidth
);
1409 metrics
->tmMaxCharWidth
= WDPTOLP(metrics
->tmMaxCharWidth
);
1410 metrics
->tmOverhang
= WDPTOLP(metrics
->tmOverhang
);
1414 TRACE("text metrics:\n"
1415 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1416 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1417 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1418 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1419 " PitchAndFamily = %02x\n"
1420 " --------------------\n"
1421 " InternalLeading = %i\n"
1425 metrics
->tmWeight
, metrics
->tmFirstChar
, metrics
->tmAveCharWidth
,
1426 metrics
->tmItalic
, metrics
->tmLastChar
, metrics
->tmMaxCharWidth
,
1427 metrics
->tmUnderlined
, metrics
->tmDefaultChar
, metrics
->tmOverhang
,
1428 metrics
->tmStruckOut
, metrics
->tmBreakChar
, metrics
->tmCharSet
,
1429 metrics
->tmPitchAndFamily
,
1430 metrics
->tmInternalLeading
,
1433 metrics
->tmHeight
);
1435 GDI_ReleaseObj( hdc
);
1440 /***********************************************************************
1441 * GetOutlineTextMetrics [GDI.308] Gets metrics for TrueType fonts.
1444 * lpOTM should be LPOUTLINETEXTMETRIC
1447 * Success: Non-zero or size of required buffer
1450 UINT16 WINAPI
GetOutlineTextMetrics16(
1451 HDC16 hdc
, /* [in] Handle of device context */
1452 UINT16 cbData
, /* [in] Size of metric data array */
1453 LPOUTLINETEXTMETRIC16 lpOTM
) /* [out] Address of metric data array */
1455 FIXME("(%04x,%04x,%p): stub\n", hdc
,cbData
,lpOTM
);
1460 /***********************************************************************
1461 * GetOutlineTextMetricsA (GDI32.@)
1462 * Gets metrics for TrueType fonts.
1465 * If the supplied buffer isn't big enough Windows partially fills it up to
1466 * its given length and returns that length.
1469 * Success: Non-zero or size of required buffer
1472 UINT WINAPI
GetOutlineTextMetricsA(
1473 HDC hdc
, /* [in] Handle of device context */
1474 UINT cbData
, /* [in] Size of metric data array */
1475 LPOUTLINETEXTMETRICA lpOTM
) /* [out] Address of metric data array */
1477 char buf
[512], *ptr
;
1479 OUTLINETEXTMETRICW
*lpOTMW
= (OUTLINETEXTMETRICW
*)buf
;
1480 OUTLINETEXTMETRICA
*output
= lpOTM
;
1483 if((ret
= GetOutlineTextMetricsW(hdc
, 0, NULL
)) == 0)
1485 if(ret
> sizeof(buf
))
1486 lpOTMW
= HeapAlloc(GetProcessHeap(), 0, ret
);
1487 GetOutlineTextMetricsW(hdc
, ret
, lpOTMW
);
1489 needed
= sizeof(OUTLINETEXTMETRICA
);
1490 if(lpOTMW
->otmpFamilyName
)
1491 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1492 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFamilyName
), -1,
1493 NULL
, 0, NULL
, NULL
);
1494 if(lpOTMW
->otmpFaceName
)
1495 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1496 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFaceName
), -1,
1497 NULL
, 0, NULL
, NULL
);
1498 if(lpOTMW
->otmpStyleName
)
1499 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1500 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpStyleName
), -1,
1501 NULL
, 0, NULL
, NULL
);
1502 if(lpOTMW
->otmpFullName
)
1503 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1504 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFullName
), -1,
1505 NULL
, 0, NULL
, NULL
);
1512 TRACE("needed = %d\n", needed
);
1514 /* Since the supplied buffer isn't big enough, we'll alloc one
1515 that is and memcpy the first cbData bytes into the lpOTM at
1517 output
= HeapAlloc(GetProcessHeap(), 0, needed
);
1519 ret
= output
->otmSize
= min(needed
, cbData
);
1520 FONT_TextMetricWToA( &lpOTMW
->otmTextMetrics
, &output
->otmTextMetrics
);
1521 output
->otmFiller
= 0;
1522 output
->otmPanoseNumber
= lpOTMW
->otmPanoseNumber
;
1523 output
->otmfsSelection
= lpOTMW
->otmfsSelection
;
1524 output
->otmfsType
= lpOTMW
->otmfsType
;
1525 output
->otmsCharSlopeRise
= lpOTMW
->otmsCharSlopeRise
;
1526 output
->otmsCharSlopeRun
= lpOTMW
->otmsCharSlopeRun
;
1527 output
->otmItalicAngle
= lpOTMW
->otmItalicAngle
;
1528 output
->otmEMSquare
= lpOTMW
->otmEMSquare
;
1529 output
->otmAscent
= lpOTMW
->otmAscent
;
1530 output
->otmDescent
= lpOTMW
->otmDescent
;
1531 output
->otmLineGap
= lpOTMW
->otmLineGap
;
1532 output
->otmsCapEmHeight
= lpOTMW
->otmsCapEmHeight
;
1533 output
->otmsXHeight
= lpOTMW
->otmsXHeight
;
1534 output
->otmrcFontBox
= lpOTMW
->otmrcFontBox
;
1535 output
->otmMacAscent
= lpOTMW
->otmMacAscent
;
1536 output
->otmMacDescent
= lpOTMW
->otmMacDescent
;
1537 output
->otmMacLineGap
= lpOTMW
->otmMacLineGap
;
1538 output
->otmusMinimumPPEM
= lpOTMW
->otmusMinimumPPEM
;
1539 output
->otmptSubscriptSize
= lpOTMW
->otmptSubscriptSize
;
1540 output
->otmptSubscriptOffset
= lpOTMW
->otmptSubscriptOffset
;
1541 output
->otmptSuperscriptSize
= lpOTMW
->otmptSuperscriptSize
;
1542 output
->otmptSuperscriptOffset
= lpOTMW
->otmptSuperscriptOffset
;
1543 output
->otmsStrikeoutSize
= lpOTMW
->otmsStrikeoutSize
;
1544 output
->otmsStrikeoutPosition
= lpOTMW
->otmsStrikeoutPosition
;
1545 output
->otmsUnderscoreSize
= lpOTMW
->otmsUnderscoreSize
;
1546 output
->otmsUnderscorePosition
= lpOTMW
->otmsUnderscorePosition
;
1549 ptr
= (char*)(output
+ 1);
1550 left
= needed
- sizeof(*output
);
1552 if(lpOTMW
->otmpFamilyName
) {
1553 output
->otmpFamilyName
= (LPSTR
)(ptr
- (char*)output
);
1554 len
= WideCharToMultiByte(CP_ACP
, 0,
1555 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFamilyName
), -1,
1556 ptr
, left
, NULL
, NULL
);
1560 output
->otmpFamilyName
= 0;
1562 if(lpOTMW
->otmpFaceName
) {
1563 output
->otmpFaceName
= (LPSTR
)(ptr
- (char*)output
);
1564 len
= WideCharToMultiByte(CP_ACP
, 0,
1565 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFaceName
), -1,
1566 ptr
, left
, NULL
, NULL
);
1570 output
->otmpFaceName
= 0;
1572 if(lpOTMW
->otmpStyleName
) {
1573 output
->otmpStyleName
= (LPSTR
)(ptr
- (char*)output
);
1574 len
= WideCharToMultiByte(CP_ACP
, 0,
1575 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpStyleName
), -1,
1576 ptr
, left
, NULL
, NULL
);
1580 output
->otmpStyleName
= 0;
1582 if(lpOTMW
->otmpFullName
) {
1583 output
->otmpFullName
= (LPSTR
)(ptr
- (char*)output
);
1584 len
= WideCharToMultiByte(CP_ACP
, 0,
1585 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFullName
), -1,
1586 ptr
, left
, NULL
, NULL
);
1589 output
->otmpFullName
= 0;
1593 if(output
!= lpOTM
) {
1594 memcpy(lpOTM
, output
, cbData
);
1595 HeapFree(GetProcessHeap(), 0, output
);
1597 /* check if the string offsets really fit into the provided size */
1598 /* FIXME: should we check string length as well? */
1599 /* make sure that we don't read/write beyond the provided buffer */
1600 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFamilyName
) + sizeof(LPSTR
))
1602 if ((UINT_PTR
)lpOTM
->otmpFamilyName
>= lpOTM
->otmSize
)
1603 lpOTM
->otmpFamilyName
= 0; /* doesn't fit */
1606 /* make sure that we don't read/write beyond the provided buffer */
1607 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFaceName
) + sizeof(LPSTR
))
1609 if ((UINT_PTR
)lpOTM
->otmpFaceName
>= lpOTM
->otmSize
)
1610 lpOTM
->otmpFaceName
= 0; /* doesn't fit */
1613 /* make sure that we don't read/write beyond the provided buffer */
1614 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpStyleName
) + sizeof(LPSTR
))
1616 if ((UINT_PTR
)lpOTM
->otmpStyleName
>= lpOTM
->otmSize
)
1617 lpOTM
->otmpStyleName
= 0; /* doesn't fit */
1620 /* make sure that we don't read/write beyond the provided buffer */
1621 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFullName
) + sizeof(LPSTR
))
1623 if ((UINT_PTR
)lpOTM
->otmpFullName
>= lpOTM
->otmSize
)
1624 lpOTM
->otmpFullName
= 0; /* doesn't fit */
1629 if(lpOTMW
!= (OUTLINETEXTMETRICW
*)buf
)
1630 HeapFree(GetProcessHeap(), 0, lpOTMW
);
1636 /***********************************************************************
1637 * GetOutlineTextMetricsW [GDI32.@]
1639 UINT WINAPI
GetOutlineTextMetricsW(
1640 HDC hdc
, /* [in] Handle of device context */
1641 UINT cbData
, /* [in] Size of metric data array */
1642 LPOUTLINETEXTMETRICW lpOTM
) /* [out] Address of metric data array */
1644 DC
*dc
= DC_GetDCPtr( hdc
);
1645 OUTLINETEXTMETRICW
*output
= lpOTM
;
1648 TRACE("(%p,%d,%p)\n", hdc
, cbData
, lpOTM
);
1652 ret
= WineEngGetOutlineTextMetrics(dc
->gdiFont
, cbData
, output
);
1655 output
= HeapAlloc(GetProcessHeap(), 0, ret
);
1656 WineEngGetOutlineTextMetrics(dc
->gdiFont
, ret
, output
);
1659 #define WDPTOLP(x) ((x<0)? \
1660 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1661 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1662 #define HDPTOLP(y) ((y<0)? \
1663 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1664 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1666 output
->otmTextMetrics
.tmHeight
= HDPTOLP(output
->otmTextMetrics
.tmHeight
);
1667 output
->otmTextMetrics
.tmAscent
= HDPTOLP(output
->otmTextMetrics
.tmAscent
);
1668 output
->otmTextMetrics
.tmDescent
= HDPTOLP(output
->otmTextMetrics
.tmDescent
);
1669 output
->otmTextMetrics
.tmInternalLeading
= HDPTOLP(output
->otmTextMetrics
.tmInternalLeading
);
1670 output
->otmTextMetrics
.tmExternalLeading
= HDPTOLP(output
->otmTextMetrics
.tmExternalLeading
);
1671 output
->otmTextMetrics
.tmAveCharWidth
= WDPTOLP(output
->otmTextMetrics
.tmAveCharWidth
);
1672 output
->otmTextMetrics
.tmMaxCharWidth
= WDPTOLP(output
->otmTextMetrics
.tmMaxCharWidth
);
1673 output
->otmTextMetrics
.tmOverhang
= WDPTOLP(output
->otmTextMetrics
.tmOverhang
);
1674 output
->otmAscent
= HDPTOLP(output
->otmAscent
);
1675 output
->otmDescent
= HDPTOLP(output
->otmDescent
);
1676 output
->otmLineGap
= HDPTOLP(output
->otmLineGap
);
1677 output
->otmsCapEmHeight
= HDPTOLP(output
->otmsCapEmHeight
);
1678 output
->otmsXHeight
= HDPTOLP(output
->otmsXHeight
);
1679 output
->otmrcFontBox
.top
= HDPTOLP(output
->otmrcFontBox
.top
);
1680 output
->otmrcFontBox
.bottom
= HDPTOLP(output
->otmrcFontBox
.bottom
);
1681 output
->otmrcFontBox
.left
= WDPTOLP(output
->otmrcFontBox
.left
);
1682 output
->otmrcFontBox
.right
= WDPTOLP(output
->otmrcFontBox
.right
);
1683 output
->otmMacAscent
= HDPTOLP(output
->otmMacAscent
);
1684 output
->otmMacDescent
= HDPTOLP(output
->otmMacDescent
);
1685 output
->otmMacLineGap
= HDPTOLP(output
->otmMacLineGap
);
1686 output
->otmptSubscriptSize
.x
= WDPTOLP(output
->otmptSubscriptSize
.x
);
1687 output
->otmptSubscriptSize
.y
= HDPTOLP(output
->otmptSubscriptSize
.y
);
1688 output
->otmptSubscriptOffset
.x
= WDPTOLP(output
->otmptSubscriptOffset
.x
);
1689 output
->otmptSubscriptOffset
.y
= HDPTOLP(output
->otmptSubscriptOffset
.y
);
1690 output
->otmptSuperscriptSize
.x
= WDPTOLP(output
->otmptSuperscriptSize
.x
);
1691 output
->otmptSuperscriptSize
.y
= HDPTOLP(output
->otmptSuperscriptSize
.y
);
1692 output
->otmptSuperscriptOffset
.x
= WDPTOLP(output
->otmptSuperscriptOffset
.x
);
1693 output
->otmptSuperscriptOffset
.y
= HDPTOLP(output
->otmptSuperscriptOffset
.y
);
1694 output
->otmsStrikeoutSize
= HDPTOLP(output
->otmsStrikeoutSize
);
1695 output
->otmsStrikeoutPosition
= HDPTOLP(output
->otmsStrikeoutPosition
);
1696 output
->otmsUnderscoreSize
= HDPTOLP(output
->otmsUnderscoreSize
);
1697 output
->otmsUnderscorePosition
= HDPTOLP(output
->otmsUnderscorePosition
);
1700 if(output
!= lpOTM
) {
1701 memcpy(lpOTM
, output
, cbData
);
1702 HeapFree(GetProcessHeap(), 0, output
);
1708 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1709 but really this should just be a return 0. */
1711 ret
= sizeof(*lpOTM
);
1716 memset(lpOTM
, 0, ret
);
1717 lpOTM
->otmSize
= sizeof(*lpOTM
);
1718 GetTextMetricsW(hdc
, &lpOTM
->otmTextMetrics
);
1720 Further fill of the structure not implemented,
1721 Needs real values for the structure members
1726 GDI_ReleaseObj(hdc
);
1731 /***********************************************************************
1732 * GetCharWidthW (GDI32.@)
1733 * GetCharWidth32W (GDI32.@)
1735 BOOL WINAPI
GetCharWidth32W( HDC hdc
, UINT firstChar
, UINT lastChar
,
1740 DC
* dc
= DC_GetDCPtr( hdc
);
1741 if (!dc
) return FALSE
;
1744 ret
= WineEngGetCharWidth( dc
->gdiFont
, firstChar
, lastChar
, buffer
);
1745 else if (dc
->funcs
->pGetCharWidth
)
1746 ret
= dc
->funcs
->pGetCharWidth( dc
->physDev
, firstChar
, lastChar
, buffer
);
1750 /* convert device units to logical */
1751 for( i
= firstChar
; i
<= lastChar
; i
++, buffer
++ )
1752 *buffer
= INTERNAL_XDSTOWS(dc
, *buffer
);
1755 GDI_ReleaseObj( hdc
);
1760 /***********************************************************************
1761 * GetCharWidthA (GDI32.@)
1762 * GetCharWidth32A (GDI32.@)
1764 BOOL WINAPI
GetCharWidth32A( HDC hdc
, UINT firstChar
, UINT lastChar
,
1767 INT i
, wlen
, count
= (INT
)(lastChar
- firstChar
+ 1);
1772 if(count
<= 0) return FALSE
;
1774 str
= HeapAlloc(GetProcessHeap(), 0, count
);
1775 for(i
= 0; i
< count
; i
++)
1776 str
[i
] = (BYTE
)(firstChar
+ i
);
1778 wstr
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
1780 for(i
= 0; i
< wlen
; i
++)
1782 if(!GetCharWidth32W(hdc
, wstr
[i
], wstr
[i
], buffer
))
1790 HeapFree(GetProcessHeap(), 0, str
);
1791 HeapFree(GetProcessHeap(), 0, wstr
);
1797 /***********************************************************************
1798 * ExtTextOutA (GDI32.@)
1802 BOOL WINAPI
ExtTextOutA( HDC hdc
, INT x
, INT y
, UINT flags
,
1803 const RECT
*lprect
, LPCSTR str
, UINT count
, const INT
*lpDx
)
1812 if (flags
& ETO_GLYPH_INDEX
)
1813 return ExtTextOutW( hdc
, x
, y
, flags
, lprect
, (LPCWSTR
)str
, count
, lpDx
);
1815 if(GetObjectType(hdc
) != OBJ_METADC
) {
1816 p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, &codepage
);
1819 unsigned int i
= 0, j
= 0;
1821 lpDxW
= HeapAlloc( GetProcessHeap(), 0, wlen
*sizeof(INT
));
1823 if(IsDBCSLeadByteEx(codepage
, str
[i
])) {
1824 lpDxW
[j
++] = lpDx
[i
] + lpDx
[i
+1];
1827 lpDxW
[j
++] = lpDx
[i
];
1832 } else { /* Special case for metafiles. Just do a straight copy */
1833 p
= HeapAlloc(GetProcessHeap(), 0, (count
+ 1) * sizeof(WCHAR
));
1834 for(i
= 0; i
< count
; i
++)
1835 p
[i
] = (BYTE
)str
[i
];
1839 lpDxW
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(INT
));
1840 for(i
= 0; i
< count
; i
++)
1845 ret
= ExtTextOutW( hdc
, x
, y
, flags
, lprect
, p
, wlen
, lpDxW
);
1847 HeapFree( GetProcessHeap(), 0, p
);
1848 HeapFree( GetProcessHeap(), 0, lpDxW
);
1853 /***********************************************************************
1854 * ExtTextOutW (GDI32.@)
1856 * Draws text using the currently selected font, background color, and text color.
1860 * x,y [I] coordinates of string
1862 * ETO_GRAYED - undocumented on MSDN
1863 * ETO_OPAQUE - use background color for fill the rectangle
1864 * ETO_CLIPPED - clipping text to the rectangle
1865 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1866 * than encoded characters. Implies ETO_IGNORELANGUAGE
1867 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1868 * Affects BiDi ordering
1869 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1870 * ETO_PDY - unimplemented
1871 * ETO_NUMERICSLATIN - unimplemented always assumed -
1872 * do not translate numbers into locale representations
1873 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1874 * lprect [I] dimensions for clipping or/and opaquing
1875 * str [I] text string
1876 * count [I] number of symbols in string
1877 * lpDx [I] optional parameter with distance between drawing characters
1883 BOOL WINAPI
ExtTextOutW( HDC hdc
, INT x
, INT y
, UINT flags
,
1884 const RECT
*lprect
, LPCWSTR str
, UINT count
, const INT
*lpDx
)
1887 LPWSTR reordered_str
= (LPWSTR
)str
;
1888 WORD
*glyphs
= NULL
;
1889 UINT align
= GetTextAlign( hdc
);
1893 double cosEsc
, sinEsc
;
1894 INT
*deltas
= NULL
, char_extra
;
1897 BOOL done_extents
= FALSE
;
1898 INT width
= 0, xwidth
= 0, ywidth
= 0;
1900 DC
* dc
= DC_GetDCUpdate( hdc
);
1903 if (!dc
) return FALSE
;
1905 breakRem
= dc
->breakRem
;
1907 if (flags
& (ETO_NUMERICSLOCAL
| ETO_NUMERICSLATIN
| ETO_PDY
))
1908 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY unimplemented\n");
1910 if (!dc
->funcs
->pExtTextOut
&& !PATH_IsPathOpen(dc
->path
))
1912 GDI_ReleaseObj( hdc
);
1916 type
= GetObjectType(hdc
);
1917 if(type
== OBJ_METADC
|| type
== OBJ_ENHMETADC
)
1919 ret
= dc
->funcs
->pExtTextOut(dc
->physDev
, x
, y
, flags
, lprect
, str
, count
, lpDx
);
1920 GDI_ReleaseObj( hdc
);
1925 flags
&= ~ETO_CLIPPED
;
1927 if( !(flags
& (ETO_GLYPH_INDEX
| ETO_IGNORELANGUAGE
)) && BidiAvail
&& count
> 0 )
1929 reordered_str
= HeapAlloc(GetProcessHeap(), 0, count
*sizeof(WCHAR
));
1931 BIDI_Reorder( str
, count
, GCP_REORDER
,
1932 ((flags
&ETO_RTLREADING
)!=0 || (GetTextAlign(hdc
)&TA_RTLREADING
)!=0)?
1933 WINE_GCPW_FORCE_RTL
:WINE_GCPW_FORCE_LTR
,
1934 reordered_str
, count
, NULL
);
1936 flags
|= ETO_IGNORELANGUAGE
;
1939 TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc
, x
, y
, flags
,
1940 lprect
, debugstr_wn(str
, count
), count
, lpDx
);
1942 if(flags
& ETO_GLYPH_INDEX
)
1943 glyphs
= reordered_str
;
1946 TRACE("rect: %d,%d - %d,%d\n", lprect
->left
, lprect
->top
, lprect
->right
,
1948 TRACE("align = %x bkmode = %x mapmode = %x\n", align
, GetBkMode(hdc
), GetMapMode(hdc
));
1950 if(align
& TA_UPDATECP
)
1952 GetCurrentPositionEx( hdc
, &pt
);
1957 GetTextMetricsW(hdc
, &tm
);
1958 GetObjectW(GetCurrentObject(hdc
, OBJ_FONT
), sizeof(lf
), &lf
);
1960 if(!(tm
.tmPitchAndFamily
& TMPF_VECTOR
)) /* Non-scalable fonts shouldn't be rotated */
1961 lf
.lfEscapement
= 0;
1963 if(lf
.lfEscapement
!= 0)
1965 cosEsc
= cos(lf
.lfEscapement
* M_PI
/ 1800);
1966 sinEsc
= sin(lf
.lfEscapement
* M_PI
/ 1800);
1974 if(flags
& (ETO_CLIPPED
| ETO_OPAQUE
))
1978 if(flags
& ETO_GLYPH_INDEX
)
1979 GetTextExtentPointI(hdc
, glyphs
, count
, &sz
);
1981 GetTextExtentPointW(hdc
, reordered_str
, count
, &sz
);
1983 done_extents
= TRUE
;
1986 rc
.right
= x
+ sz
.cx
;
1987 rc
.bottom
= y
+ sz
.cy
;
1994 LPtoDP(hdc
, (POINT
*)&rc
, 2);
1996 if(rc
.left
> rc
.right
) {INT tmp
= rc
.left
; rc
.left
= rc
.right
; rc
.right
= tmp
;}
1997 if(rc
.top
> rc
.bottom
) {INT tmp
= rc
.top
; rc
.top
= rc
.bottom
; rc
.bottom
= tmp
;}
2000 if ((flags
& ETO_OPAQUE
) && !PATH_IsPathOpen(dc
->path
))
2001 dc
->funcs
->pExtTextOut(dc
->physDev
, 0, 0, ETO_OPAQUE
, &rc
, NULL
, 0, NULL
);
2011 LPtoDP(hdc
, &pt
, 1);
2015 char_extra
= GetTextCharacterExtra(hdc
);
2016 if(char_extra
|| dc
->breakExtra
|| breakRem
|| lpDx
)
2020 deltas
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(INT
));
2021 for(i
= 0; i
< count
; i
++)
2023 if(lpDx
&& (flags
& ETO_PDY
))
2024 deltas
[i
] = lpDx
[i
*2] + char_extra
;
2026 deltas
[i
] = lpDx
[i
] + char_extra
;
2029 if(flags
& ETO_GLYPH_INDEX
)
2030 GetTextExtentPointI(hdc
, glyphs
+ i
, 1, &tmpsz
);
2032 GetTextExtentPointW(hdc
, reordered_str
+ i
, 1, &tmpsz
);
2034 deltas
[i
] = tmpsz
.cx
;
2037 if (!(flags
& ETO_GLYPH_INDEX
) && (dc
->breakExtra
|| breakRem
) && reordered_str
[i
] == tm
.tmBreakChar
)
2039 deltas
[i
] = deltas
[i
] + dc
->breakExtra
;
2046 deltas
[i
] = INTERNAL_XWSTODS(dc
, deltas
[i
]);
2054 if(flags
& ETO_GLYPH_INDEX
)
2055 GetTextExtentPointI(hdc
, glyphs
, count
, &sz
);
2057 GetTextExtentPointW(hdc
, reordered_str
, count
, &sz
);
2058 done_extents
= TRUE
;
2060 width
= INTERNAL_XWSTODS(dc
, sz
.cx
);
2062 xwidth
= width
* cosEsc
;
2063 ywidth
= width
* sinEsc
;
2065 tm
.tmAscent
= abs(INTERNAL_YWSTODS(dc
, tm
.tmAscent
));
2066 tm
.tmDescent
= abs(INTERNAL_YWSTODS(dc
, tm
.tmDescent
));
2067 switch( align
& (TA_LEFT
| TA_RIGHT
| TA_CENTER
) )
2070 if (align
& TA_UPDATECP
)
2074 DPtoLP(hdc
, &pt
, 1);
2075 MoveToEx(hdc
, pt
.x
, pt
.y
, NULL
);
2087 if (align
& TA_UPDATECP
)
2091 DPtoLP(hdc
, &pt
, 1);
2092 MoveToEx(hdc
, pt
.x
, pt
.y
, NULL
);
2097 switch( align
& (TA_TOP
| TA_BOTTOM
| TA_BASELINE
) )
2100 y
+= tm
.tmAscent
* cosEsc
;
2101 x
+= tm
.tmAscent
* sinEsc
;
2105 y
-= tm
.tmDescent
* cosEsc
;
2106 x
-= tm
.tmDescent
* sinEsc
;
2113 if (GetBkMode(hdc
) != TRANSPARENT
&& !PATH_IsPathOpen(dc
->path
))
2115 if(!((flags
& ETO_CLIPPED
) && (flags
& ETO_OPAQUE
)))
2117 if(!(flags
& ETO_OPAQUE
) || x
< rc
.left
|| x
+ width
>= rc
.right
||
2118 y
- tm
.tmAscent
< rc
.top
|| y
+ tm
.tmDescent
>= rc
.bottom
)
2122 rc
.right
= x
+ width
;
2123 rc
.top
= y
- tm
.tmAscent
;
2124 rc
.bottom
= y
+ tm
.tmDescent
;
2125 dc
->funcs
->pExtTextOut(dc
->physDev
, 0, 0, ETO_OPAQUE
, &rc
, NULL
, 0, NULL
);
2130 if(FontIsLinked(hdc
) && !(flags
& ETO_GLYPH_INDEX
))
2132 HFONT orig_font
= dc
->hFont
, cur_font
;
2134 INT span
= 0, *offsets
= NULL
, i
;
2136 glyphs
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(WORD
));
2137 for(i
= 0; i
< count
; i
++)
2139 WineEngGetLinkedHFont(dc
, reordered_str
[i
], &cur_font
, &glyph
);
2140 if(cur_font
!= dc
->hFont
)
2145 offsets
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(*deltas
));
2150 for(j
= 1; j
< count
; j
++)
2152 GetTextExtentPointW(hdc
, reordered_str
+ j
- 1, 1, &tmpsz
);
2153 offsets
[j
] = offsets
[j
-1] + INTERNAL_XWSTODS(dc
, tmpsz
.cx
);
2158 for(j
= 1; j
< count
; j
++)
2159 offsets
[j
] = offsets
[j
-1] + deltas
[j
];
2164 if (PATH_IsPathOpen(dc
->path
))
2165 ret
= PATH_ExtTextOut(dc
, x
+ offsets
[i
- span
] * cosEsc
, y
- offsets
[i
- span
] * sinEsc
,
2166 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
,
2167 glyphs
, span
, deltas
? deltas
+ i
- span
: NULL
);
2169 dc
->funcs
->pExtTextOut(dc
->physDev
, x
+ offsets
[i
- span
] * cosEsc
, y
- offsets
[i
- span
] * sinEsc
,
2170 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
,
2171 glyphs
, span
, deltas
? deltas
+ i
- span
: NULL
);
2174 SelectObject(hdc
, cur_font
);
2176 glyphs
[span
++] = glyph
;
2180 if (PATH_IsPathOpen(dc
->path
))
2181 ret
= PATH_ExtTextOut(dc
, x
+ (offsets
? offsets
[count
- span
] * cosEsc
: 0),
2182 y
- (offsets
? offsets
[count
- span
] * sinEsc
: 0),
2183 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
,
2184 glyphs
, span
, deltas
? deltas
+ count
- span
: NULL
);
2186 ret
= dc
->funcs
->pExtTextOut(dc
->physDev
, x
+ (offsets
? offsets
[count
- span
] * cosEsc
: 0),
2187 y
- (offsets
? offsets
[count
- span
] * sinEsc
: 0),
2188 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
,
2189 glyphs
, span
, deltas
? deltas
+ count
- span
: NULL
);
2190 SelectObject(hdc
, orig_font
);
2191 HeapFree(GetProcessHeap(), 0, offsets
);
2197 if(!(flags
& ETO_GLYPH_INDEX
) && dc
->gdiFont
)
2199 glyphs
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(WORD
));
2200 GetGlyphIndicesW(hdc
, reordered_str
, count
, glyphs
, 0);
2201 flags
|= ETO_GLYPH_INDEX
;
2204 if (PATH_IsPathOpen(dc
->path
))
2205 ret
= PATH_ExtTextOut(dc
, x
, y
, (flags
& ~ETO_OPAQUE
), &rc
,
2206 glyphs
? glyphs
: reordered_str
, count
, deltas
);
2208 ret
= dc
->funcs
->pExtTextOut(dc
->physDev
, x
, y
, (flags
& ~ETO_OPAQUE
), &rc
,
2209 glyphs
? glyphs
: reordered_str
, count
, deltas
);
2213 HeapFree(GetProcessHeap(), 0, deltas
);
2214 if(glyphs
!= reordered_str
)
2215 HeapFree(GetProcessHeap(), 0, glyphs
);
2216 if(reordered_str
!= str
)
2217 HeapFree(GetProcessHeap(), 0, reordered_str
);
2219 GDI_ReleaseObj( hdc
);
2221 if (ret
&& (lf
.lfUnderline
|| lf
.lfStrikeOut
))
2223 int underlinePos
, strikeoutPos
;
2224 int underlineWidth
, strikeoutWidth
;
2225 UINT size
= GetOutlineTextMetricsW(hdc
, 0, NULL
);
2226 OUTLINETEXTMETRICW
* otm
= NULL
;
2231 underlineWidth
= tm
.tmAscent
/ 20 + 1;
2232 strikeoutPos
= tm
.tmAscent
/ 2;
2233 strikeoutWidth
= underlineWidth
;
2237 otm
= HeapAlloc(GetProcessHeap(), 0, size
);
2238 GetOutlineTextMetricsW(hdc
, size
, otm
);
2239 underlinePos
= otm
->otmsUnderscorePosition
;
2240 underlineWidth
= otm
->otmsUnderscoreSize
;
2241 strikeoutPos
= otm
->otmsStrikeoutPosition
;
2242 strikeoutWidth
= otm
->otmsStrikeoutSize
;
2243 HeapFree(GetProcessHeap(), 0, otm
);
2246 if (PATH_IsPathOpen(dc
->path
))
2250 HBRUSH hbrush
= CreateSolidBrush(GetTextColor(hdc
));
2252 hbrush
= SelectObject(hdc
, hbrush
);
2253 hpen
= SelectObject(hdc
, GetStockObject(NULL_PEN
));
2257 pts
[0].x
= x
- underlinePos
* sinEsc
;
2258 pts
[0].y
= y
- underlinePos
* cosEsc
;
2259 pts
[1].x
= x
+ xwidth
- underlinePos
* sinEsc
;
2260 pts
[1].y
= y
- ywidth
- underlinePos
* cosEsc
;
2261 pts
[2].x
= pts
[1].x
+ underlineWidth
* sinEsc
;
2262 pts
[2].y
= pts
[1].y
+ underlineWidth
* cosEsc
;
2263 pts
[3].x
= pts
[0].x
+ underlineWidth
* sinEsc
;
2264 pts
[3].y
= pts
[0].y
+ underlineWidth
* cosEsc
;
2265 pts
[4].x
= pts
[0].x
;
2266 pts
[4].y
= pts
[0].y
;
2267 DPtoLP(hdc
, pts
, 5);
2268 Polygon(hdc
, pts
, 5);
2273 pts
[0].x
= x
- strikeoutPos
* sinEsc
;
2274 pts
[0].y
= y
- strikeoutPos
* cosEsc
;
2275 pts
[1].x
= x
+ xwidth
- strikeoutPos
* sinEsc
;
2276 pts
[1].y
= y
- ywidth
- strikeoutPos
* cosEsc
;
2277 pts
[2].x
= pts
[1].x
+ strikeoutWidth
* sinEsc
;
2278 pts
[2].y
= pts
[1].y
+ strikeoutWidth
* cosEsc
;
2279 pts
[3].x
= pts
[0].x
+ strikeoutWidth
* sinEsc
;
2280 pts
[3].y
= pts
[0].y
+ strikeoutWidth
* cosEsc
;
2281 pts
[4].x
= pts
[0].x
;
2282 pts
[4].y
= pts
[0].y
;
2283 DPtoLP(hdc
, pts
, 5);
2284 Polygon(hdc
, pts
, 5);
2287 SelectObject(hdc
, hpen
);
2288 hbrush
= SelectObject(hdc
, hbrush
);
2289 DeleteObject(hbrush
);
2293 POINT pts
[2], oldpt
;
2298 hpen
= CreatePen(PS_SOLID
, underlineWidth
, GetTextColor(hdc
));
2299 hpen
= SelectObject(hdc
, hpen
);
2302 pts
[1].x
= x
+ xwidth
;
2303 pts
[1].y
= y
- ywidth
;
2304 DPtoLP(hdc
, pts
, 2);
2305 MoveToEx(hdc
, pts
[0].x
- underlinePos
* sinEsc
, pts
[0].y
- underlinePos
* cosEsc
, &oldpt
);
2306 LineTo(hdc
, pts
[1].x
- underlinePos
* sinEsc
, pts
[1].y
- underlinePos
* cosEsc
);
2307 MoveToEx(hdc
, oldpt
.x
, oldpt
.y
, NULL
);
2308 DeleteObject(SelectObject(hdc
, hpen
));
2313 hpen
= CreatePen(PS_SOLID
, strikeoutWidth
, GetTextColor(hdc
));
2314 hpen
= SelectObject(hdc
, hpen
);
2317 pts
[1].x
= x
+ xwidth
;
2318 pts
[1].y
= y
- ywidth
;
2319 DPtoLP(hdc
, pts
, 2);
2320 MoveToEx(hdc
, pts
[0].x
- strikeoutPos
* sinEsc
, pts
[0].y
- strikeoutPos
* cosEsc
, &oldpt
);
2321 LineTo(hdc
, pts
[1].x
- strikeoutPos
* sinEsc
, pts
[1].y
- strikeoutPos
* cosEsc
);
2322 MoveToEx(hdc
, oldpt
.x
, oldpt
.y
, NULL
);
2323 DeleteObject(SelectObject(hdc
, hpen
));
2332 /***********************************************************************
2333 * TextOutA (GDI32.@)
2335 BOOL WINAPI
TextOutA( HDC hdc
, INT x
, INT y
, LPCSTR str
, INT count
)
2337 return ExtTextOutA( hdc
, x
, y
, 0, NULL
, str
, count
, NULL
);
2341 /***********************************************************************
2342 * TextOutW (GDI32.@)
2344 BOOL WINAPI
TextOutW(HDC hdc
, INT x
, INT y
, LPCWSTR str
, INT count
)
2346 return ExtTextOutW( hdc
, x
, y
, 0, NULL
, str
, count
, NULL
);
2350 /***********************************************************************
2351 * PolyTextOutA (GDI32.@)
2355 BOOL WINAPI
PolyTextOutA ( HDC hdc
, /* [in] Handle to device context */
2356 PPOLYTEXTA pptxt
, /* [in] Array of strings */
2357 INT cStrings
) /* [in] Number of strings in array */
2359 for (; cStrings
>0; cStrings
--, pptxt
++)
2360 if (!ExtTextOutA( hdc
, pptxt
->x
, pptxt
->y
, pptxt
->uiFlags
, &pptxt
->rcl
, pptxt
->lpstr
, pptxt
->n
, pptxt
->pdx
))
2367 /***********************************************************************
2368 * PolyTextOutW (GDI32.@)
2370 * Draw several Strings
2376 BOOL WINAPI
PolyTextOutW ( HDC hdc
, /* [in] Handle to device context */
2377 PPOLYTEXTW pptxt
, /* [in] Array of strings */
2378 INT cStrings
) /* [in] Number of strings in array */
2380 for (; cStrings
>0; cStrings
--, pptxt
++)
2381 if (!ExtTextOutW( hdc
, pptxt
->x
, pptxt
->y
, pptxt
->uiFlags
, &pptxt
->rcl
, pptxt
->lpstr
, pptxt
->n
, pptxt
->pdx
))
2387 /* FIXME: all following APIs ******************************************/
2390 /***********************************************************************
2391 * SetMapperFlags (GDI32.@)
2393 DWORD WINAPI
SetMapperFlags( HDC hDC
, DWORD dwFlag
)
2395 DC
*dc
= DC_GetDCPtr( hDC
);
2398 if(dc
->funcs
->pSetMapperFlags
)
2400 ret
= dc
->funcs
->pSetMapperFlags( dc
->physDev
, dwFlag
);
2401 /* FIXME: ret is just a success flag, we should return a proper value */
2404 FIXME("(%p, 0x%08x): stub - harmless\n", hDC
, dwFlag
);
2405 GDI_ReleaseObj( hDC
);
2409 /***********************************************************************
2410 * GetAspectRatioFilterEx (GDI.486)
2412 BOOL16 WINAPI
GetAspectRatioFilterEx16( HDC16 hdc
, LPSIZE16 pAspectRatio
)
2414 FIXME("(%04x, %p): -- Empty Stub !\n", hdc
, pAspectRatio
);
2418 /***********************************************************************
2419 * GetAspectRatioFilterEx (GDI32.@)
2421 BOOL WINAPI
GetAspectRatioFilterEx( HDC hdc
, LPSIZE pAspectRatio
)
2423 FIXME("(%p, %p): -- Empty Stub !\n", hdc
, pAspectRatio
);
2428 /***********************************************************************
2429 * GetCharABCWidthsA (GDI32.@)
2431 * See GetCharABCWidthsW.
2433 BOOL WINAPI
GetCharABCWidthsA(HDC hdc
, UINT firstChar
, UINT lastChar
,
2436 INT i
, wlen
, count
= (INT
)(lastChar
- firstChar
+ 1);
2441 if(count
<= 0) return FALSE
;
2443 str
= HeapAlloc(GetProcessHeap(), 0, count
);
2444 for(i
= 0; i
< count
; i
++)
2445 str
[i
] = (BYTE
)(firstChar
+ i
);
2447 wstr
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
2449 for(i
= 0; i
< wlen
; i
++)
2451 if(!GetCharABCWidthsW(hdc
, wstr
[i
], wstr
[i
], abc
))
2459 HeapFree(GetProcessHeap(), 0, str
);
2460 HeapFree(GetProcessHeap(), 0, wstr
);
2466 /******************************************************************************
2467 * GetCharABCWidthsW [GDI32.@]
2469 * Retrieves widths of characters in range.
2472 * hdc [I] Handle of device context
2473 * firstChar [I] First character in range to query
2474 * lastChar [I] Last character in range to query
2475 * abc [O] Address of character-width structure
2478 * Only works with TrueType fonts
2484 BOOL WINAPI
GetCharABCWidthsW( HDC hdc
, UINT firstChar
, UINT lastChar
,
2487 DC
*dc
= DC_GetDCPtr(hdc
);
2491 if (!dc
) return FALSE
;
2494 ret
= WineEngGetCharABCWidths( dc
->gdiFont
, firstChar
, lastChar
, abc
);
2500 /* convert device units to logical */
2501 for( i
= firstChar
; i
<= lastChar
; i
++, abc
++ ) {
2502 abc
->abcA
= INTERNAL_XDSTOWS(dc
, abc
->abcA
);
2503 abc
->abcB
= INTERNAL_XDSTOWS(dc
, abc
->abcB
);
2504 abc
->abcC
= INTERNAL_XDSTOWS(dc
, abc
->abcC
);
2509 GDI_ReleaseObj(hdc
);
2514 /******************************************************************************
2515 * GetCharABCWidthsI [GDI32.@]
2517 * Retrieves widths of characters in range.
2520 * hdc [I] Handle of device context
2521 * firstChar [I] First glyphs in range to query
2522 * count [I] Last glyphs in range to query
2523 * pgi [i] Array of glyphs to query
2524 * abc [O] Address of character-width structure
2527 * Only works with TrueType fonts
2533 BOOL WINAPI
GetCharABCWidthsI( HDC hdc
, UINT firstChar
, UINT count
,
2534 LPWORD pgi
, LPABC abc
)
2536 DC
*dc
= DC_GetDCPtr(hdc
);
2540 if (!dc
) return FALSE
;
2543 ret
= WineEngGetCharABCWidthsI( dc
->gdiFont
, firstChar
, count
, pgi
, abc
);
2549 /* convert device units to logical */
2550 for( i
= 0; i
< count
; i
++, abc
++ ) {
2551 abc
->abcA
= INTERNAL_XDSTOWS(dc
, abc
->abcA
);
2552 abc
->abcB
= INTERNAL_XDSTOWS(dc
, abc
->abcB
);
2553 abc
->abcC
= INTERNAL_XDSTOWS(dc
, abc
->abcC
);
2558 GDI_ReleaseObj(hdc
);
2563 /***********************************************************************
2564 * GetGlyphOutlineA (GDI32.@)
2566 DWORD WINAPI
GetGlyphOutlineA( HDC hdc
, UINT uChar
, UINT fuFormat
,
2567 LPGLYPHMETRICS lpgm
, DWORD cbBuffer
,
2568 LPVOID lpBuffer
, const MAT2
*lpmat2
)
2574 if(!(fuFormat
& GGO_GLYPH_INDEX
)) {
2577 if(uChar
> 0xff) { /* but, 2 bytes character only */
2579 mbchs
[0] = (uChar
& 0xff00) >> 8;
2580 mbchs
[1] = (uChar
& 0xff);
2583 mbchs
[0] = (uChar
& 0xff);
2585 p
= FONT_mbtowc(hdc
, mbchs
, len
, NULL
, NULL
);
2589 ret
= GetGlyphOutlineW(hdc
, c
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
,
2591 HeapFree(GetProcessHeap(), 0, p
);
2595 /***********************************************************************
2596 * GetGlyphOutlineW (GDI32.@)
2598 DWORD WINAPI
GetGlyphOutlineW( HDC hdc
, UINT uChar
, UINT fuFormat
,
2599 LPGLYPHMETRICS lpgm
, DWORD cbBuffer
,
2600 LPVOID lpBuffer
, const MAT2
*lpmat2
)
2602 DC
*dc
= DC_GetDCPtr(hdc
);
2605 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2606 hdc
, uChar
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
, lpmat2
);
2608 if(!dc
) return GDI_ERROR
;
2611 ret
= WineEngGetGlyphOutline(dc
->gdiFont
, uChar
, fuFormat
, lpgm
,
2612 cbBuffer
, lpBuffer
, lpmat2
);
2616 GDI_ReleaseObj(hdc
);
2621 /***********************************************************************
2622 * CreateScalableFontResourceA (GDI32.@)
2624 BOOL WINAPI
CreateScalableFontResourceA( DWORD fHidden
,
2625 LPCSTR lpszResourceFile
,
2626 LPCSTR lpszFontFile
,
2627 LPCSTR lpszCurrentPath
)
2631 /* fHidden=1 - only visible for the calling app, read-only, not
2632 * enumbered with EnumFonts/EnumFontFamilies
2633 * lpszCurrentPath can be NULL
2635 FIXME("(%d,%s,%s,%s): stub\n",
2636 fHidden
, debugstr_a(lpszResourceFile
), debugstr_a(lpszFontFile
),
2637 debugstr_a(lpszCurrentPath
) );
2639 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2640 if ((f
= CreateFileA(lpszResourceFile
, 0, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, 0)) != INVALID_HANDLE_VALUE
) {
2642 SetLastError(ERROR_FILE_EXISTS
);
2645 return FALSE
; /* create failed */
2648 /***********************************************************************
2649 * CreateScalableFontResourceW (GDI32.@)
2651 BOOL WINAPI
CreateScalableFontResourceW( DWORD fHidden
,
2652 LPCWSTR lpszResourceFile
,
2653 LPCWSTR lpszFontFile
,
2654 LPCWSTR lpszCurrentPath
)
2656 FIXME("(%d,%p,%p,%p): stub\n",
2657 fHidden
, lpszResourceFile
, lpszFontFile
, lpszCurrentPath
);
2658 return FALSE
; /* create failed */
2661 /*************************************************************************
2662 * GetKerningPairsA (GDI32.@)
2664 DWORD WINAPI
GetKerningPairsA( HDC hDC
, DWORD cPairs
,
2665 LPKERNINGPAIR kern_pairA
)
2670 DWORD i
, total_kern_pairs
, kern_pairs_copied
= 0;
2671 KERNINGPAIR
*kern_pairW
;
2673 if (!cPairs
&& kern_pairA
)
2675 SetLastError(ERROR_INVALID_PARAMETER
);
2679 charset
= GetTextCharset(hDC
);
2680 if (!TranslateCharsetInfo((DWORD
*)charset
, &csi
, TCI_SRCCHARSET
))
2682 FIXME("Can't find codepage for charset %d\n", charset
);
2685 if (!GetCPInfo(csi
.ciACP
, &cpi
))
2687 FIXME("Can't find codepage %u info\n", csi
.ciACP
);
2690 TRACE("charset %d => codepage %u\n", charset
, csi
.ciACP
);
2692 total_kern_pairs
= GetKerningPairsW(hDC
, 0, NULL
);
2693 if (!total_kern_pairs
) return 0;
2695 kern_pairW
= HeapAlloc(GetProcessHeap(), 0, total_kern_pairs
* sizeof(*kern_pairW
));
2696 GetKerningPairsW(hDC
, total_kern_pairs
, kern_pairW
);
2698 for (i
= 0; i
< total_kern_pairs
; i
++)
2702 if (!WideCharToMultiByte(csi
.ciACP
, 0, &kern_pairW
[i
].wFirst
, 1, &first
, 1, NULL
, NULL
))
2705 if (!WideCharToMultiByte(csi
.ciACP
, 0, &kern_pairW
[i
].wSecond
, 1, &second
, 1, NULL
, NULL
))
2708 if (first
== cpi
.DefaultChar
[0] || second
== cpi
.DefaultChar
[0])
2713 if (kern_pairs_copied
>= cPairs
) break;
2715 kern_pairA
->wFirst
= (BYTE
)first
;
2716 kern_pairA
->wSecond
= (BYTE
)second
;
2717 kern_pairA
->iKernAmount
= kern_pairW
[i
].iKernAmount
;
2720 kern_pairs_copied
++;
2723 HeapFree(GetProcessHeap(), 0, kern_pairW
);
2725 return kern_pairs_copied
;
2728 /*************************************************************************
2729 * GetKerningPairsW (GDI32.@)
2731 DWORD WINAPI
GetKerningPairsW( HDC hDC
, DWORD cPairs
,
2732 LPKERNINGPAIR lpKerningPairs
)
2737 TRACE("(%p,%d,%p)\n", hDC
, cPairs
, lpKerningPairs
);
2739 if (!cPairs
&& lpKerningPairs
)
2741 SetLastError(ERROR_INVALID_PARAMETER
);
2745 dc
= DC_GetDCPtr(hDC
);
2749 ret
= WineEngGetKerningPairs(dc
->gdiFont
, cPairs
, lpKerningPairs
);
2751 GDI_ReleaseObj(hDC
);
2755 /*************************************************************************
2756 * TranslateCharsetInfo [GDI32.@]
2758 * Fills a CHARSETINFO structure for a character set, code page, or
2759 * font. This allows making the correspondance between different labelings
2760 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2761 * of the same encoding.
2763 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2764 * only one codepage should be set in *lpSrc.
2767 * TRUE on success, FALSE on failure.
2770 BOOL WINAPI
TranslateCharsetInfo(
2771 LPDWORD lpSrc
, /* [in]
2772 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2773 if flags == TCI_SRCCHARSET: a character set value
2774 if flags == TCI_SRCCODEPAGE: a code page value
2776 LPCHARSETINFO lpCs
, /* [out] structure to receive charset information */
2777 DWORD flags
/* [in] determines interpretation of lpSrc */)
2781 case TCI_SRCFONTSIG
:
2782 while (!(*lpSrc
>>index
& 0x0001) && index
<MAXTCIINDEX
) index
++;
2784 case TCI_SRCCODEPAGE
:
2785 while ((UINT
) (lpSrc
) != FONT_tci
[index
].ciACP
&& index
< MAXTCIINDEX
) index
++;
2787 case TCI_SRCCHARSET
:
2788 while ((UINT
) (lpSrc
) != FONT_tci
[index
].ciCharset
&& index
< MAXTCIINDEX
) index
++;
2793 if (index
>= MAXTCIINDEX
|| FONT_tci
[index
].ciCharset
== DEFAULT_CHARSET
) return FALSE
;
2794 memcpy(lpCs
, &FONT_tci
[index
], sizeof(CHARSETINFO
));
2798 /*************************************************************************
2799 * GetFontLanguageInfo (GDI32.@)
2801 DWORD WINAPI
GetFontLanguageInfo(HDC hdc
)
2803 FONTSIGNATURE fontsig
;
2804 static const DWORD GCP_DBCS_MASK
=0x003F0000,
2805 GCP_DIACRITIC_MASK
=0x00000000,
2806 FLI_GLYPHS_MASK
=0x00000000,
2807 GCP_GLYPHSHAPE_MASK
=0x00000040,
2808 GCP_KASHIDA_MASK
=0x00000000,
2809 GCP_LIGATE_MASK
=0x00000000,
2810 GCP_USEKERNING_MASK
=0x00000000,
2811 GCP_REORDER_MASK
=0x00000060;
2815 GetTextCharsetInfo( hdc
, &fontsig
, 0 );
2816 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2818 if( (fontsig
.fsCsb
[0]&GCP_DBCS_MASK
)!=0 )
2821 if( (fontsig
.fsCsb
[0]&GCP_DIACRITIC_MASK
)!=0 )
2822 result
|=GCP_DIACRITIC
;
2824 if( (fontsig
.fsCsb
[0]&FLI_GLYPHS_MASK
)!=0 )
2827 if( (fontsig
.fsCsb
[0]&GCP_GLYPHSHAPE_MASK
)!=0 )
2828 result
|=GCP_GLYPHSHAPE
;
2830 if( (fontsig
.fsCsb
[0]&GCP_KASHIDA_MASK
)!=0 )
2831 result
|=GCP_KASHIDA
;
2833 if( (fontsig
.fsCsb
[0]&GCP_LIGATE_MASK
)!=0 )
2836 if( (fontsig
.fsCsb
[0]&GCP_USEKERNING_MASK
)!=0 )
2837 result
|=GCP_USEKERNING
;
2839 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2840 if( GetTextAlign( hdc
) & TA_RTLREADING
)
2841 if( (fontsig
.fsCsb
[0]&GCP_REORDER_MASK
)!=0 )
2842 result
|=GCP_REORDER
;
2848 /*************************************************************************
2849 * GetFontData [GDI32.@]
2851 * Retrieve data for TrueType font.
2855 * success: Number of bytes returned
2856 * failure: GDI_ERROR
2860 * Calls SetLastError()
2863 DWORD WINAPI
GetFontData(HDC hdc
, DWORD table
, DWORD offset
,
2864 LPVOID buffer
, DWORD length
)
2866 DC
*dc
= DC_GetDCPtr(hdc
);
2867 DWORD ret
= GDI_ERROR
;
2869 if(!dc
) return GDI_ERROR
;
2872 ret
= WineEngGetFontData(dc
->gdiFont
, table
, offset
, buffer
, length
);
2874 GDI_ReleaseObj(hdc
);
2878 /*************************************************************************
2879 * GetGlyphIndicesA [GDI32.@]
2881 DWORD WINAPI
GetGlyphIndicesA(HDC hdc
, LPCSTR lpstr
, INT count
,
2882 LPWORD pgi
, DWORD flags
)
2888 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2889 hdc
, debugstr_an(lpstr
, count
), count
, pgi
, flags
);
2891 lpstrW
= FONT_mbtowc(hdc
, lpstr
, count
, &countW
, NULL
);
2892 ret
= GetGlyphIndicesW(hdc
, lpstrW
, countW
, pgi
, flags
);
2893 HeapFree(GetProcessHeap(), 0, lpstrW
);
2898 /*************************************************************************
2899 * GetGlyphIndicesW [GDI32.@]
2901 DWORD WINAPI
GetGlyphIndicesW(HDC hdc
, LPCWSTR lpstr
, INT count
,
2902 LPWORD pgi
, DWORD flags
)
2904 DC
*dc
= DC_GetDCPtr(hdc
);
2905 DWORD ret
= GDI_ERROR
;
2907 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2908 hdc
, debugstr_wn(lpstr
, count
), count
, pgi
, flags
);
2910 if(!dc
) return GDI_ERROR
;
2913 ret
= WineEngGetGlyphIndices(dc
->gdiFont
, lpstr
, count
, pgi
, flags
);
2915 GDI_ReleaseObj(hdc
);
2919 /*************************************************************************
2920 * GetCharacterPlacementA [GDI32.@]
2922 * See GetCharacterPlacementW.
2925 * the web browser control of ie4 calls this with dwFlags=0
2928 GetCharacterPlacementA(HDC hdc
, LPCSTR lpString
, INT uCount
,
2929 INT nMaxExtent
, GCP_RESULTSA
*lpResults
,
2934 GCP_RESULTSW resultsW
;
2938 TRACE("%s, %d, %d, 0x%08x\n",
2939 debugstr_an(lpString
, uCount
), uCount
, nMaxExtent
, dwFlags
);
2941 /* both structs are equal in size */
2942 memcpy(&resultsW
, lpResults
, sizeof(resultsW
));
2944 lpStringW
= FONT_mbtowc(hdc
, lpString
, uCount
, &uCountW
, &font_cp
);
2945 if(lpResults
->lpOutString
)
2946 resultsW
.lpOutString
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*uCountW
);
2948 ret
= GetCharacterPlacementW(hdc
, lpStringW
, uCountW
, nMaxExtent
, &resultsW
, dwFlags
);
2950 lpResults
->nGlyphs
= resultsW
.nGlyphs
;
2951 lpResults
->nMaxFit
= resultsW
.nMaxFit
;
2953 if(lpResults
->lpOutString
) {
2954 WideCharToMultiByte(font_cp
, 0, resultsW
.lpOutString
, uCountW
,
2955 lpResults
->lpOutString
, uCount
, NULL
, NULL
);
2958 HeapFree(GetProcessHeap(), 0, lpStringW
);
2959 HeapFree(GetProcessHeap(), 0, resultsW
.lpOutString
);
2964 /*************************************************************************
2965 * GetCharacterPlacementW [GDI32.@]
2967 * Retrieve information about a string. This includes the width, reordering,
2968 * Glyphing and so on.
2972 * The width and height of the string if successful, 0 if failed.
2976 * All flags except GCP_REORDER are not yet implemented.
2977 * Reordering is not 100% complient to the Windows BiDi method.
2978 * Caret positioning is not yet implemented for BiDi.
2979 * Classes are not yet implemented.
2983 GetCharacterPlacementW(
2984 HDC hdc
, /* [in] Device context for which the rendering is to be done */
2985 LPCWSTR lpString
, /* [in] The string for which information is to be returned */
2986 INT uCount
, /* [in] Number of WORDS in string. */
2987 INT nMaxExtent
, /* [in] Maximum extent the string is to take (in HDC logical units) */
2988 GCP_RESULTSW
*lpResults
,/* [in/out] A pointer to a GCP_RESULTSW struct */
2989 DWORD dwFlags
/* [in] Flags specifying how to process the string */
2996 TRACE("%s, %d, %d, 0x%08x\n",
2997 debugstr_wn(lpString
, uCount
), uCount
, nMaxExtent
, dwFlags
);
2999 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
3000 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
3001 lpResults
->lStructSize
, lpResults
->lpOutString
, lpResults
->lpOrder
,
3002 lpResults
->lpDx
, lpResults
->lpCaretPos
, lpResults
->lpClass
,
3003 lpResults
->lpGlyphs
, lpResults
->nGlyphs
, lpResults
->nMaxFit
);
3005 if(dwFlags
&(~GCP_REORDER
)) FIXME("flags 0x%08x ignored\n", dwFlags
);
3006 if(lpResults
->lpClass
) FIXME("classes not implemented\n");
3007 if (lpResults
->lpCaretPos
&& (dwFlags
& GCP_REORDER
))
3008 FIXME("Caret positions for complex scripts not implemented\n");
3010 nSet
= (UINT
)uCount
;
3011 if(nSet
> lpResults
->nGlyphs
)
3012 nSet
= lpResults
->nGlyphs
;
3014 /* return number of initialized fields */
3015 lpResults
->nGlyphs
= nSet
;
3017 if((dwFlags
&GCP_REORDER
)==0 || !BidiAvail
)
3019 /* Treat the case where no special handling was requested in a fastpath way */
3020 /* copy will do if the GCP_REORDER flag is not set */
3021 if(lpResults
->lpOutString
)
3022 memcpy( lpResults
->lpOutString
, lpString
, nSet
* sizeof(WCHAR
));
3024 if(lpResults
->lpOrder
)
3026 for(i
= 0; i
< nSet
; i
++)
3027 lpResults
->lpOrder
[i
] = i
;
3031 BIDI_Reorder( lpString
, uCount
, dwFlags
, WINE_GCPW_FORCE_LTR
, lpResults
->lpOutString
,
3032 nSet
, lpResults
->lpOrder
);
3035 /* FIXME: Will use the placement chars */
3036 if (lpResults
->lpDx
)
3039 for (i
= 0; i
< nSet
; i
++)
3041 if (GetCharWidth32W(hdc
, lpString
[i
], lpString
[i
], &c
))
3042 lpResults
->lpDx
[i
]= c
;
3046 if (lpResults
->lpCaretPos
&& !(dwFlags
& GCP_REORDER
))
3050 lpResults
->lpCaretPos
[0] = 0;
3051 for (i
= 1; i
< nSet
; i
++)
3052 if (GetTextExtentPoint32W(hdc
, &(lpString
[i
- 1]), 1, &size
))
3053 lpResults
->lpCaretPos
[i
] = (pos
+= size
.cx
);
3056 if(lpResults
->lpGlyphs
)
3057 GetGlyphIndicesW(hdc
, lpString
, nSet
, lpResults
->lpGlyphs
, 0);
3059 if (GetTextExtentPoint32W(hdc
, lpString
, uCount
, &size
))
3060 ret
= MAKELONG(size
.cx
, size
.cy
);
3065 /*************************************************************************
3066 * GetCharABCWidthsFloatA [GDI32.@]
3068 * See GetCharABCWidthsFloatW.
3070 BOOL WINAPI
GetCharABCWidthsFloatA( HDC hdc
, UINT first
, UINT last
, LPABCFLOAT abcf
)
3072 INT i
, wlen
, count
= (INT
)(last
- first
+ 1);
3077 if (count
<= 0) return FALSE
;
3079 str
= HeapAlloc(GetProcessHeap(), 0, count
);
3081 for(i
= 0; i
< count
; i
++)
3082 str
[i
] = (BYTE
)(first
+ i
);
3084 wstr
= FONT_mbtowc( hdc
, str
, count
, &wlen
, NULL
);
3086 for (i
= 0; i
< wlen
; i
++)
3088 if (!GetCharABCWidthsFloatW( hdc
, wstr
[i
], wstr
[i
], abcf
))
3096 HeapFree( GetProcessHeap(), 0, str
);
3097 HeapFree( GetProcessHeap(), 0, wstr
);
3102 /*************************************************************************
3103 * GetCharABCWidthsFloatW [GDI32.@]
3105 * Retrieves widths of a range of characters.
3108 * hdc [I] Handle to device context.
3109 * first [I] First character in range to query.
3110 * last [I] Last character in range to query.
3111 * abcf [O] Array of LPABCFLOAT structures.
3118 * Only works with TrueType fonts. It also doesn't return real
3119 * floats but converted integers because it's implemented on
3120 * top of GetCharABCWidthsW.
3122 BOOL WINAPI
GetCharABCWidthsFloatW( HDC hdc
, UINT first
, UINT last
, LPABCFLOAT abcf
)
3125 unsigned int i
, size
= sizeof(ABC
) * (last
- first
+ 1);
3128 TRACE("%p, %d, %d, %p - partial stub\n", hdc
, first
, last
, abcf
);
3130 abc
= HeapAlloc( GetProcessHeap(), 0, size
);
3131 if (!abc
) return FALSE
;
3133 ret
= GetCharABCWidthsW( hdc
, first
, last
, abc
);
3136 for (i
= first
; i
<= last
; i
++, abc
++, abcf
++)
3138 abcf
->abcfA
= abc
->abcA
;
3139 abcf
->abcfB
= abc
->abcB
;
3140 abcf
->abcfC
= abc
->abcC
;
3143 HeapFree( GetProcessHeap(), 0, abc
);
3147 /*************************************************************************
3148 * GetCharWidthFloatA [GDI32.@]
3150 BOOL WINAPI
GetCharWidthFloatA(HDC hdc
, UINT iFirstChar
,
3151 UINT iLastChar
, PFLOAT pxBuffer
)
3153 FIXME("%p, %u, %u, %p: stub!\n", hdc
, iFirstChar
, iLastChar
, pxBuffer
);
3157 /*************************************************************************
3158 * GetCharWidthFloatW [GDI32.@]
3160 BOOL WINAPI
GetCharWidthFloatW(HDC hdc
, UINT iFirstChar
,
3161 UINT iLastChar
, PFLOAT pxBuffer
)
3163 FIXME("%p, %u, %u, %p: stub!\n", hdc
, iFirstChar
, iLastChar
, pxBuffer
);
3168 /***********************************************************************
3170 * Font Resource API *
3172 ***********************************************************************/
3174 /***********************************************************************
3175 * AddFontResourceA (GDI32.@)
3177 INT WINAPI
AddFontResourceA( LPCSTR str
)
3179 return AddFontResourceExA( str
, 0, NULL
);
3182 /***********************************************************************
3183 * AddFontResourceW (GDI32.@)
3185 INT WINAPI
AddFontResourceW( LPCWSTR str
)
3187 return AddFontResourceExW(str
, 0, NULL
);
3191 /***********************************************************************
3192 * AddFontResourceExA (GDI32.@)
3194 INT WINAPI
AddFontResourceExA( LPCSTR str
, DWORD fl
, PVOID pdv
)
3196 DWORD len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
3197 LPWSTR strW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3200 MultiByteToWideChar(CP_ACP
, 0, str
, -1, strW
, len
);
3201 ret
= AddFontResourceExW(strW
, fl
, pdv
);
3202 HeapFree(GetProcessHeap(), 0, strW
);
3206 /***********************************************************************
3207 * AddFontResourceExW (GDI32.@)
3209 INT WINAPI
AddFontResourceExW( LPCWSTR str
, DWORD fl
, PVOID pdv
)
3211 return WineEngAddFontResourceEx(str
, fl
, pdv
);
3214 /***********************************************************************
3215 * RemoveFontResourceA (GDI32.@)
3217 BOOL WINAPI
RemoveFontResourceA( LPCSTR str
)
3219 return RemoveFontResourceExA(str
, 0, 0);
3222 /***********************************************************************
3223 * RemoveFontResourceW (GDI32.@)
3225 BOOL WINAPI
RemoveFontResourceW( LPCWSTR str
)
3227 return RemoveFontResourceExW(str
, 0, 0);
3230 /***********************************************************************
3231 * AddFontMemResourceEx (GDI32.@)
3233 HANDLE WINAPI
AddFontMemResourceEx( PVOID pbFont
, DWORD cbFont
, PVOID pdv
, DWORD
*pcFonts
)
3235 FIXME("(%p,%08x,%p,%p): stub\n", pbFont
, cbFont
, pdv
, pcFonts
);
3239 /***********************************************************************
3240 * RemoveFontResourceExA (GDI32.@)
3242 BOOL WINAPI
RemoveFontResourceExA( LPCSTR str
, DWORD fl
, PVOID pdv
)
3244 DWORD len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
3245 LPWSTR strW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3248 MultiByteToWideChar(CP_ACP
, 0, str
, -1, strW
, len
);
3249 ret
= RemoveFontResourceExW(strW
, fl
, pdv
);
3250 HeapFree(GetProcessHeap(), 0, strW
);
3254 /***********************************************************************
3255 * RemoveFontResourceExW (GDI32.@)
3257 BOOL WINAPI
RemoveFontResourceExW( LPCWSTR str
, DWORD fl
, PVOID pdv
)
3259 return WineEngRemoveFontResourceEx(str
, fl
, pdv
);
3262 /***********************************************************************
3263 * GetTextCharset (GDI32.@)
3265 UINT WINAPI
GetTextCharset(HDC hdc
)
3267 /* MSDN docs say this is equivalent */
3268 return GetTextCharsetInfo(hdc
, NULL
, 0);
3271 /***********************************************************************
3272 * GetTextCharsetInfo (GDI32.@)
3274 UINT WINAPI
GetTextCharsetInfo(HDC hdc
, LPFONTSIGNATURE fs
, DWORD flags
)
3276 UINT ret
= DEFAULT_CHARSET
;
3277 DC
*dc
= DC_GetDCPtr(hdc
);
3282 ret
= WineEngGetTextCharsetInfo(dc
->gdiFont
, fs
, flags
);
3284 GDI_ReleaseObj(hdc
);
3287 if (ret
== DEFAULT_CHARSET
&& fs
)
3288 memset(fs
, 0, sizeof(FONTSIGNATURE
));
3292 /***********************************************************************
3293 * GdiGetCharDimensions (GDI32.@)
3295 * Gets the average width of the characters in the English alphabet.
3298 * hdc [I] Handle to the device context to measure on.
3299 * lptm [O] Pointer to memory to store the text metrics into.
3300 * height [O] On exit, the maximum height of characters in the English alphabet.
3303 * The average width of characters in the English alphabet.
3306 * This function is used by the dialog manager to get the size of a dialog
3307 * unit. It should also be used by other pieces of code that need to know
3308 * the size of a dialog unit in logical units without having access to the
3309 * window handle of the dialog.
3310 * Windows caches the font metrics from this function, but we don't and
3311 * there doesn't appear to be an immediate advantage to do so.
3314 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3316 LONG WINAPI
GdiGetCharDimensions(HDC hdc
, LPTEXTMETRICW lptm
, LONG
*height
)
3319 static const WCHAR alphabet
[] = {
3320 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3321 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3322 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3324 if(lptm
&& !GetTextMetricsW(hdc
, lptm
)) return 0;
3326 if(!GetTextExtentPointW(hdc
, alphabet
, 52, &sz
)) return 0;
3328 if (height
) *height
= sz
.cy
;
3329 return (sz
.cx
/ 26 + 1) / 2;
3332 BOOL WINAPI
EnableEUDC(BOOL fEnableEUDC
)
3334 FIXME("(%d): stub\n", fEnableEUDC
);
3338 /***********************************************************************
3339 * GetCharWidthI (GDI32.@)
3341 * Retrieve widths of characters.
3344 * hdc [I] Handle to a device context.
3345 * first [I] First glyph in range to query.
3346 * count [I] Number of glyph indices to query.
3347 * glyphs [I] Array of glyphs to query.
3348 * buffer [O] Buffer to receive character widths.
3351 * Only works with TrueType fonts.
3357 BOOL WINAPI
GetCharWidthI(HDC hdc
, UINT first
, UINT count
, LPWORD glyphs
, LPINT buffer
)
3362 TRACE("(%p, %d, %d, %p, %p)\n", hdc
, first
, count
, glyphs
, buffer
);
3364 if (!(abc
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(ABC
))))
3367 if (!GetCharABCWidthsI(hdc
, first
, count
, glyphs
, abc
))
3369 HeapFree(GetProcessHeap(), 0, abc
);
3373 for (i
= 0; i
< count
; i
++)
3374 buffer
[i
] = abc
->abcA
+ abc
->abcB
+ abc
->abcC
;
3376 HeapFree(GetProcessHeap(), 0, abc
);
3380 /***********************************************************************
3381 * GetFontUnicodeRanges (GDI32.@)
3383 * Retrieve a list of supported Unicode characters in a font.
3386 * hdc [I] Handle to a device context.
3387 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3390 * Success: Number of bytes written to the buffer pointed to by lpgs.
3394 DWORD WINAPI
GetFontUnicodeRanges(HDC hdc
, LPGLYPHSET lpgs
)
3396 return WineEngGetFontUnicodeRanges(hdc
, lpgs
);