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
, 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 MAXTCIINDEX 32
145 static const CHARSETINFO FONT_tci
[MAXTCIINDEX
] = {
147 { ANSI_CHARSET
, 1252, {{0,0,0,0},{FS_LATIN1
,0}} },
148 { EASTEUROPE_CHARSET
, 1250, {{0,0,0,0},{FS_LATIN2
,0}} },
149 { RUSSIAN_CHARSET
, 1251, {{0,0,0,0},{FS_CYRILLIC
,0}} },
150 { GREEK_CHARSET
, 1253, {{0,0,0,0},{FS_GREEK
,0}} },
151 { TURKISH_CHARSET
, 1254, {{0,0,0,0},{FS_TURKISH
,0}} },
152 { HEBREW_CHARSET
, 1255, {{0,0,0,0},{FS_HEBREW
,0}} },
153 { ARABIC_CHARSET
, 1256, {{0,0,0,0},{FS_ARABIC
,0}} },
154 { BALTIC_CHARSET
, 1257, {{0,0,0,0},{FS_BALTIC
,0}} },
155 { VIETNAMESE_CHARSET
, 1258, {{0,0,0,0},{FS_VIETNAMESE
,0}} },
156 /* reserved by ANSI */
157 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
158 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
159 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
160 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
161 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
162 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
163 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
165 { THAI_CHARSET
, 874, {{0,0,0,0},{FS_THAI
,0}} },
166 { SHIFTJIS_CHARSET
, 932, {{0,0,0,0},{FS_JISJAPAN
,0}} },
167 { GB2312_CHARSET
, 936, {{0,0,0,0},{FS_CHINESESIMP
,0}} },
168 { HANGEUL_CHARSET
, 949, {{0,0,0,0},{FS_WANSUNG
,0}} },
169 { CHINESEBIG5_CHARSET
, 950, {{0,0,0,0},{FS_CHINESETRAD
,0}} },
170 { JOHAB_CHARSET
, 1361, {{0,0,0,0},{FS_JOHAB
,0}} },
171 /* reserved for alternate ANSI and OEM */
172 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
173 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
174 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
175 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
176 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
177 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
178 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
179 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
180 /* reserved for system */
181 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
182 { SYMBOL_CHARSET
, CP_SYMBOL
, {{0,0,0,0},{FS_SYMBOL
,0}} }
185 /***********************************************************************
186 * LOGFONT conversion functions.
188 static void FONT_LogFontWTo16( const LOGFONTW
* font32
, LPLOGFONT16 font16
)
190 font16
->lfHeight
= font32
->lfHeight
;
191 font16
->lfWidth
= font32
->lfWidth
;
192 font16
->lfEscapement
= font32
->lfEscapement
;
193 font16
->lfOrientation
= font32
->lfOrientation
;
194 font16
->lfWeight
= font32
->lfWeight
;
195 font16
->lfItalic
= font32
->lfItalic
;
196 font16
->lfUnderline
= font32
->lfUnderline
;
197 font16
->lfStrikeOut
= font32
->lfStrikeOut
;
198 font16
->lfCharSet
= font32
->lfCharSet
;
199 font16
->lfOutPrecision
= font32
->lfOutPrecision
;
200 font16
->lfClipPrecision
= font32
->lfClipPrecision
;
201 font16
->lfQuality
= font32
->lfQuality
;
202 font16
->lfPitchAndFamily
= font32
->lfPitchAndFamily
;
203 WideCharToMultiByte( CP_ACP
, 0, font32
->lfFaceName
, -1,
204 font16
->lfFaceName
, LF_FACESIZE
, NULL
, NULL
);
205 font16
->lfFaceName
[LF_FACESIZE
-1] = 0;
208 static void FONT_LogFont16ToW( const LOGFONT16
*font16
, LPLOGFONTW font32
)
210 font32
->lfHeight
= font16
->lfHeight
;
211 font32
->lfWidth
= font16
->lfWidth
;
212 font32
->lfEscapement
= font16
->lfEscapement
;
213 font32
->lfOrientation
= font16
->lfOrientation
;
214 font32
->lfWeight
= font16
->lfWeight
;
215 font32
->lfItalic
= font16
->lfItalic
;
216 font32
->lfUnderline
= font16
->lfUnderline
;
217 font32
->lfStrikeOut
= font16
->lfStrikeOut
;
218 font32
->lfCharSet
= font16
->lfCharSet
;
219 font32
->lfOutPrecision
= font16
->lfOutPrecision
;
220 font32
->lfClipPrecision
= font16
->lfClipPrecision
;
221 font32
->lfQuality
= font16
->lfQuality
;
222 font32
->lfPitchAndFamily
= font16
->lfPitchAndFamily
;
223 MultiByteToWideChar( CP_ACP
, 0, font16
->lfFaceName
, -1, font32
->lfFaceName
, LF_FACESIZE
);
224 font32
->lfFaceName
[LF_FACESIZE
-1] = 0;
227 static void FONT_LogFontAToW( const LOGFONTA
*fontA
, LPLOGFONTW fontW
)
229 memcpy(fontW
, fontA
, sizeof(LOGFONTA
) - LF_FACESIZE
);
230 MultiByteToWideChar(CP_ACP
, 0, fontA
->lfFaceName
, -1, fontW
->lfFaceName
,
232 fontW
->lfFaceName
[LF_FACESIZE
-1] = 0;
235 static void FONT_LogFontWToA( const LOGFONTW
*fontW
, LPLOGFONTA fontA
)
237 memcpy(fontA
, fontW
, sizeof(LOGFONTA
) - LF_FACESIZE
);
238 WideCharToMultiByte(CP_ACP
, 0, fontW
->lfFaceName
, -1, fontA
->lfFaceName
,
239 LF_FACESIZE
, NULL
, NULL
);
240 fontA
->lfFaceName
[LF_FACESIZE
-1] = 0;
243 static void FONT_EnumLogFontExWTo16( const ENUMLOGFONTEXW
*fontW
, LPENUMLOGFONTEX16 font16
)
245 FONT_LogFontWTo16( (const LOGFONTW
*)fontW
, (LPLOGFONT16
)font16
);
247 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfFullName
, -1,
248 (LPSTR
) font16
->elfFullName
, LF_FULLFACESIZE
, NULL
, NULL
);
249 font16
->elfFullName
[LF_FULLFACESIZE
-1] = '\0';
250 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfStyle
, -1,
251 (LPSTR
) font16
->elfStyle
, LF_FACESIZE
, NULL
, NULL
);
252 font16
->elfStyle
[LF_FACESIZE
-1] = '\0';
253 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfScript
, -1,
254 (LPSTR
) font16
->elfScript
, LF_FACESIZE
, NULL
, NULL
);
255 font16
->elfScript
[LF_FACESIZE
-1] = '\0';
258 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW
*fontW
, LPENUMLOGFONTEXA fontA
)
260 FONT_LogFontWToA( (const LOGFONTW
*)fontW
, (LPLOGFONTA
)fontA
);
262 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfFullName
, -1,
263 (LPSTR
) fontA
->elfFullName
, LF_FULLFACESIZE
, NULL
, NULL
);
264 fontA
->elfFullName
[LF_FULLFACESIZE
-1] = '\0';
265 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfStyle
, -1,
266 (LPSTR
) fontA
->elfStyle
, LF_FACESIZE
, NULL
, NULL
);
267 fontA
->elfStyle
[LF_FACESIZE
-1] = '\0';
268 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfScript
, -1,
269 (LPSTR
) fontA
->elfScript
, LF_FACESIZE
, NULL
, NULL
);
270 fontA
->elfScript
[LF_FACESIZE
-1] = '\0';
273 /***********************************************************************
274 * TEXTMETRIC conversion functions.
276 static void FONT_TextMetricWToA(const TEXTMETRICW
*ptmW
, LPTEXTMETRICA ptmA
)
278 ptmA
->tmHeight
= ptmW
->tmHeight
;
279 ptmA
->tmAscent
= ptmW
->tmAscent
;
280 ptmA
->tmDescent
= ptmW
->tmDescent
;
281 ptmA
->tmInternalLeading
= ptmW
->tmInternalLeading
;
282 ptmA
->tmExternalLeading
= ptmW
->tmExternalLeading
;
283 ptmA
->tmAveCharWidth
= ptmW
->tmAveCharWidth
;
284 ptmA
->tmMaxCharWidth
= ptmW
->tmMaxCharWidth
;
285 ptmA
->tmWeight
= ptmW
->tmWeight
;
286 ptmA
->tmOverhang
= ptmW
->tmOverhang
;
287 ptmA
->tmDigitizedAspectX
= ptmW
->tmDigitizedAspectX
;
288 ptmA
->tmDigitizedAspectY
= ptmW
->tmDigitizedAspectY
;
289 ptmA
->tmFirstChar
= min(ptmW
->tmFirstChar
, 255);
290 if (ptmW
->tmCharSet
== SYMBOL_CHARSET
)
292 UINT last_char
= ptmW
->tmLastChar
;
293 if (last_char
> 0xf000) last_char
-= 0xf000;
294 ptmA
->tmLastChar
= min(last_char
, 255);
297 ptmA
->tmLastChar
= min(ptmW
->tmLastChar
, 255);
298 ptmA
->tmDefaultChar
= min(ptmW
->tmDefaultChar
, 255);
299 ptmA
->tmBreakChar
= min(ptmW
->tmBreakChar
, 255);
300 ptmA
->tmItalic
= ptmW
->tmItalic
;
301 ptmA
->tmUnderlined
= ptmW
->tmUnderlined
;
302 ptmA
->tmStruckOut
= ptmW
->tmStruckOut
;
303 ptmA
->tmPitchAndFamily
= ptmW
->tmPitchAndFamily
;
304 ptmA
->tmCharSet
= ptmW
->tmCharSet
;
308 static void FONT_NewTextMetricExWTo16(const NEWTEXTMETRICEXW
*ptmW
, LPNEWTEXTMETRICEX16 ptm16
)
310 ptm16
->ntmTm
.tmHeight
= ptmW
->ntmTm
.tmHeight
;
311 ptm16
->ntmTm
.tmAscent
= ptmW
->ntmTm
.tmAscent
;
312 ptm16
->ntmTm
.tmDescent
= ptmW
->ntmTm
.tmDescent
;
313 ptm16
->ntmTm
.tmInternalLeading
= ptmW
->ntmTm
.tmInternalLeading
;
314 ptm16
->ntmTm
.tmExternalLeading
= ptmW
->ntmTm
.tmExternalLeading
;
315 ptm16
->ntmTm
.tmAveCharWidth
= ptmW
->ntmTm
.tmAveCharWidth
;
316 ptm16
->ntmTm
.tmMaxCharWidth
= ptmW
->ntmTm
.tmMaxCharWidth
;
317 ptm16
->ntmTm
.tmWeight
= ptmW
->ntmTm
.tmWeight
;
318 ptm16
->ntmTm
.tmOverhang
= ptmW
->ntmTm
.tmOverhang
;
319 ptm16
->ntmTm
.tmDigitizedAspectX
= ptmW
->ntmTm
.tmDigitizedAspectX
;
320 ptm16
->ntmTm
.tmDigitizedAspectY
= ptmW
->ntmTm
.tmDigitizedAspectY
;
321 ptm16
->ntmTm
.tmFirstChar
= ptmW
->ntmTm
.tmFirstChar
> 255 ? 255 : ptmW
->ntmTm
.tmFirstChar
;
322 ptm16
->ntmTm
.tmLastChar
= ptmW
->ntmTm
.tmLastChar
> 255 ? 255 : ptmW
->ntmTm
.tmLastChar
;
323 ptm16
->ntmTm
.tmDefaultChar
= ptmW
->ntmTm
.tmDefaultChar
> 255 ? 255 : ptmW
->ntmTm
.tmDefaultChar
;
324 ptm16
->ntmTm
.tmBreakChar
= ptmW
->ntmTm
.tmBreakChar
> 255 ? 255 : ptmW
->ntmTm
.tmBreakChar
;
325 ptm16
->ntmTm
.tmItalic
= ptmW
->ntmTm
.tmItalic
;
326 ptm16
->ntmTm
.tmUnderlined
= ptmW
->ntmTm
.tmUnderlined
;
327 ptm16
->ntmTm
.tmStruckOut
= ptmW
->ntmTm
.tmStruckOut
;
328 ptm16
->ntmTm
.tmPitchAndFamily
= ptmW
->ntmTm
.tmPitchAndFamily
;
329 ptm16
->ntmTm
.tmCharSet
= ptmW
->ntmTm
.tmCharSet
;
330 ptm16
->ntmTm
.ntmFlags
= ptmW
->ntmTm
.ntmFlags
;
331 ptm16
->ntmTm
.ntmSizeEM
= ptmW
->ntmTm
.ntmSizeEM
;
332 ptm16
->ntmTm
.ntmCellHeight
= ptmW
->ntmTm
.ntmCellHeight
;
333 ptm16
->ntmTm
.ntmAvgWidth
= ptmW
->ntmTm
.ntmAvgWidth
;
334 memcpy(&ptm16
->ntmFontSig
, &ptmW
->ntmFontSig
, sizeof(FONTSIGNATURE
));
337 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW
*ptmW
, NEWTEXTMETRICEXA
*ptmA
)
339 FONT_TextMetricWToA((const TEXTMETRICW
*)ptmW
, (LPTEXTMETRICA
)ptmA
);
340 ptmA
->ntmTm
.ntmFlags
= ptmW
->ntmTm
.ntmFlags
;
341 ptmA
->ntmTm
.ntmSizeEM
= ptmW
->ntmTm
.ntmSizeEM
;
342 ptmA
->ntmTm
.ntmCellHeight
= ptmW
->ntmTm
.ntmCellHeight
;
343 ptmA
->ntmTm
.ntmAvgWidth
= ptmW
->ntmTm
.ntmAvgWidth
;
344 memcpy(&ptmA
->ntmFontSig
, &ptmW
->ntmFontSig
, sizeof(FONTSIGNATURE
));
348 /***********************************************************************
349 * GdiGetCodePage (GDI32.@)
351 DWORD WINAPI
GdiGetCodePage( HDC hdc
)
355 int charset
= GetTextCharset(hdc
);
357 /* Hmm, nicely designed api this one! */
358 if(TranslateCharsetInfo(ULongToPtr(charset
), &csi
, TCI_SRCCHARSET
))
365 case DEFAULT_CHARSET
:
376 /* FIXME: These have no place here, but because x11drv
377 enumerates fonts with these (made up) charsets some apps
378 might use them and then the FIXME below would become
379 annoying. Now we could pick the intended codepage for
380 each of these, but since it's broken anyway we'll just
381 use CP_ACP and hope it'll go away...
387 FIXME("Can't find codepage for charset %d\n", charset
);
392 TRACE("charset %d => cp %d\n", charset
, cp
);
396 /***********************************************************************
399 * Returns a Unicode translation of str using the charset of the
400 * currently selected font in hdc. If count is -1 then str is assumed
401 * to be '\0' terminated, otherwise it contains the number of bytes to
402 * convert. If plenW is non-NULL, on return it will point to the
403 * number of WCHARs that have been written. If pCP is non-NULL, on
404 * return it will point to the codepage used in the conversion. The
405 * caller should free the returned LPWSTR from the process heap
408 static LPWSTR
FONT_mbtowc(HDC hdc
, LPCSTR str
, INT count
, INT
*plenW
, UINT
*pCP
)
414 cp
= GdiGetCodePage( hdc
);
416 if(count
== -1) count
= strlen(str
);
417 lenW
= MultiByteToWideChar(cp
, 0, str
, count
, NULL
, 0);
418 strW
= HeapAlloc(GetProcessHeap(), 0, lenW
*sizeof(WCHAR
));
419 MultiByteToWideChar(cp
, 0, str
, count
, strW
, lenW
);
420 TRACE("mapped %s -> %s\n", debugstr_an(str
, count
), debugstr_wn(strW
, lenW
));
421 if(plenW
) *plenW
= lenW
;
427 /***********************************************************************
428 * CreateFontIndirectA (GDI32.@)
430 HFONT WINAPI
CreateFontIndirectA( const LOGFONTA
*plfA
)
436 FONT_LogFontAToW( plfA
, &lfW
);
437 return CreateFontIndirectW( &lfW
);
440 /***********************************************************************
441 * CreateFontIndirectW (GDI32.@)
443 HFONT WINAPI
CreateFontIndirectW( const LOGFONTW
*plf
)
445 static const WCHAR ItalicW
[] = {' ','I','t','a','l','i','c','\0'};
446 static const WCHAR BoldW
[] = {' ','B','o','l','d','\0'};
447 WCHAR
*pFaceNameItalicSuffix
, *pFaceNameBoldSuffix
;
448 WCHAR
*pFaceNameSuffix
= NULL
;
454 if (!(fontPtr
= GDI_AllocObject( sizeof(FONTOBJ
), FONT_MAGIC
, (HGDIOBJ
*)&hFont
,
455 &font_funcs
))) return 0;
457 memcpy( &fontPtr
->logfont
, plf
, sizeof(LOGFONTW
) );
459 TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
460 plf
->lfHeight
, plf
->lfWidth
,
461 plf
->lfEscapement
, plf
->lfOrientation
,
462 plf
->lfPitchAndFamily
,
463 plf
->lfOutPrecision
, plf
->lfClipPrecision
,
464 plf
->lfQuality
, plf
->lfCharSet
,
465 debugstr_w(plf
->lfFaceName
),
466 plf
->lfWeight
> 400 ? "Bold" : "",
467 plf
->lfItalic
? "Italic" : "",
468 plf
->lfUnderline
? "Underline" : "", hFont
);
470 if (plf
->lfEscapement
!= plf
->lfOrientation
)
472 /* this should really depend on whether GM_ADVANCED is set */
473 fontPtr
->logfont
.lfOrientation
= fontPtr
->logfont
.lfEscapement
;
474 WARN("orientation angle %f set to "
475 "escapement angle %f for new font %p\n",
476 plf
->lfOrientation
/10., plf
->lfEscapement
/10., hFont
);
479 pFaceNameItalicSuffix
= strstrW(fontPtr
->logfont
.lfFaceName
, ItalicW
);
480 if (pFaceNameItalicSuffix
)
482 fontPtr
->logfont
.lfItalic
= TRUE
;
483 pFaceNameSuffix
= pFaceNameItalicSuffix
;
486 pFaceNameBoldSuffix
= strstrW(fontPtr
->logfont
.lfFaceName
, BoldW
);
487 if (pFaceNameBoldSuffix
)
489 if (fontPtr
->logfont
.lfWeight
< FW_BOLD
)
490 fontPtr
->logfont
.lfWeight
= FW_BOLD
;
491 if (!pFaceNameSuffix
|| (pFaceNameBoldSuffix
< pFaceNameSuffix
))
492 pFaceNameSuffix
= pFaceNameBoldSuffix
;
495 if (pFaceNameSuffix
) *pFaceNameSuffix
= 0;
497 GDI_ReleaseObj( hFont
);
501 /*************************************************************************
502 * CreateFontA (GDI32.@)
504 HFONT WINAPI
CreateFontA( INT height
, INT width
, INT esc
,
505 INT orient
, INT weight
, DWORD italic
,
506 DWORD underline
, DWORD strikeout
, DWORD charset
,
507 DWORD outpres
, DWORD clippres
, DWORD quality
,
508 DWORD pitch
, LPCSTR name
)
512 logfont
.lfHeight
= height
;
513 logfont
.lfWidth
= width
;
514 logfont
.lfEscapement
= esc
;
515 logfont
.lfOrientation
= orient
;
516 logfont
.lfWeight
= weight
;
517 logfont
.lfItalic
= italic
;
518 logfont
.lfUnderline
= underline
;
519 logfont
.lfStrikeOut
= strikeout
;
520 logfont
.lfCharSet
= charset
;
521 logfont
.lfOutPrecision
= outpres
;
522 logfont
.lfClipPrecision
= clippres
;
523 logfont
.lfQuality
= quality
;
524 logfont
.lfPitchAndFamily
= pitch
;
527 lstrcpynA(logfont
.lfFaceName
,name
,sizeof(logfont
.lfFaceName
));
529 logfont
.lfFaceName
[0] = '\0';
531 return CreateFontIndirectA( &logfont
);
534 /*************************************************************************
535 * CreateFontW (GDI32.@)
537 HFONT WINAPI
CreateFontW( INT height
, INT width
, INT esc
,
538 INT orient
, INT weight
, DWORD italic
,
539 DWORD underline
, DWORD strikeout
, DWORD charset
,
540 DWORD outpres
, DWORD clippres
, DWORD quality
,
541 DWORD pitch
, LPCWSTR name
)
545 logfont
.lfHeight
= height
;
546 logfont
.lfWidth
= width
;
547 logfont
.lfEscapement
= esc
;
548 logfont
.lfOrientation
= orient
;
549 logfont
.lfWeight
= weight
;
550 logfont
.lfItalic
= italic
;
551 logfont
.lfUnderline
= underline
;
552 logfont
.lfStrikeOut
= strikeout
;
553 logfont
.lfCharSet
= charset
;
554 logfont
.lfOutPrecision
= outpres
;
555 logfont
.lfClipPrecision
= clippres
;
556 logfont
.lfQuality
= quality
;
557 logfont
.lfPitchAndFamily
= pitch
;
560 lstrcpynW(logfont
.lfFaceName
, name
,
561 sizeof(logfont
.lfFaceName
) / sizeof(WCHAR
));
563 logfont
.lfFaceName
[0] = '\0';
565 return CreateFontIndirectW( &logfont
);
569 /***********************************************************************
572 * If the driver supports vector fonts we create a gdi font first and
573 * then call the driver to give it a chance to supply its own device
574 * font. If the driver wants to do this it returns TRUE and we can
575 * delete the gdi font, if the driver wants to use the gdi font it
576 * should return FALSE, to signal an error return GDI_ERROR. For
577 * drivers that don't support vector fonts they must supply their own
580 static HGDIOBJ
FONT_SelectObject( HGDIOBJ handle
, HDC hdc
)
583 DC
*dc
= get_dc_ptr( hdc
);
587 if (!GDI_inc_ref_count( handle
))
589 release_dc_ptr( dc
);
593 if (dc
->hFont
!= handle
|| dc
->gdiFont
== NULL
)
595 if(GetDeviceCaps(dc
->hSelf
, TEXTCAPS
) & TC_VA_ABLE
)
597 FONTOBJ
*font
= GDI_GetObjPtr( handle
, FONT_MAGIC
); /* to grab the GDI lock (FIXME) */
598 dc
->gdiFont
= WineEngCreateFontInstance(dc
, handle
);
599 if (font
) GDI_ReleaseObj( handle
);
603 if (dc
->funcs
->pSelectFont
) ret
= dc
->funcs
->pSelectFont( dc
->physDev
, handle
, dc
->gdiFont
);
605 if (ret
&& dc
->gdiFont
) dc
->gdiFont
= 0;
607 if (ret
== HGDI_ERROR
)
609 GDI_dec_ref_count( handle
);
610 ret
= 0; /* SelectObject returns 0 on error */
616 GDI_dec_ref_count( ret
);
618 release_dc_ptr( dc
);
623 /***********************************************************************
626 static INT
FONT_GetObject16( HGDIOBJ handle
, void *obj
, INT count
, LPVOID buffer
)
631 FONT_LogFontWTo16( &font
->logfont
, &lf16
);
633 if (count
> sizeof(LOGFONT16
)) count
= sizeof(LOGFONT16
);
634 memcpy( buffer
, &lf16
, count
);
638 /***********************************************************************
641 static INT
FONT_GetObjectA( HGDIOBJ handle
, void *obj
, INT count
, LPVOID buffer
)
648 FONT_LogFontWToA( &font
->logfont
, &lfA
);
650 if (count
> sizeof(lfA
)) count
= sizeof(lfA
);
651 memcpy( buffer
, &lfA
, count
);
655 /***********************************************************************
658 static INT
FONT_GetObjectW( HGDIOBJ handle
, void *obj
, INT count
, LPVOID buffer
)
662 return sizeof(LOGFONTW
);
663 if (count
> sizeof(LOGFONTW
)) count
= sizeof(LOGFONTW
);
664 memcpy( buffer
, &font
->logfont
, count
);
669 /***********************************************************************
672 static BOOL
FONT_DeleteObject( HGDIOBJ handle
, void *obj
)
674 WineEngDestroyFontInstance( handle
);
675 return GDI_FreeObject( handle
, obj
);
679 /***********************************************************************
680 * FONT_EnumInstance16
682 * Called by the device driver layer to pass font info
683 * down to the application.
685 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
686 * We have to use other types because of the FONTENUMPROCW definition.
688 static INT CALLBACK
FONT_EnumInstance16( const LOGFONTW
*plf
, const TEXTMETRICW
*ptm
,
689 DWORD fType
, LPARAM lp
)
691 fontEnum16
*pfe
= (fontEnum16
*)lp
;
695 if (!pfe
->lpLogFontParam
||
696 pfe
->lpLogFontParam
->lfCharSet
== DEFAULT_CHARSET
||
697 pfe
->lpLogFontParam
->lfCharSet
== plf
->lfCharSet
)
702 FONT_EnumLogFontExWTo16((const ENUMLOGFONTEXW
*)plf
, pfe
->lpLogFont
);
703 FONT_NewTextMetricExWTo16((const NEWTEXTMETRICEXW
*)ptm
, pfe
->lpTextMetric
);
704 pfe
->dwFlags
|= ENUM_CALLED
;
705 DC_ReleaseDCPtr( pfe
->dc
); /* release the GDI lock */
707 args
[6] = SELECTOROF(pfe
->segLogFont
);
708 args
[5] = OFFSETOF(pfe
->segLogFont
);
709 args
[4] = SELECTOROF(pfe
->segTextMetric
);
710 args
[3] = OFFSETOF(pfe
->segTextMetric
);
712 args
[1] = HIWORD(pfe
->lpData
);
713 args
[0] = LOWORD(pfe
->lpData
);
714 WOWCallback16Ex( (DWORD
)pfe
->lpEnumFunc
, WCB16_PASCAL
, sizeof(args
), args
, &result
);
715 ret
= LOWORD(result
);
717 /* get the lock again and make sure the DC is still valid */
718 dc
= DC_GetDCPtr( pfe
->hdc
);
719 if (!dc
|| dc
!= pfe
->dc
|| dc
->physDev
!= pfe
->physDev
)
721 if (dc
) DC_ReleaseDCPtr( dc
);
722 pfe
->hdc
= 0; /* make sure we don't try to release it later on */
730 /***********************************************************************
733 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
734 * We have to use other types because of the FONTENUMPROCW definition.
736 static INT CALLBACK
FONT_EnumInstance( const LOGFONTW
*plf
, const TEXTMETRICW
*ptm
,
737 DWORD fType
, LPARAM lp
)
739 fontEnum32
*pfe
= (fontEnum32
*)lp
;
743 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
744 if ((!pfe
->lpLogFontParam
||
745 pfe
->lpLogFontParam
->lfCharSet
== DEFAULT_CHARSET
||
746 pfe
->lpLogFontParam
->lfCharSet
== plf
->lfCharSet
) &&
747 (!(fType
& RASTER_FONTTYPE
) || GetDeviceCaps(pfe
->hdc
, TEXTCAPS
) & TC_RA_ABLE
) )
749 /* convert font metrics */
750 ENUMLOGFONTEXA logfont
;
751 NEWTEXTMETRICEXA tmA
;
753 pfe
->dwFlags
|= ENUM_CALLED
;
754 if (!(pfe
->dwFlags
& ENUM_UNICODE
))
756 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW
*)plf
, &logfont
);
757 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW
*)ptm
, &tmA
);
758 plf
= (LOGFONTW
*)&logfont
.elfLogFont
;
759 ptm
= (TEXTMETRICW
*)&tmA
;
761 DC_ReleaseDCPtr( pfe
->dc
); /* release the GDI lock */
763 ret
= pfe
->lpEnumFunc( plf
, ptm
, fType
, pfe
->lpData
);
765 /* get the lock again and make sure the DC is still valid */
766 dc
= DC_GetDCPtr( pfe
->hdc
);
767 if (!dc
|| dc
!= pfe
->dc
|| dc
->physDev
!= pfe
->physDev
)
769 if (dc
) DC_ReleaseDCPtr( dc
);
770 pfe
->hdc
= 0; /* make sure we don't try to release it later on */
778 /***********************************************************************
779 * EnumFontFamiliesEx (GDI.613)
781 INT16 WINAPI
EnumFontFamiliesEx16( HDC16 hDC
, LPLOGFONT16 plf
,
782 FONTENUMPROC16 efproc
, LPARAM lParam
,
787 DC
* dc
= DC_GetDCPtr( HDC_32(hDC
) );
788 NEWTEXTMETRICEX16 tm16
;
789 ENUMLOGFONTEX16 lf16
;
797 FONT_LogFont16ToW(plf
, &lfW
);
802 fe16
.hdc
= HDC_32(hDC
);
804 fe16
.physDev
= dc
->physDev
;
805 fe16
.lpLogFontParam
= plf
;
806 fe16
.lpEnumFunc
= efproc
;
807 fe16
.lpData
= lParam
;
808 fe16
.lpTextMetric
= &tm16
;
809 fe16
.lpLogFont
= &lf16
;
810 fe16
.segTextMetric
= MapLS( &tm16
);
811 fe16
.segLogFont
= MapLS( &lf16
);
814 enum_gdi_fonts
= GetDeviceCaps(fe16
.hdc
, TEXTCAPS
) & TC_VA_ABLE
;
816 if (!dc
->funcs
->pEnumDeviceFonts
&& !enum_gdi_fonts
)
823 ret
= WineEngEnumFonts( plfW
, FONT_EnumInstance16
, (LPARAM
)&fe16
);
824 fe16
.dwFlags
&= ~ENUM_CALLED
;
825 if (ret
&& dc
->funcs
->pEnumDeviceFonts
) {
826 ret2
= dc
->funcs
->pEnumDeviceFonts( dc
->physDev
, plfW
, FONT_EnumInstance16
, (LPARAM
)&fe16
);
827 if(fe16
.dwFlags
& ENUM_CALLED
) /* update ret iff a font gets enumed */
831 UnMapLS( fe16
.segTextMetric
);
832 UnMapLS( fe16
.segLogFont
);
833 if (fe16
.dc
) DC_ReleaseDCPtr( fe16
.dc
);
837 /***********************************************************************
838 * FONT_EnumFontFamiliesEx
840 static INT
FONT_EnumFontFamiliesEx( HDC hDC
, LPLOGFONTW plf
,
841 FONTENUMPROCW efproc
,
842 LPARAM lParam
, DWORD dwUnicode
)
845 DC
*dc
= DC_GetDCPtr( hDC
);
852 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf
->lfFaceName
),
854 fe32
.lpLogFontParam
= plf
;
855 fe32
.lpEnumFunc
= efproc
;
856 fe32
.lpData
= lParam
;
857 fe32
.dwFlags
= dwUnicode
;
860 fe32
.physDev
= dc
->physDev
;
862 enum_gdi_fonts
= GetDeviceCaps(hDC
, TEXTCAPS
) & TC_VA_ABLE
;
864 if (!dc
->funcs
->pEnumDeviceFonts
&& !enum_gdi_fonts
)
871 ret
= WineEngEnumFonts( plf
, FONT_EnumInstance
, (LPARAM
)&fe32
);
872 fe32
.dwFlags
&= ~ENUM_CALLED
;
873 if (ret
&& dc
->funcs
->pEnumDeviceFonts
) {
874 ret2
= dc
->funcs
->pEnumDeviceFonts( dc
->physDev
, plf
, FONT_EnumInstance
, (LPARAM
)&fe32
);
875 if(fe32
.dwFlags
& ENUM_CALLED
) /* update ret iff a font gets enumed */
879 if (fe32
.dc
) DC_ReleaseDCPtr( fe32
.dc
);
883 /***********************************************************************
884 * EnumFontFamiliesExW (GDI32.@)
886 INT WINAPI
EnumFontFamiliesExW( HDC hDC
, LPLOGFONTW plf
,
887 FONTENUMPROCW efproc
,
888 LPARAM lParam
, DWORD dwFlags
)
890 return FONT_EnumFontFamiliesEx( hDC
, plf
, efproc
, lParam
, ENUM_UNICODE
);
893 /***********************************************************************
894 * EnumFontFamiliesExA (GDI32.@)
896 INT WINAPI
EnumFontFamiliesExA( HDC hDC
, LPLOGFONTA plf
,
897 FONTENUMPROCA efproc
,
898 LPARAM lParam
, DWORD dwFlags
)
904 FONT_LogFontAToW( plf
, &lfW
);
909 return FONT_EnumFontFamiliesEx( hDC
, plfW
, (FONTENUMPROCW
)efproc
, lParam
, 0);
912 /***********************************************************************
913 * EnumFontFamilies (GDI.330)
915 INT16 WINAPI
EnumFontFamilies16( HDC16 hDC
, LPCSTR lpFamily
,
916 FONTENUMPROC16 efproc
, LPARAM lpData
)
922 if (!*lpFamily
) return 1;
923 lstrcpynA( lf
.lfFaceName
, lpFamily
, LF_FACESIZE
);
924 lf
.lfCharSet
= DEFAULT_CHARSET
;
925 lf
.lfPitchAndFamily
= 0;
930 return EnumFontFamiliesEx16( hDC
, plf
, efproc
, lpData
, 0 );
933 /***********************************************************************
934 * EnumFontFamiliesA (GDI32.@)
936 INT WINAPI
EnumFontFamiliesA( HDC hDC
, LPCSTR lpFamily
,
937 FONTENUMPROCA efproc
, LPARAM lpData
)
943 if (!*lpFamily
) return 1;
944 lstrcpynA( lf
.lfFaceName
, lpFamily
, LF_FACESIZE
);
945 lf
.lfCharSet
= DEFAULT_CHARSET
;
946 lf
.lfPitchAndFamily
= 0;
951 return EnumFontFamiliesExA( hDC
, plf
, efproc
, lpData
, 0 );
954 /***********************************************************************
955 * EnumFontFamiliesW (GDI32.@)
957 INT WINAPI
EnumFontFamiliesW( HDC hDC
, LPCWSTR lpFamily
,
958 FONTENUMPROCW efproc
, LPARAM lpData
)
964 if (!*lpFamily
) return 1;
965 lstrcpynW( lf
.lfFaceName
, lpFamily
, LF_FACESIZE
);
966 lf
.lfCharSet
= DEFAULT_CHARSET
;
967 lf
.lfPitchAndFamily
= 0;
972 return EnumFontFamiliesExW( hDC
, plf
, efproc
, lpData
, 0 );
975 /***********************************************************************
978 INT16 WINAPI
EnumFonts16( HDC16 hDC
, LPCSTR lpName
, FONTENUMPROC16 efproc
,
981 return EnumFontFamilies16( hDC
, lpName
, efproc
, lpData
);
984 /***********************************************************************
985 * EnumFontsA (GDI32.@)
987 INT WINAPI
EnumFontsA( HDC hDC
, LPCSTR lpName
, FONTENUMPROCA efproc
,
990 return EnumFontFamiliesA( hDC
, lpName
, efproc
, lpData
);
993 /***********************************************************************
994 * EnumFontsW (GDI32.@)
996 INT WINAPI
EnumFontsW( HDC hDC
, LPCWSTR lpName
, FONTENUMPROCW efproc
,
999 return EnumFontFamiliesW( hDC
, lpName
, efproc
, lpData
);
1003 /***********************************************************************
1004 * GetTextCharacterExtra (GDI32.@)
1006 INT WINAPI
GetTextCharacterExtra( HDC hdc
)
1009 DC
*dc
= DC_GetDCPtr( hdc
);
1010 if (!dc
) return 0x80000000;
1011 ret
= dc
->charExtra
;
1012 DC_ReleaseDCPtr( dc
);
1017 /***********************************************************************
1018 * SetTextCharacterExtra (GDI32.@)
1020 INT WINAPI
SetTextCharacterExtra( HDC hdc
, INT extra
)
1023 DC
* dc
= DC_GetDCPtr( hdc
);
1024 if (!dc
) return 0x80000000;
1025 if (dc
->funcs
->pSetTextCharacterExtra
)
1026 prev
= dc
->funcs
->pSetTextCharacterExtra( dc
->physDev
, extra
);
1029 prev
= dc
->charExtra
;
1030 dc
->charExtra
= extra
;
1032 DC_ReleaseDCPtr( dc
);
1037 /***********************************************************************
1038 * SetTextJustification (GDI32.@)
1040 BOOL WINAPI
SetTextJustification( HDC hdc
, INT extra
, INT breaks
)
1043 DC
* dc
= DC_GetDCPtr( hdc
);
1044 if (!dc
) return FALSE
;
1045 if (dc
->funcs
->pSetTextJustification
)
1046 ret
= dc
->funcs
->pSetTextJustification( dc
->physDev
, extra
, breaks
);
1049 extra
= abs((extra
* dc
->vportExtX
+ dc
->wndExtX
/ 2) / dc
->wndExtX
);
1050 if (!extra
) breaks
= 0;
1053 dc
->breakExtra
= extra
/ breaks
;
1054 dc
->breakRem
= extra
- (breaks
* dc
->breakExtra
);
1062 DC_ReleaseDCPtr( dc
);
1067 /***********************************************************************
1068 * GetTextFaceA (GDI32.@)
1070 INT WINAPI
GetTextFaceA( HDC hdc
, INT count
, LPSTR name
)
1072 INT res
= GetTextFaceW(hdc
, 0, NULL
);
1073 LPWSTR nameW
= HeapAlloc( GetProcessHeap(), 0, res
* 2 );
1074 GetTextFaceW( hdc
, res
, nameW
);
1078 if (count
&& !WideCharToMultiByte( CP_ACP
, 0, nameW
, -1, name
, count
, NULL
, NULL
))
1083 res
= WideCharToMultiByte( CP_ACP
, 0, nameW
, -1, NULL
, 0, NULL
, NULL
);
1084 HeapFree( GetProcessHeap(), 0, nameW
);
1088 /***********************************************************************
1089 * GetTextFaceW (GDI32.@)
1091 INT WINAPI
GetTextFaceW( HDC hdc
, INT count
, LPWSTR name
)
1096 DC
* dc
= DC_GetDCPtr( hdc
);
1100 ret
= WineEngGetTextFace(dc
->gdiFont
, count
, name
);
1101 else if ((font
= (FONTOBJ
*) GDI_GetObjPtr( dc
->hFont
, FONT_MAGIC
)))
1105 lstrcpynW( name
, font
->logfont
.lfFaceName
, count
);
1106 ret
= strlenW(name
);
1108 else ret
= strlenW(font
->logfont
.lfFaceName
) + 1;
1109 GDI_ReleaseObj( dc
->hFont
);
1111 DC_ReleaseDCPtr( dc
);
1116 /***********************************************************************
1117 * GetTextExtentPoint32A (GDI32.@)
1119 * See GetTextExtentPoint32W.
1121 BOOL WINAPI
GetTextExtentPoint32A( HDC hdc
, LPCSTR str
, INT count
,
1126 LPWSTR p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
1129 ret
= GetTextExtentPoint32W( hdc
, p
, wlen
, size
);
1130 HeapFree( GetProcessHeap(), 0, p
);
1133 TRACE("(%p %s %d %p): returning %d x %d\n",
1134 hdc
, debugstr_an (str
, count
), count
, size
, size
->cx
, size
->cy
);
1139 /***********************************************************************
1140 * GetTextExtentPoint32W [GDI32.@]
1142 * Computes width/height for a string.
1144 * Computes width and height of the specified string.
1150 BOOL WINAPI
GetTextExtentPoint32W(
1151 HDC hdc
, /* [in] Handle of device context */
1152 LPCWSTR str
, /* [in] Address of text string */
1153 INT count
, /* [in] Number of characters in string */
1154 LPSIZE size
) /* [out] Address of structure for string size */
1156 return GetTextExtentExPointW(hdc
, str
, count
, 0, NULL
, NULL
, size
);
1159 /***********************************************************************
1160 * GetTextExtentExPointI [GDI32.@]
1162 * Computes width and height of the array of glyph indices.
1165 * hdc [I] Handle of device context.
1166 * indices [I] Glyph index array.
1167 * count [I] Number of glyphs in array.
1168 * max_ext [I] Maximum width in glyphs.
1169 * nfit [O] Maximum number of characters.
1170 * dxs [O] Partial string widths.
1171 * size [O] Returned string size.
1177 BOOL WINAPI
GetTextExtentExPointI( HDC hdc
, const WORD
*indices
, INT count
, INT max_ext
,
1178 LPINT nfit
, LPINT dxs
, LPSIZE size
)
1181 DC
* dc
= DC_GetDCPtr( hdc
);
1182 if (!dc
) return FALSE
;
1185 ret
= WineEngGetTextExtentExPointI(dc
->gdiFont
, indices
, count
, max_ext
, nfit
, dxs
, size
);
1186 size
->cx
= abs(INTERNAL_XDSTOWS(dc
, size
->cx
));
1187 size
->cy
= abs(INTERNAL_YDSTOWS(dc
, size
->cy
));
1188 size
->cx
+= count
* dc
->charExtra
;
1190 else if(dc
->funcs
->pGetTextExtentExPoint
) {
1191 FIXME("calling GetTextExtentExPoint\n");
1192 ret
= dc
->funcs
->pGetTextExtentExPoint( dc
->physDev
, (LPCWSTR
)indices
,
1193 count
, max_ext
, nfit
, dxs
, size
);
1196 DC_ReleaseDCPtr( dc
);
1198 TRACE("(%p %p %d %p): returning %d x %d\n",
1199 hdc
, indices
, count
, size
, size
->cx
, size
->cy
);
1203 /***********************************************************************
1204 * GetTextExtentPointI [GDI32.@]
1206 * Computes width and height of the array of glyph indices.
1209 * hdc [I] Handle of device context.
1210 * indices [I] Glyph index array.
1211 * count [I] Number of glyphs in array.
1212 * size [O] Returned string size.
1218 BOOL WINAPI
GetTextExtentPointI( HDC hdc
, const WORD
*indices
, INT count
, LPSIZE size
)
1220 return GetTextExtentExPointI( hdc
, indices
, count
, 0, NULL
, NULL
, size
);
1224 /***********************************************************************
1225 * GetTextExtentPointA (GDI32.@)
1227 BOOL WINAPI
GetTextExtentPointA( HDC hdc
, LPCSTR str
, INT count
,
1230 TRACE("not bug compatible.\n");
1231 return GetTextExtentPoint32A( hdc
, str
, count
, size
);
1234 /***********************************************************************
1235 * GetTextExtentPointW (GDI32.@)
1237 BOOL WINAPI
GetTextExtentPointW( HDC hdc
, LPCWSTR str
, INT count
,
1240 TRACE("not bug compatible.\n");
1241 return GetTextExtentPoint32W( hdc
, str
, count
, size
);
1245 /***********************************************************************
1246 * GetTextExtentExPointA (GDI32.@)
1248 BOOL WINAPI
GetTextExtentExPointA( HDC hdc
, LPCSTR str
, INT count
,
1249 INT maxExt
, LPINT lpnFit
,
1250 LPINT alpDx
, LPSIZE size
)
1258 NULL
== (walpDx
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(INT
))))
1261 p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
1262 ret
= GetTextExtentExPointW( hdc
, p
, wlen
, maxExt
, lpnFit
, walpDx
, size
);
1265 INT n
= lpnFit
? *lpnFit
: wlen
;
1267 for(i
= 0, j
= 0; i
< n
; i
++, j
++)
1269 alpDx
[j
] = walpDx
[i
];
1270 if (IsDBCSLeadByte(str
[j
])) alpDx
[++j
] = walpDx
[i
];
1273 if (lpnFit
) *lpnFit
= WideCharToMultiByte(CP_ACP
,0,p
,*lpnFit
,NULL
,0,NULL
,NULL
);
1274 HeapFree( GetProcessHeap(), 0, p
);
1275 HeapFree( GetProcessHeap(), 0, walpDx
);
1280 /***********************************************************************
1281 * GetTextExtentExPointW (GDI32.@)
1283 * Return the size of the string as it would be if it was output properly by
1286 * This should include
1287 * - Intercharacter spacing
1288 * - justification spacing (not yet done)
1289 * - kerning? see below
1291 * Kerning. Since kerning would be carried out by the rendering code it should
1292 * be done by the driver. However they don't support it yet. Also I am not
1293 * yet persuaded that (certainly under Win95) any kerning is actually done.
1295 * str: According to MSDN this should be null-terminated. That is not true; a
1296 * null will not terminate it early.
1297 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1298 * than count. I have seen it be either the size of the full string or
1299 * 1 less than the size of the full string. I have not seen it bear any
1300 * resemblance to the portion that would fit.
1301 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1302 * trailing intercharacter spacing and any trailing justification.
1305 * Currently we do this by measuring each character etc. We should do it by
1306 * passing the request to the driver, perhaps by extending the
1307 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1308 * thinking about kerning issues and rounding issues in the justification.
1311 BOOL WINAPI
GetTextExtentExPointW( HDC hdc
, LPCWSTR str
, INT count
,
1312 INT maxExt
, LPINT lpnFit
,
1313 LPINT alpDx
, LPSIZE size
)
1321 TRACE("(%p, %s, %d)\n",hdc
,debugstr_wn(str
,count
),maxExt
);
1323 dc
= DC_GetDCPtr(hdc
);
1327 GetTextMetricsW(hdc
, &tm
);
1329 /* If we need to calculate nFit, then we need the partial extents even if
1330 the user hasn't provided us with an array. */
1333 dxs
= alpDx
? alpDx
: HeapAlloc(GetProcessHeap(), 0, count
* sizeof alpDx
[0]);
1336 DC_ReleaseDCPtr(dc
);
1337 SetLastError(ERROR_OUTOFMEMORY
);
1345 ret
= WineEngGetTextExtentExPoint(dc
->gdiFont
, str
, count
,
1346 0, NULL
, dxs
, size
);
1347 else if (dc
->funcs
->pGetTextExtentExPoint
)
1348 ret
= dc
->funcs
->pGetTextExtentExPoint(dc
->physDev
, str
, count
,
1349 0, NULL
, dxs
, size
);
1351 /* Perform device size to world size transformations. */
1354 INT extra
= dc
->charExtra
,
1355 breakExtra
= dc
->breakExtra
,
1356 breakRem
= dc
->breakRem
,
1361 for (i
= 0; i
< count
; ++i
)
1363 dxs
[i
] = abs(INTERNAL_XDSTOWS(dc
, dxs
[i
]));
1364 dxs
[i
] += (i
+1) * extra
;
1365 if (count
> 1 && (breakExtra
|| breakRem
) && str
[i
] == tm
.tmBreakChar
)
1367 dxs
[i
] += breakExtra
;
1374 if (dxs
[i
] <= maxExt
)
1377 breakRem
= dc
->breakRem
;
1379 size
->cx
= abs(INTERNAL_XDSTOWS(dc
, size
->cx
));
1380 size
->cy
= abs(INTERNAL_YDSTOWS(dc
, size
->cy
));
1382 if (!dxs
&& count
> 1 && (breakExtra
|| breakRem
))
1384 for (i
= 0; i
< count
; i
++)
1386 if (str
[i
] == tm
.tmBreakChar
)
1388 size
->cx
+= breakExtra
;
1403 HeapFree(GetProcessHeap(), 0, dxs
);
1405 DC_ReleaseDCPtr( dc
);
1407 TRACE("returning %d %d x %d\n",nFit
,size
->cx
,size
->cy
);
1411 /***********************************************************************
1412 * GetTextMetricsA (GDI32.@)
1414 BOOL WINAPI
GetTextMetricsA( HDC hdc
, TEXTMETRICA
*metrics
)
1418 if (!GetTextMetricsW( hdc
, &tm32
)) return FALSE
;
1419 FONT_TextMetricWToA( &tm32
, metrics
);
1423 /***********************************************************************
1424 * GetTextMetricsW (GDI32.@)
1426 BOOL WINAPI
GetTextMetricsW( HDC hdc
, TEXTMETRICW
*metrics
)
1429 DC
* dc
= DC_GetDCPtr( hdc
);
1430 if (!dc
) return FALSE
;
1433 ret
= WineEngGetTextMetrics(dc
->gdiFont
, metrics
);
1434 else if (dc
->funcs
->pGetTextMetrics
)
1435 ret
= dc
->funcs
->pGetTextMetrics( dc
->physDev
, metrics
);
1439 /* device layer returns values in device units
1440 * therefore we have to convert them to logical */
1442 metrics
->tmDigitizedAspectX
= GetDeviceCaps(hdc
, LOGPIXELSX
);
1443 metrics
->tmDigitizedAspectY
= GetDeviceCaps(hdc
, LOGPIXELSY
);
1445 #define WDPTOLP(x) ((x<0)? \
1446 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1447 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1448 #define HDPTOLP(y) ((y<0)? \
1449 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1450 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1452 metrics
->tmHeight
= HDPTOLP(metrics
->tmHeight
);
1453 metrics
->tmAscent
= HDPTOLP(metrics
->tmAscent
);
1454 metrics
->tmDescent
= HDPTOLP(metrics
->tmDescent
);
1455 metrics
->tmInternalLeading
= HDPTOLP(metrics
->tmInternalLeading
);
1456 metrics
->tmExternalLeading
= HDPTOLP(metrics
->tmExternalLeading
);
1457 metrics
->tmAveCharWidth
= WDPTOLP(metrics
->tmAveCharWidth
);
1458 metrics
->tmMaxCharWidth
= WDPTOLP(metrics
->tmMaxCharWidth
);
1459 metrics
->tmOverhang
= WDPTOLP(metrics
->tmOverhang
);
1463 TRACE("text metrics:\n"
1464 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1465 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1466 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1467 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1468 " PitchAndFamily = %02x\n"
1469 " --------------------\n"
1470 " InternalLeading = %i\n"
1474 metrics
->tmWeight
, metrics
->tmFirstChar
, metrics
->tmAveCharWidth
,
1475 metrics
->tmItalic
, metrics
->tmLastChar
, metrics
->tmMaxCharWidth
,
1476 metrics
->tmUnderlined
, metrics
->tmDefaultChar
, metrics
->tmOverhang
,
1477 metrics
->tmStruckOut
, metrics
->tmBreakChar
, metrics
->tmCharSet
,
1478 metrics
->tmPitchAndFamily
,
1479 metrics
->tmInternalLeading
,
1482 metrics
->tmHeight
);
1484 DC_ReleaseDCPtr( dc
);
1489 /***********************************************************************
1490 * GetOutlineTextMetrics [GDI.308] Gets metrics for TrueType fonts.
1493 * lpOTM should be LPOUTLINETEXTMETRIC
1496 * Success: Non-zero or size of required buffer
1499 UINT16 WINAPI
GetOutlineTextMetrics16(
1500 HDC16 hdc
, /* [in] Handle of device context */
1501 UINT16 cbData
, /* [in] Size of metric data array */
1502 LPOUTLINETEXTMETRIC16 lpOTM
) /* [out] Address of metric data array */
1504 FIXME("(%04x,%04x,%p): stub\n", hdc
,cbData
,lpOTM
);
1509 /***********************************************************************
1510 * GetOutlineTextMetricsA (GDI32.@)
1511 * Gets metrics for TrueType fonts.
1514 * If the supplied buffer isn't big enough Windows partially fills it up to
1515 * its given length and returns that length.
1518 * Success: Non-zero or size of required buffer
1521 UINT WINAPI
GetOutlineTextMetricsA(
1522 HDC hdc
, /* [in] Handle of device context */
1523 UINT cbData
, /* [in] Size of metric data array */
1524 LPOUTLINETEXTMETRICA lpOTM
) /* [out] Address of metric data array */
1526 char buf
[512], *ptr
;
1528 OUTLINETEXTMETRICW
*lpOTMW
= (OUTLINETEXTMETRICW
*)buf
;
1529 OUTLINETEXTMETRICA
*output
= lpOTM
;
1532 if((ret
= GetOutlineTextMetricsW(hdc
, 0, NULL
)) == 0)
1534 if(ret
> sizeof(buf
))
1535 lpOTMW
= HeapAlloc(GetProcessHeap(), 0, ret
);
1536 GetOutlineTextMetricsW(hdc
, ret
, lpOTMW
);
1538 needed
= sizeof(OUTLINETEXTMETRICA
);
1539 if(lpOTMW
->otmpFamilyName
)
1540 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1541 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFamilyName
), -1,
1542 NULL
, 0, NULL
, NULL
);
1543 if(lpOTMW
->otmpFaceName
)
1544 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1545 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFaceName
), -1,
1546 NULL
, 0, NULL
, NULL
);
1547 if(lpOTMW
->otmpStyleName
)
1548 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1549 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpStyleName
), -1,
1550 NULL
, 0, NULL
, NULL
);
1551 if(lpOTMW
->otmpFullName
)
1552 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1553 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFullName
), -1,
1554 NULL
, 0, NULL
, NULL
);
1561 TRACE("needed = %d\n", needed
);
1563 /* Since the supplied buffer isn't big enough, we'll alloc one
1564 that is and memcpy the first cbData bytes into the lpOTM at
1566 output
= HeapAlloc(GetProcessHeap(), 0, needed
);
1568 ret
= output
->otmSize
= min(needed
, cbData
);
1569 FONT_TextMetricWToA( &lpOTMW
->otmTextMetrics
, &output
->otmTextMetrics
);
1570 output
->otmFiller
= 0;
1571 output
->otmPanoseNumber
= lpOTMW
->otmPanoseNumber
;
1572 output
->otmfsSelection
= lpOTMW
->otmfsSelection
;
1573 output
->otmfsType
= lpOTMW
->otmfsType
;
1574 output
->otmsCharSlopeRise
= lpOTMW
->otmsCharSlopeRise
;
1575 output
->otmsCharSlopeRun
= lpOTMW
->otmsCharSlopeRun
;
1576 output
->otmItalicAngle
= lpOTMW
->otmItalicAngle
;
1577 output
->otmEMSquare
= lpOTMW
->otmEMSquare
;
1578 output
->otmAscent
= lpOTMW
->otmAscent
;
1579 output
->otmDescent
= lpOTMW
->otmDescent
;
1580 output
->otmLineGap
= lpOTMW
->otmLineGap
;
1581 output
->otmsCapEmHeight
= lpOTMW
->otmsCapEmHeight
;
1582 output
->otmsXHeight
= lpOTMW
->otmsXHeight
;
1583 output
->otmrcFontBox
= lpOTMW
->otmrcFontBox
;
1584 output
->otmMacAscent
= lpOTMW
->otmMacAscent
;
1585 output
->otmMacDescent
= lpOTMW
->otmMacDescent
;
1586 output
->otmMacLineGap
= lpOTMW
->otmMacLineGap
;
1587 output
->otmusMinimumPPEM
= lpOTMW
->otmusMinimumPPEM
;
1588 output
->otmptSubscriptSize
= lpOTMW
->otmptSubscriptSize
;
1589 output
->otmptSubscriptOffset
= lpOTMW
->otmptSubscriptOffset
;
1590 output
->otmptSuperscriptSize
= lpOTMW
->otmptSuperscriptSize
;
1591 output
->otmptSuperscriptOffset
= lpOTMW
->otmptSuperscriptOffset
;
1592 output
->otmsStrikeoutSize
= lpOTMW
->otmsStrikeoutSize
;
1593 output
->otmsStrikeoutPosition
= lpOTMW
->otmsStrikeoutPosition
;
1594 output
->otmsUnderscoreSize
= lpOTMW
->otmsUnderscoreSize
;
1595 output
->otmsUnderscorePosition
= lpOTMW
->otmsUnderscorePosition
;
1598 ptr
= (char*)(output
+ 1);
1599 left
= needed
- sizeof(*output
);
1601 if(lpOTMW
->otmpFamilyName
) {
1602 output
->otmpFamilyName
= (LPSTR
)(ptr
- (char*)output
);
1603 len
= WideCharToMultiByte(CP_ACP
, 0,
1604 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFamilyName
), -1,
1605 ptr
, left
, NULL
, NULL
);
1609 output
->otmpFamilyName
= 0;
1611 if(lpOTMW
->otmpFaceName
) {
1612 output
->otmpFaceName
= (LPSTR
)(ptr
- (char*)output
);
1613 len
= WideCharToMultiByte(CP_ACP
, 0,
1614 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFaceName
), -1,
1615 ptr
, left
, NULL
, NULL
);
1619 output
->otmpFaceName
= 0;
1621 if(lpOTMW
->otmpStyleName
) {
1622 output
->otmpStyleName
= (LPSTR
)(ptr
- (char*)output
);
1623 len
= WideCharToMultiByte(CP_ACP
, 0,
1624 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpStyleName
), -1,
1625 ptr
, left
, NULL
, NULL
);
1629 output
->otmpStyleName
= 0;
1631 if(lpOTMW
->otmpFullName
) {
1632 output
->otmpFullName
= (LPSTR
)(ptr
- (char*)output
);
1633 len
= WideCharToMultiByte(CP_ACP
, 0,
1634 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFullName
), -1,
1635 ptr
, left
, NULL
, NULL
);
1638 output
->otmpFullName
= 0;
1642 if(output
!= lpOTM
) {
1643 memcpy(lpOTM
, output
, cbData
);
1644 HeapFree(GetProcessHeap(), 0, output
);
1646 /* check if the string offsets really fit into the provided size */
1647 /* FIXME: should we check string length as well? */
1648 /* make sure that we don't read/write beyond the provided buffer */
1649 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFamilyName
) + sizeof(LPSTR
))
1651 if ((UINT_PTR
)lpOTM
->otmpFamilyName
>= lpOTM
->otmSize
)
1652 lpOTM
->otmpFamilyName
= 0; /* doesn't fit */
1655 /* make sure that we don't read/write beyond the provided buffer */
1656 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFaceName
) + sizeof(LPSTR
))
1658 if ((UINT_PTR
)lpOTM
->otmpFaceName
>= lpOTM
->otmSize
)
1659 lpOTM
->otmpFaceName
= 0; /* doesn't fit */
1662 /* make sure that we don't read/write beyond the provided buffer */
1663 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpStyleName
) + sizeof(LPSTR
))
1665 if ((UINT_PTR
)lpOTM
->otmpStyleName
>= lpOTM
->otmSize
)
1666 lpOTM
->otmpStyleName
= 0; /* doesn't fit */
1669 /* make sure that we don't read/write beyond the provided buffer */
1670 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFullName
) + sizeof(LPSTR
))
1672 if ((UINT_PTR
)lpOTM
->otmpFullName
>= lpOTM
->otmSize
)
1673 lpOTM
->otmpFullName
= 0; /* doesn't fit */
1678 if(lpOTMW
!= (OUTLINETEXTMETRICW
*)buf
)
1679 HeapFree(GetProcessHeap(), 0, lpOTMW
);
1685 /***********************************************************************
1686 * GetOutlineTextMetricsW [GDI32.@]
1688 UINT WINAPI
GetOutlineTextMetricsW(
1689 HDC hdc
, /* [in] Handle of device context */
1690 UINT cbData
, /* [in] Size of metric data array */
1691 LPOUTLINETEXTMETRICW lpOTM
) /* [out] Address of metric data array */
1693 DC
*dc
= DC_GetDCPtr( hdc
);
1694 OUTLINETEXTMETRICW
*output
= lpOTM
;
1697 TRACE("(%p,%d,%p)\n", hdc
, cbData
, lpOTM
);
1701 ret
= WineEngGetOutlineTextMetrics(dc
->gdiFont
, cbData
, output
);
1704 output
= HeapAlloc(GetProcessHeap(), 0, ret
);
1705 WineEngGetOutlineTextMetrics(dc
->gdiFont
, ret
, output
);
1708 #define WDPTOLP(x) ((x<0)? \
1709 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1710 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1711 #define HDPTOLP(y) ((y<0)? \
1712 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1713 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1715 output
->otmTextMetrics
.tmHeight
= HDPTOLP(output
->otmTextMetrics
.tmHeight
);
1716 output
->otmTextMetrics
.tmAscent
= HDPTOLP(output
->otmTextMetrics
.tmAscent
);
1717 output
->otmTextMetrics
.tmDescent
= HDPTOLP(output
->otmTextMetrics
.tmDescent
);
1718 output
->otmTextMetrics
.tmInternalLeading
= HDPTOLP(output
->otmTextMetrics
.tmInternalLeading
);
1719 output
->otmTextMetrics
.tmExternalLeading
= HDPTOLP(output
->otmTextMetrics
.tmExternalLeading
);
1720 output
->otmTextMetrics
.tmAveCharWidth
= WDPTOLP(output
->otmTextMetrics
.tmAveCharWidth
);
1721 output
->otmTextMetrics
.tmMaxCharWidth
= WDPTOLP(output
->otmTextMetrics
.tmMaxCharWidth
);
1722 output
->otmTextMetrics
.tmOverhang
= WDPTOLP(output
->otmTextMetrics
.tmOverhang
);
1723 output
->otmAscent
= HDPTOLP(output
->otmAscent
);
1724 output
->otmDescent
= HDPTOLP(output
->otmDescent
);
1725 output
->otmLineGap
= HDPTOLP(output
->otmLineGap
);
1726 output
->otmsCapEmHeight
= HDPTOLP(output
->otmsCapEmHeight
);
1727 output
->otmsXHeight
= HDPTOLP(output
->otmsXHeight
);
1728 output
->otmrcFontBox
.top
= HDPTOLP(output
->otmrcFontBox
.top
);
1729 output
->otmrcFontBox
.bottom
= HDPTOLP(output
->otmrcFontBox
.bottom
);
1730 output
->otmrcFontBox
.left
= WDPTOLP(output
->otmrcFontBox
.left
);
1731 output
->otmrcFontBox
.right
= WDPTOLP(output
->otmrcFontBox
.right
);
1732 output
->otmMacAscent
= HDPTOLP(output
->otmMacAscent
);
1733 output
->otmMacDescent
= HDPTOLP(output
->otmMacDescent
);
1734 output
->otmMacLineGap
= HDPTOLP(output
->otmMacLineGap
);
1735 output
->otmptSubscriptSize
.x
= WDPTOLP(output
->otmptSubscriptSize
.x
);
1736 output
->otmptSubscriptSize
.y
= HDPTOLP(output
->otmptSubscriptSize
.y
);
1737 output
->otmptSubscriptOffset
.x
= WDPTOLP(output
->otmptSubscriptOffset
.x
);
1738 output
->otmptSubscriptOffset
.y
= HDPTOLP(output
->otmptSubscriptOffset
.y
);
1739 output
->otmptSuperscriptSize
.x
= WDPTOLP(output
->otmptSuperscriptSize
.x
);
1740 output
->otmptSuperscriptSize
.y
= HDPTOLP(output
->otmptSuperscriptSize
.y
);
1741 output
->otmptSuperscriptOffset
.x
= WDPTOLP(output
->otmptSuperscriptOffset
.x
);
1742 output
->otmptSuperscriptOffset
.y
= HDPTOLP(output
->otmptSuperscriptOffset
.y
);
1743 output
->otmsStrikeoutSize
= HDPTOLP(output
->otmsStrikeoutSize
);
1744 output
->otmsStrikeoutPosition
= HDPTOLP(output
->otmsStrikeoutPosition
);
1745 output
->otmsUnderscoreSize
= HDPTOLP(output
->otmsUnderscoreSize
);
1746 output
->otmsUnderscorePosition
= HDPTOLP(output
->otmsUnderscorePosition
);
1749 if(output
!= lpOTM
) {
1750 memcpy(lpOTM
, output
, cbData
);
1751 HeapFree(GetProcessHeap(), 0, output
);
1757 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1758 but really this should just be a return 0. */
1760 ret
= sizeof(*lpOTM
);
1765 memset(lpOTM
, 0, ret
);
1766 lpOTM
->otmSize
= sizeof(*lpOTM
);
1767 GetTextMetricsW(hdc
, &lpOTM
->otmTextMetrics
);
1769 Further fill of the structure not implemented,
1770 Needs real values for the structure members
1775 DC_ReleaseDCPtr(dc
);
1780 /***********************************************************************
1781 * GetCharWidthW (GDI32.@)
1782 * GetCharWidth32W (GDI32.@)
1784 BOOL WINAPI
GetCharWidth32W( HDC hdc
, UINT firstChar
, UINT lastChar
,
1789 DC
* dc
= DC_GetDCPtr( hdc
);
1790 if (!dc
) return FALSE
;
1793 ret
= WineEngGetCharWidth( dc
->gdiFont
, firstChar
, lastChar
, buffer
);
1794 else if (dc
->funcs
->pGetCharWidth
)
1795 ret
= dc
->funcs
->pGetCharWidth( dc
->physDev
, firstChar
, lastChar
, buffer
);
1799 /* convert device units to logical */
1800 for( i
= firstChar
; i
<= lastChar
; i
++, buffer
++ )
1801 *buffer
= INTERNAL_XDSTOWS(dc
, *buffer
);
1804 DC_ReleaseDCPtr( dc
);
1809 /***********************************************************************
1810 * GetCharWidthA (GDI32.@)
1811 * GetCharWidth32A (GDI32.@)
1813 BOOL WINAPI
GetCharWidth32A( HDC hdc
, UINT firstChar
, UINT lastChar
,
1816 INT i
, wlen
, count
= (INT
)(lastChar
- firstChar
+ 1);
1821 if(count
<= 0) return FALSE
;
1823 str
= HeapAlloc(GetProcessHeap(), 0, count
);
1824 for(i
= 0; i
< count
; i
++)
1825 str
[i
] = (BYTE
)(firstChar
+ i
);
1827 wstr
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
1829 for(i
= 0; i
< wlen
; i
++)
1831 if(!GetCharWidth32W(hdc
, wstr
[i
], wstr
[i
], buffer
))
1839 HeapFree(GetProcessHeap(), 0, str
);
1840 HeapFree(GetProcessHeap(), 0, wstr
);
1846 /***********************************************************************
1847 * ExtTextOutA (GDI32.@)
1851 BOOL WINAPI
ExtTextOutA( HDC hdc
, INT x
, INT y
, UINT flags
,
1852 const RECT
*lprect
, LPCSTR str
, UINT count
, const INT
*lpDx
)
1860 if (flags
& ETO_GLYPH_INDEX
)
1861 return ExtTextOutW( hdc
, x
, y
, flags
, lprect
, (LPCWSTR
)str
, count
, lpDx
);
1863 p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, &codepage
);
1866 unsigned int i
= 0, j
= 0;
1868 lpDxW
= HeapAlloc( GetProcessHeap(), 0, wlen
*sizeof(INT
));
1870 if(IsDBCSLeadByteEx(codepage
, str
[i
])) {
1871 lpDxW
[j
++] = lpDx
[i
] + lpDx
[i
+1];
1874 lpDxW
[j
++] = lpDx
[i
];
1880 ret
= ExtTextOutW( hdc
, x
, y
, flags
, lprect
, p
, wlen
, lpDxW
);
1882 HeapFree( GetProcessHeap(), 0, p
);
1883 HeapFree( GetProcessHeap(), 0, lpDxW
);
1888 /***********************************************************************
1889 * ExtTextOutW (GDI32.@)
1891 * Draws text using the currently selected font, background color, and text color.
1895 * x,y [I] coordinates of string
1897 * ETO_GRAYED - undocumented on MSDN
1898 * ETO_OPAQUE - use background color for fill the rectangle
1899 * ETO_CLIPPED - clipping text to the rectangle
1900 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1901 * than encoded characters. Implies ETO_IGNORELANGUAGE
1902 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1903 * Affects BiDi ordering
1904 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1905 * ETO_PDY - unimplemented
1906 * ETO_NUMERICSLATIN - unimplemented always assumed -
1907 * do not translate numbers into locale representations
1908 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1909 * lprect [I] dimensions for clipping or/and opaquing
1910 * str [I] text string
1911 * count [I] number of symbols in string
1912 * lpDx [I] optional parameter with distance between drawing characters
1918 BOOL WINAPI
ExtTextOutW( HDC hdc
, INT x
, INT y
, UINT flags
,
1919 const RECT
*lprect
, LPCWSTR str
, UINT count
, const INT
*lpDx
)
1922 LPWSTR reordered_str
= (LPWSTR
)str
;
1923 WORD
*glyphs
= NULL
;
1924 UINT align
= GetTextAlign( hdc
);
1928 double cosEsc
, sinEsc
;
1929 INT
*deltas
= NULL
, char_extra
;
1932 BOOL done_extents
= FALSE
;
1933 INT width
= 0, xwidth
= 0, ywidth
= 0;
1935 DC
* dc
= get_dc_ptr( hdc
);
1938 if (!dc
) return FALSE
;
1940 breakRem
= dc
->breakRem
;
1942 if (flags
& (ETO_NUMERICSLOCAL
| ETO_NUMERICSLATIN
| ETO_PDY
))
1943 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY unimplemented\n");
1945 if (!dc
->funcs
->pExtTextOut
&& !PATH_IsPathOpen(dc
->path
))
1947 release_dc_ptr( dc
);
1952 type
= GetObjectType(hdc
);
1953 if(type
== OBJ_METADC
|| type
== OBJ_ENHMETADC
)
1955 ret
= dc
->funcs
->pExtTextOut(dc
->physDev
, x
, y
, flags
, lprect
, str
, count
, lpDx
);
1956 release_dc_ptr( dc
);
1961 flags
&= ~ETO_CLIPPED
;
1963 if( !(flags
& (ETO_GLYPH_INDEX
| ETO_IGNORELANGUAGE
)) && count
> 0 )
1965 reordered_str
= HeapAlloc(GetProcessHeap(), 0, count
*sizeof(WCHAR
));
1967 BIDI_Reorder( str
, count
, GCP_REORDER
,
1968 ((flags
&ETO_RTLREADING
)!=0 || (GetTextAlign(hdc
)&TA_RTLREADING
)!=0)?
1969 WINE_GCPW_FORCE_RTL
:WINE_GCPW_FORCE_LTR
,
1970 reordered_str
, count
, NULL
);
1972 flags
|= ETO_IGNORELANGUAGE
;
1975 TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc
, x
, y
, flags
,
1976 lprect
, debugstr_wn(str
, count
), count
, lpDx
);
1978 if(flags
& ETO_GLYPH_INDEX
)
1979 glyphs
= reordered_str
;
1982 TRACE("rect: %d,%d - %d,%d\n", lprect
->left
, lprect
->top
, lprect
->right
,
1984 TRACE("align = %x bkmode = %x mapmode = %x\n", align
, GetBkMode(hdc
), GetMapMode(hdc
));
1986 if(align
& TA_UPDATECP
)
1988 GetCurrentPositionEx( hdc
, &pt
);
1993 GetTextMetricsW(hdc
, &tm
);
1994 GetObjectW(GetCurrentObject(hdc
, OBJ_FONT
), sizeof(lf
), &lf
);
1996 if(!(tm
.tmPitchAndFamily
& TMPF_VECTOR
)) /* Non-scalable fonts shouldn't be rotated */
1997 lf
.lfEscapement
= 0;
1999 if(lf
.lfEscapement
!= 0)
2001 cosEsc
= cos(lf
.lfEscapement
* M_PI
/ 1800);
2002 sinEsc
= sin(lf
.lfEscapement
* M_PI
/ 1800);
2010 if(flags
& (ETO_CLIPPED
| ETO_OPAQUE
))
2014 if(flags
& ETO_GLYPH_INDEX
)
2015 GetTextExtentPointI(hdc
, glyphs
, count
, &sz
);
2017 GetTextExtentPointW(hdc
, reordered_str
, count
, &sz
);
2019 done_extents
= TRUE
;
2022 rc
.right
= x
+ sz
.cx
;
2023 rc
.bottom
= y
+ sz
.cy
;
2030 LPtoDP(hdc
, (POINT
*)&rc
, 2);
2032 if(rc
.left
> rc
.right
) {INT tmp
= rc
.left
; rc
.left
= rc
.right
; rc
.right
= tmp
;}
2033 if(rc
.top
> rc
.bottom
) {INT tmp
= rc
.top
; rc
.top
= rc
.bottom
; rc
.bottom
= tmp
;}
2036 if ((flags
& ETO_OPAQUE
) && !PATH_IsPathOpen(dc
->path
))
2037 dc
->funcs
->pExtTextOut(dc
->physDev
, 0, 0, ETO_OPAQUE
, &rc
, NULL
, 0, NULL
);
2047 LPtoDP(hdc
, &pt
, 1);
2051 char_extra
= GetTextCharacterExtra(hdc
);
2052 if(char_extra
|| dc
->breakExtra
|| breakRem
|| lpDx
|| lf
.lfEscapement
!= 0)
2056 deltas
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(INT
));
2057 for(i
= 0; i
< count
; i
++)
2059 if(lpDx
&& (flags
& ETO_PDY
))
2060 deltas
[i
] = lpDx
[i
*2] + char_extra
;
2062 deltas
[i
] = lpDx
[i
] + char_extra
;
2065 if(flags
& ETO_GLYPH_INDEX
)
2066 GetTextExtentPointI(hdc
, glyphs
+ i
, 1, &tmpsz
);
2068 GetTextExtentPointW(hdc
, reordered_str
+ i
, 1, &tmpsz
);
2070 deltas
[i
] = tmpsz
.cx
;
2073 if (!(flags
& ETO_GLYPH_INDEX
) && (dc
->breakExtra
|| breakRem
) && reordered_str
[i
] == tm
.tmBreakChar
)
2075 deltas
[i
] = deltas
[i
] + dc
->breakExtra
;
2082 deltas
[i
] = INTERNAL_XWSTODS(dc
, deltas
[i
]);
2090 if(flags
& ETO_GLYPH_INDEX
)
2091 GetTextExtentPointI(hdc
, glyphs
, count
, &sz
);
2093 GetTextExtentPointW(hdc
, reordered_str
, count
, &sz
);
2094 done_extents
= TRUE
;
2096 width
= INTERNAL_XWSTODS(dc
, sz
.cx
);
2098 xwidth
= width
* cosEsc
;
2099 ywidth
= width
* sinEsc
;
2101 tm
.tmAscent
= abs(INTERNAL_YWSTODS(dc
, tm
.tmAscent
));
2102 tm
.tmDescent
= abs(INTERNAL_YWSTODS(dc
, tm
.tmDescent
));
2103 switch( align
& (TA_LEFT
| TA_RIGHT
| TA_CENTER
) )
2106 if (align
& TA_UPDATECP
)
2110 DPtoLP(hdc
, &pt
, 1);
2111 MoveToEx(hdc
, pt
.x
, pt
.y
, NULL
);
2123 if (align
& TA_UPDATECP
)
2127 DPtoLP(hdc
, &pt
, 1);
2128 MoveToEx(hdc
, pt
.x
, pt
.y
, NULL
);
2133 switch( align
& (TA_TOP
| TA_BOTTOM
| TA_BASELINE
) )
2136 y
+= tm
.tmAscent
* cosEsc
;
2137 x
+= tm
.tmAscent
* sinEsc
;
2141 y
-= tm
.tmDescent
* cosEsc
;
2142 x
-= tm
.tmDescent
* sinEsc
;
2149 if (GetBkMode(hdc
) != TRANSPARENT
&& !PATH_IsPathOpen(dc
->path
))
2151 if(!((flags
& ETO_CLIPPED
) && (flags
& ETO_OPAQUE
)))
2153 if(!(flags
& ETO_OPAQUE
) || x
< rc
.left
|| x
+ width
>= rc
.right
||
2154 y
- tm
.tmAscent
< rc
.top
|| y
+ tm
.tmDescent
>= rc
.bottom
)
2158 rc
.right
= x
+ width
;
2159 rc
.top
= y
- tm
.tmAscent
;
2160 rc
.bottom
= y
+ tm
.tmDescent
;
2161 dc
->funcs
->pExtTextOut(dc
->physDev
, 0, 0, ETO_OPAQUE
, &rc
, NULL
, 0, NULL
);
2166 if(FontIsLinked(hdc
) && !(flags
& ETO_GLYPH_INDEX
))
2168 HFONT orig_font
= dc
->hFont
, cur_font
;
2170 INT span
= 0, *offsets
= NULL
;
2173 glyphs
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(WORD
));
2174 for(i
= 0; i
< count
; i
++)
2176 WineEngGetLinkedHFont(dc
, reordered_str
[i
], &cur_font
, &glyph
);
2177 if(cur_font
!= dc
->hFont
)
2182 offsets
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(*deltas
));
2187 for(j
= 1; j
< count
; j
++)
2189 GetTextExtentPointW(hdc
, reordered_str
+ j
- 1, 1, &tmpsz
);
2190 offsets
[j
] = offsets
[j
-1] + INTERNAL_XWSTODS(dc
, tmpsz
.cx
);
2195 for(j
= 1; j
< count
; j
++)
2196 offsets
[j
] = offsets
[j
-1] + deltas
[j
];
2201 if (PATH_IsPathOpen(dc
->path
))
2202 ret
= PATH_ExtTextOut(dc
, x
+ offsets
[i
- span
] * cosEsc
, y
- offsets
[i
- span
] * sinEsc
,
2203 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
,
2204 glyphs
, span
, deltas
? deltas
+ i
- span
: NULL
);
2206 dc
->funcs
->pExtTextOut(dc
->physDev
, x
+ offsets
[i
- span
] * cosEsc
, y
- offsets
[i
- span
] * sinEsc
,
2207 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
,
2208 glyphs
, span
, deltas
? deltas
+ i
- span
: NULL
);
2211 SelectObject(hdc
, cur_font
);
2213 glyphs
[span
++] = glyph
;
2217 if (PATH_IsPathOpen(dc
->path
))
2218 ret
= PATH_ExtTextOut(dc
, x
+ (offsets
? offsets
[count
- span
] * cosEsc
: 0),
2219 y
- (offsets
? offsets
[count
- span
] * sinEsc
: 0),
2220 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
,
2221 glyphs
, span
, deltas
? deltas
+ count
- span
: NULL
);
2223 ret
= dc
->funcs
->pExtTextOut(dc
->physDev
, x
+ (offsets
? offsets
[count
- span
] * cosEsc
: 0),
2224 y
- (offsets
? offsets
[count
- span
] * sinEsc
: 0),
2225 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
,
2226 glyphs
, span
, deltas
? deltas
+ count
- span
: NULL
);
2227 SelectObject(hdc
, orig_font
);
2228 HeapFree(GetProcessHeap(), 0, offsets
);
2234 if(!(flags
& ETO_GLYPH_INDEX
) && dc
->gdiFont
)
2236 glyphs
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(WORD
));
2237 GetGlyphIndicesW(hdc
, reordered_str
, count
, glyphs
, 0);
2238 flags
|= ETO_GLYPH_INDEX
;
2241 if (PATH_IsPathOpen(dc
->path
))
2242 ret
= PATH_ExtTextOut(dc
, x
, y
, (flags
& ~ETO_OPAQUE
), &rc
,
2243 glyphs
? glyphs
: reordered_str
, count
, deltas
);
2245 ret
= dc
->funcs
->pExtTextOut(dc
->physDev
, x
, y
, (flags
& ~ETO_OPAQUE
), &rc
,
2246 glyphs
? glyphs
: reordered_str
, count
, deltas
);
2250 HeapFree(GetProcessHeap(), 0, deltas
);
2251 if(glyphs
!= reordered_str
)
2252 HeapFree(GetProcessHeap(), 0, glyphs
);
2253 if(reordered_str
!= str
)
2254 HeapFree(GetProcessHeap(), 0, reordered_str
);
2256 release_dc_ptr( dc
);
2258 if (ret
&& (lf
.lfUnderline
|| lf
.lfStrikeOut
))
2260 int underlinePos
, strikeoutPos
;
2261 int underlineWidth
, strikeoutWidth
;
2262 UINT size
= GetOutlineTextMetricsW(hdc
, 0, NULL
);
2263 OUTLINETEXTMETRICW
* otm
= NULL
;
2268 underlineWidth
= tm
.tmAscent
/ 20 + 1;
2269 strikeoutPos
= tm
.tmAscent
/ 2;
2270 strikeoutWidth
= underlineWidth
;
2274 otm
= HeapAlloc(GetProcessHeap(), 0, size
);
2275 GetOutlineTextMetricsW(hdc
, size
, otm
);
2276 underlinePos
= otm
->otmsUnderscorePosition
;
2277 underlineWidth
= otm
->otmsUnderscoreSize
;
2278 strikeoutPos
= otm
->otmsStrikeoutPosition
;
2279 strikeoutWidth
= otm
->otmsStrikeoutSize
;
2280 HeapFree(GetProcessHeap(), 0, otm
);
2283 if (PATH_IsPathOpen(dc
->path
))
2287 HBRUSH hbrush
= CreateSolidBrush(GetTextColor(hdc
));
2289 hbrush
= SelectObject(hdc
, hbrush
);
2290 hpen
= SelectObject(hdc
, GetStockObject(NULL_PEN
));
2294 pts
[0].x
= x
- underlinePos
* sinEsc
;
2295 pts
[0].y
= y
- underlinePos
* cosEsc
;
2296 pts
[1].x
= x
+ xwidth
- underlinePos
* sinEsc
;
2297 pts
[1].y
= y
- ywidth
- underlinePos
* cosEsc
;
2298 pts
[2].x
= pts
[1].x
+ underlineWidth
* sinEsc
;
2299 pts
[2].y
= pts
[1].y
+ underlineWidth
* cosEsc
;
2300 pts
[3].x
= pts
[0].x
+ underlineWidth
* sinEsc
;
2301 pts
[3].y
= pts
[0].y
+ underlineWidth
* cosEsc
;
2302 pts
[4].x
= pts
[0].x
;
2303 pts
[4].y
= pts
[0].y
;
2304 DPtoLP(hdc
, pts
, 5);
2305 Polygon(hdc
, pts
, 5);
2310 pts
[0].x
= x
- strikeoutPos
* sinEsc
;
2311 pts
[0].y
= y
- strikeoutPos
* cosEsc
;
2312 pts
[1].x
= x
+ xwidth
- strikeoutPos
* sinEsc
;
2313 pts
[1].y
= y
- ywidth
- strikeoutPos
* cosEsc
;
2314 pts
[2].x
= pts
[1].x
+ strikeoutWidth
* sinEsc
;
2315 pts
[2].y
= pts
[1].y
+ strikeoutWidth
* cosEsc
;
2316 pts
[3].x
= pts
[0].x
+ strikeoutWidth
* sinEsc
;
2317 pts
[3].y
= pts
[0].y
+ strikeoutWidth
* cosEsc
;
2318 pts
[4].x
= pts
[0].x
;
2319 pts
[4].y
= pts
[0].y
;
2320 DPtoLP(hdc
, pts
, 5);
2321 Polygon(hdc
, pts
, 5);
2324 SelectObject(hdc
, hpen
);
2325 hbrush
= SelectObject(hdc
, hbrush
);
2326 DeleteObject(hbrush
);
2330 POINT pts
[2], oldpt
;
2335 hpen
= CreatePen(PS_SOLID
, underlineWidth
, GetTextColor(hdc
));
2336 hpen
= SelectObject(hdc
, hpen
);
2339 pts
[1].x
= x
+ xwidth
;
2340 pts
[1].y
= y
- ywidth
;
2341 DPtoLP(hdc
, pts
, 2);
2342 MoveToEx(hdc
, pts
[0].x
- underlinePos
* sinEsc
, pts
[0].y
- underlinePos
* cosEsc
, &oldpt
);
2343 LineTo(hdc
, pts
[1].x
- underlinePos
* sinEsc
, pts
[1].y
- underlinePos
* cosEsc
);
2344 MoveToEx(hdc
, oldpt
.x
, oldpt
.y
, NULL
);
2345 DeleteObject(SelectObject(hdc
, hpen
));
2350 hpen
= CreatePen(PS_SOLID
, strikeoutWidth
, GetTextColor(hdc
));
2351 hpen
= SelectObject(hdc
, hpen
);
2354 pts
[1].x
= x
+ xwidth
;
2355 pts
[1].y
= y
- ywidth
;
2356 DPtoLP(hdc
, pts
, 2);
2357 MoveToEx(hdc
, pts
[0].x
- strikeoutPos
* sinEsc
, pts
[0].y
- strikeoutPos
* cosEsc
, &oldpt
);
2358 LineTo(hdc
, pts
[1].x
- strikeoutPos
* sinEsc
, pts
[1].y
- strikeoutPos
* cosEsc
);
2359 MoveToEx(hdc
, oldpt
.x
, oldpt
.y
, NULL
);
2360 DeleteObject(SelectObject(hdc
, hpen
));
2369 /***********************************************************************
2370 * TextOutA (GDI32.@)
2372 BOOL WINAPI
TextOutA( HDC hdc
, INT x
, INT y
, LPCSTR str
, INT count
)
2374 return ExtTextOutA( hdc
, x
, y
, 0, NULL
, str
, count
, NULL
);
2378 /***********************************************************************
2379 * TextOutW (GDI32.@)
2381 BOOL WINAPI
TextOutW(HDC hdc
, INT x
, INT y
, LPCWSTR str
, INT count
)
2383 return ExtTextOutW( hdc
, x
, y
, 0, NULL
, str
, count
, NULL
);
2387 /***********************************************************************
2388 * PolyTextOutA (GDI32.@)
2392 BOOL WINAPI
PolyTextOutA( HDC hdc
, const POLYTEXTA
*pptxt
, INT cStrings
)
2394 for (; cStrings
>0; cStrings
--, pptxt
++)
2395 if (!ExtTextOutA( hdc
, pptxt
->x
, pptxt
->y
, pptxt
->uiFlags
, &pptxt
->rcl
, pptxt
->lpstr
, pptxt
->n
, pptxt
->pdx
))
2402 /***********************************************************************
2403 * PolyTextOutW (GDI32.@)
2405 * Draw several Strings
2411 BOOL WINAPI
PolyTextOutW( HDC hdc
, const POLYTEXTW
*pptxt
, INT cStrings
)
2413 for (; cStrings
>0; cStrings
--, pptxt
++)
2414 if (!ExtTextOutW( hdc
, pptxt
->x
, pptxt
->y
, pptxt
->uiFlags
, &pptxt
->rcl
, pptxt
->lpstr
, pptxt
->n
, pptxt
->pdx
))
2420 /* FIXME: all following APIs ******************************************/
2423 /***********************************************************************
2424 * SetMapperFlags (GDI32.@)
2426 DWORD WINAPI
SetMapperFlags( HDC hDC
, DWORD dwFlag
)
2428 DC
*dc
= DC_GetDCPtr( hDC
);
2431 if(dc
->funcs
->pSetMapperFlags
)
2433 ret
= dc
->funcs
->pSetMapperFlags( dc
->physDev
, dwFlag
);
2434 /* FIXME: ret is just a success flag, we should return a proper value */
2437 FIXME("(%p, 0x%08x): stub - harmless\n", hDC
, dwFlag
);
2438 DC_ReleaseDCPtr( dc
);
2442 /***********************************************************************
2443 * GetAspectRatioFilterEx (GDI.486)
2445 BOOL16 WINAPI
GetAspectRatioFilterEx16( HDC16 hdc
, LPSIZE16 pAspectRatio
)
2447 FIXME("(%04x, %p): -- Empty Stub !\n", hdc
, pAspectRatio
);
2451 /***********************************************************************
2452 * GetAspectRatioFilterEx (GDI32.@)
2454 BOOL WINAPI
GetAspectRatioFilterEx( HDC hdc
, LPSIZE pAspectRatio
)
2456 FIXME("(%p, %p): -- Empty Stub !\n", hdc
, pAspectRatio
);
2461 /***********************************************************************
2462 * GetCharABCWidthsA (GDI32.@)
2464 * See GetCharABCWidthsW.
2466 BOOL WINAPI
GetCharABCWidthsA(HDC hdc
, UINT firstChar
, UINT lastChar
,
2469 INT i
, wlen
, count
= (INT
)(lastChar
- firstChar
+ 1);
2474 if(count
<= 0) return FALSE
;
2476 str
= HeapAlloc(GetProcessHeap(), 0, count
);
2477 for(i
= 0; i
< count
; i
++)
2478 str
[i
] = (BYTE
)(firstChar
+ i
);
2480 wstr
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
2482 for(i
= 0; i
< wlen
; i
++)
2484 if(!GetCharABCWidthsW(hdc
, wstr
[i
], wstr
[i
], abc
))
2492 HeapFree(GetProcessHeap(), 0, str
);
2493 HeapFree(GetProcessHeap(), 0, wstr
);
2499 /******************************************************************************
2500 * GetCharABCWidthsW [GDI32.@]
2502 * Retrieves widths of characters in range.
2505 * hdc [I] Handle of device context
2506 * firstChar [I] First character in range to query
2507 * lastChar [I] Last character in range to query
2508 * abc [O] Address of character-width structure
2511 * Only works with TrueType fonts
2517 BOOL WINAPI
GetCharABCWidthsW( HDC hdc
, UINT firstChar
, UINT lastChar
,
2520 DC
*dc
= DC_GetDCPtr(hdc
);
2524 if (!dc
) return FALSE
;
2528 DC_ReleaseDCPtr( dc
);
2533 ret
= WineEngGetCharABCWidths( dc
->gdiFont
, firstChar
, lastChar
, abc
);
2539 /* convert device units to logical */
2540 for( i
= firstChar
; i
<= lastChar
; i
++, abc
++ ) {
2541 abc
->abcA
= INTERNAL_XDSTOWS(dc
, abc
->abcA
);
2542 abc
->abcB
= INTERNAL_XDSTOWS(dc
, abc
->abcB
);
2543 abc
->abcC
= INTERNAL_XDSTOWS(dc
, abc
->abcC
);
2548 DC_ReleaseDCPtr( dc
);
2553 /******************************************************************************
2554 * GetCharABCWidthsI [GDI32.@]
2556 * Retrieves widths of characters in range.
2559 * hdc [I] Handle of device context
2560 * firstChar [I] First glyphs in range to query
2561 * count [I] Last glyphs in range to query
2562 * pgi [i] Array of glyphs to query
2563 * abc [O] Address of character-width structure
2566 * Only works with TrueType fonts
2572 BOOL WINAPI
GetCharABCWidthsI( HDC hdc
, UINT firstChar
, UINT count
,
2573 LPWORD pgi
, LPABC abc
)
2575 DC
*dc
= DC_GetDCPtr(hdc
);
2579 if (!dc
) return FALSE
;
2583 DC_ReleaseDCPtr( dc
);
2588 ret
= WineEngGetCharABCWidthsI( dc
->gdiFont
, firstChar
, count
, pgi
, abc
);
2594 /* convert device units to logical */
2595 for( i
= 0; i
< count
; i
++, abc
++ ) {
2596 abc
->abcA
= INTERNAL_XDSTOWS(dc
, abc
->abcA
);
2597 abc
->abcB
= INTERNAL_XDSTOWS(dc
, abc
->abcB
);
2598 abc
->abcC
= INTERNAL_XDSTOWS(dc
, abc
->abcC
);
2603 DC_ReleaseDCPtr( dc
);
2608 /***********************************************************************
2609 * GetGlyphOutlineA (GDI32.@)
2611 DWORD WINAPI
GetGlyphOutlineA( HDC hdc
, UINT uChar
, UINT fuFormat
,
2612 LPGLYPHMETRICS lpgm
, DWORD cbBuffer
,
2613 LPVOID lpBuffer
, const MAT2
*lpmat2
)
2619 if(!(fuFormat
& GGO_GLYPH_INDEX
)) {
2622 if(uChar
> 0xff) { /* but, 2 bytes character only */
2624 mbchs
[0] = (uChar
& 0xff00) >> 8;
2625 mbchs
[1] = (uChar
& 0xff);
2628 mbchs
[0] = (uChar
& 0xff);
2630 p
= FONT_mbtowc(hdc
, mbchs
, len
, NULL
, NULL
);
2634 ret
= GetGlyphOutlineW(hdc
, c
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
,
2636 HeapFree(GetProcessHeap(), 0, p
);
2640 /***********************************************************************
2641 * GetGlyphOutlineW (GDI32.@)
2643 DWORD WINAPI
GetGlyphOutlineW( HDC hdc
, UINT uChar
, UINT fuFormat
,
2644 LPGLYPHMETRICS lpgm
, DWORD cbBuffer
,
2645 LPVOID lpBuffer
, const MAT2
*lpmat2
)
2647 DC
*dc
= DC_GetDCPtr(hdc
);
2650 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2651 hdc
, uChar
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
, lpmat2
);
2653 if(!dc
) return GDI_ERROR
;
2656 ret
= WineEngGetGlyphOutline(dc
->gdiFont
, uChar
, fuFormat
, lpgm
,
2657 cbBuffer
, lpBuffer
, lpmat2
);
2661 DC_ReleaseDCPtr( dc
);
2666 /***********************************************************************
2667 * CreateScalableFontResourceA (GDI32.@)
2669 BOOL WINAPI
CreateScalableFontResourceA( DWORD fHidden
,
2670 LPCSTR lpszResourceFile
,
2671 LPCSTR lpszFontFile
,
2672 LPCSTR lpszCurrentPath
)
2676 /* fHidden=1 - only visible for the calling app, read-only, not
2677 * enumbered with EnumFonts/EnumFontFamilies
2678 * lpszCurrentPath can be NULL
2680 FIXME("(%d,%s,%s,%s): stub\n",
2681 fHidden
, debugstr_a(lpszResourceFile
), debugstr_a(lpszFontFile
),
2682 debugstr_a(lpszCurrentPath
) );
2684 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2685 if ((f
= CreateFileA(lpszResourceFile
, 0, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, 0)) != INVALID_HANDLE_VALUE
) {
2687 SetLastError(ERROR_FILE_EXISTS
);
2690 return FALSE
; /* create failed */
2693 /***********************************************************************
2694 * CreateScalableFontResourceW (GDI32.@)
2696 BOOL WINAPI
CreateScalableFontResourceW( DWORD fHidden
,
2697 LPCWSTR lpszResourceFile
,
2698 LPCWSTR lpszFontFile
,
2699 LPCWSTR lpszCurrentPath
)
2701 FIXME("(%d,%p,%p,%p): stub\n",
2702 fHidden
, lpszResourceFile
, lpszFontFile
, lpszCurrentPath
);
2703 return FALSE
; /* create failed */
2706 /*************************************************************************
2707 * GetKerningPairsA (GDI32.@)
2709 DWORD WINAPI
GetKerningPairsA( HDC hDC
, DWORD cPairs
,
2710 LPKERNINGPAIR kern_pairA
)
2715 DWORD i
, total_kern_pairs
, kern_pairs_copied
= 0;
2716 KERNINGPAIR
*kern_pairW
;
2718 if (!cPairs
&& kern_pairA
)
2720 SetLastError(ERROR_INVALID_PARAMETER
);
2724 charset
= GetTextCharset(hDC
);
2725 if (!TranslateCharsetInfo(ULongToPtr(charset
), &csi
, TCI_SRCCHARSET
))
2727 FIXME("Can't find codepage for charset %d\n", charset
);
2730 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2731 * to fail on an invalid character for CP_SYMBOL.
2733 cpi
.DefaultChar
[0] = 0;
2734 if (csi
.ciACP
!= CP_SYMBOL
&& !GetCPInfo(csi
.ciACP
, &cpi
))
2736 FIXME("Can't find codepage %u info\n", csi
.ciACP
);
2739 TRACE("charset %d => codepage %u\n", charset
, csi
.ciACP
);
2741 total_kern_pairs
= GetKerningPairsW(hDC
, 0, NULL
);
2742 if (!total_kern_pairs
) return 0;
2744 kern_pairW
= HeapAlloc(GetProcessHeap(), 0, total_kern_pairs
* sizeof(*kern_pairW
));
2745 GetKerningPairsW(hDC
, total_kern_pairs
, kern_pairW
);
2747 for (i
= 0; i
< total_kern_pairs
; i
++)
2751 if (!WideCharToMultiByte(csi
.ciACP
, 0, &kern_pairW
[i
].wFirst
, 1, &first
, 1, NULL
, NULL
))
2754 if (!WideCharToMultiByte(csi
.ciACP
, 0, &kern_pairW
[i
].wSecond
, 1, &second
, 1, NULL
, NULL
))
2757 if (first
== cpi
.DefaultChar
[0] || second
== cpi
.DefaultChar
[0])
2762 if (kern_pairs_copied
>= cPairs
) break;
2764 kern_pairA
->wFirst
= (BYTE
)first
;
2765 kern_pairA
->wSecond
= (BYTE
)second
;
2766 kern_pairA
->iKernAmount
= kern_pairW
[i
].iKernAmount
;
2769 kern_pairs_copied
++;
2772 HeapFree(GetProcessHeap(), 0, kern_pairW
);
2774 return kern_pairs_copied
;
2777 /*************************************************************************
2778 * GetKerningPairsW (GDI32.@)
2780 DWORD WINAPI
GetKerningPairsW( HDC hDC
, DWORD cPairs
,
2781 LPKERNINGPAIR lpKerningPairs
)
2786 TRACE("(%p,%d,%p)\n", hDC
, cPairs
, lpKerningPairs
);
2788 if (!cPairs
&& lpKerningPairs
)
2790 SetLastError(ERROR_INVALID_PARAMETER
);
2794 dc
= DC_GetDCPtr(hDC
);
2798 ret
= WineEngGetKerningPairs(dc
->gdiFont
, cPairs
, lpKerningPairs
);
2800 DC_ReleaseDCPtr( dc
);
2804 /*************************************************************************
2805 * TranslateCharsetInfo [GDI32.@]
2807 * Fills a CHARSETINFO structure for a character set, code page, or
2808 * font. This allows making the correspondence between different labels
2809 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2810 * of the same encoding.
2812 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2813 * only one codepage should be set in *lpSrc.
2816 * TRUE on success, FALSE on failure.
2819 BOOL WINAPI
TranslateCharsetInfo(
2820 LPDWORD lpSrc
, /* [in]
2821 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2822 if flags == TCI_SRCCHARSET: a character set value
2823 if flags == TCI_SRCCODEPAGE: a code page value
2825 LPCHARSETINFO lpCs
, /* [out] structure to receive charset information */
2826 DWORD flags
/* [in] determines interpretation of lpSrc */)
2830 case TCI_SRCFONTSIG
:
2831 while (!(*lpSrc
>>index
& 0x0001) && index
<MAXTCIINDEX
) index
++;
2833 case TCI_SRCCODEPAGE
:
2834 while (PtrToUlong(lpSrc
) != FONT_tci
[index
].ciACP
&& index
< MAXTCIINDEX
) index
++;
2836 case TCI_SRCCHARSET
:
2837 while (PtrToUlong(lpSrc
) != FONT_tci
[index
].ciCharset
&& index
< MAXTCIINDEX
) index
++;
2842 if (index
>= MAXTCIINDEX
|| FONT_tci
[index
].ciCharset
== DEFAULT_CHARSET
) return FALSE
;
2843 memcpy(lpCs
, &FONT_tci
[index
], sizeof(CHARSETINFO
));
2847 /*************************************************************************
2848 * GetFontLanguageInfo (GDI32.@)
2850 DWORD WINAPI
GetFontLanguageInfo(HDC hdc
)
2852 FONTSIGNATURE fontsig
;
2853 static const DWORD GCP_DBCS_MASK
=0x003F0000,
2854 GCP_DIACRITIC_MASK
=0x00000000,
2855 FLI_GLYPHS_MASK
=0x00000000,
2856 GCP_GLYPHSHAPE_MASK
=0x00000040,
2857 GCP_KASHIDA_MASK
=0x00000000,
2858 GCP_LIGATE_MASK
=0x00000000,
2859 GCP_USEKERNING_MASK
=0x00000000,
2860 GCP_REORDER_MASK
=0x00000060;
2864 GetTextCharsetInfo( hdc
, &fontsig
, 0 );
2865 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2867 if( (fontsig
.fsCsb
[0]&GCP_DBCS_MASK
)!=0 )
2870 if( (fontsig
.fsCsb
[0]&GCP_DIACRITIC_MASK
)!=0 )
2871 result
|=GCP_DIACRITIC
;
2873 if( (fontsig
.fsCsb
[0]&FLI_GLYPHS_MASK
)!=0 )
2876 if( (fontsig
.fsCsb
[0]&GCP_GLYPHSHAPE_MASK
)!=0 )
2877 result
|=GCP_GLYPHSHAPE
;
2879 if( (fontsig
.fsCsb
[0]&GCP_KASHIDA_MASK
)!=0 )
2880 result
|=GCP_KASHIDA
;
2882 if( (fontsig
.fsCsb
[0]&GCP_LIGATE_MASK
)!=0 )
2885 if( (fontsig
.fsCsb
[0]&GCP_USEKERNING_MASK
)!=0 )
2886 result
|=GCP_USEKERNING
;
2888 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2889 if( GetTextAlign( hdc
) & TA_RTLREADING
)
2890 if( (fontsig
.fsCsb
[0]&GCP_REORDER_MASK
)!=0 )
2891 result
|=GCP_REORDER
;
2897 /*************************************************************************
2898 * GetFontData [GDI32.@]
2900 * Retrieve data for TrueType font.
2904 * success: Number of bytes returned
2905 * failure: GDI_ERROR
2909 * Calls SetLastError()
2912 DWORD WINAPI
GetFontData(HDC hdc
, DWORD table
, DWORD offset
,
2913 LPVOID buffer
, DWORD length
)
2915 DC
*dc
= DC_GetDCPtr(hdc
);
2916 DWORD ret
= GDI_ERROR
;
2918 if(!dc
) return GDI_ERROR
;
2921 ret
= WineEngGetFontData(dc
->gdiFont
, table
, offset
, buffer
, length
);
2923 DC_ReleaseDCPtr( dc
);
2927 /*************************************************************************
2928 * GetGlyphIndicesA [GDI32.@]
2930 DWORD WINAPI
GetGlyphIndicesA(HDC hdc
, LPCSTR lpstr
, INT count
,
2931 LPWORD pgi
, DWORD flags
)
2937 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2938 hdc
, debugstr_an(lpstr
, count
), count
, pgi
, flags
);
2940 lpstrW
= FONT_mbtowc(hdc
, lpstr
, count
, &countW
, NULL
);
2941 ret
= GetGlyphIndicesW(hdc
, lpstrW
, countW
, pgi
, flags
);
2942 HeapFree(GetProcessHeap(), 0, lpstrW
);
2947 /*************************************************************************
2948 * GetGlyphIndicesW [GDI32.@]
2950 DWORD WINAPI
GetGlyphIndicesW(HDC hdc
, LPCWSTR lpstr
, INT count
,
2951 LPWORD pgi
, DWORD flags
)
2953 DC
*dc
= DC_GetDCPtr(hdc
);
2954 DWORD ret
= GDI_ERROR
;
2956 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2957 hdc
, debugstr_wn(lpstr
, count
), count
, pgi
, flags
);
2959 if(!dc
) return GDI_ERROR
;
2962 ret
= WineEngGetGlyphIndices(dc
->gdiFont
, lpstr
, count
, pgi
, flags
);
2964 DC_ReleaseDCPtr( dc
);
2968 /*************************************************************************
2969 * GetCharacterPlacementA [GDI32.@]
2971 * See GetCharacterPlacementW.
2974 * the web browser control of ie4 calls this with dwFlags=0
2977 GetCharacterPlacementA(HDC hdc
, LPCSTR lpString
, INT uCount
,
2978 INT nMaxExtent
, GCP_RESULTSA
*lpResults
,
2983 GCP_RESULTSW resultsW
;
2987 TRACE("%s, %d, %d, 0x%08x\n",
2988 debugstr_an(lpString
, uCount
), uCount
, nMaxExtent
, dwFlags
);
2990 /* both structs are equal in size */
2991 memcpy(&resultsW
, lpResults
, sizeof(resultsW
));
2993 lpStringW
= FONT_mbtowc(hdc
, lpString
, uCount
, &uCountW
, &font_cp
);
2994 if(lpResults
->lpOutString
)
2995 resultsW
.lpOutString
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*uCountW
);
2997 ret
= GetCharacterPlacementW(hdc
, lpStringW
, uCountW
, nMaxExtent
, &resultsW
, dwFlags
);
2999 lpResults
->nGlyphs
= resultsW
.nGlyphs
;
3000 lpResults
->nMaxFit
= resultsW
.nMaxFit
;
3002 if(lpResults
->lpOutString
) {
3003 WideCharToMultiByte(font_cp
, 0, resultsW
.lpOutString
, uCountW
,
3004 lpResults
->lpOutString
, uCount
, NULL
, NULL
);
3007 HeapFree(GetProcessHeap(), 0, lpStringW
);
3008 HeapFree(GetProcessHeap(), 0, resultsW
.lpOutString
);
3013 /*************************************************************************
3014 * GetCharacterPlacementW [GDI32.@]
3016 * Retrieve information about a string. This includes the width, reordering,
3017 * Glyphing and so on.
3021 * The width and height of the string if successful, 0 if failed.
3025 * All flags except GCP_REORDER are not yet implemented.
3026 * Reordering is not 100% complient to the Windows BiDi method.
3027 * Caret positioning is not yet implemented for BiDi.
3028 * Classes are not yet implemented.
3032 GetCharacterPlacementW(
3033 HDC hdc
, /* [in] Device context for which the rendering is to be done */
3034 LPCWSTR lpString
, /* [in] The string for which information is to be returned */
3035 INT uCount
, /* [in] Number of WORDS in string. */
3036 INT nMaxExtent
, /* [in] Maximum extent the string is to take (in HDC logical units) */
3037 GCP_RESULTSW
*lpResults
,/* [in/out] A pointer to a GCP_RESULTSW struct */
3038 DWORD dwFlags
/* [in] Flags specifying how to process the string */
3045 TRACE("%s, %d, %d, 0x%08x\n",
3046 debugstr_wn(lpString
, uCount
), uCount
, nMaxExtent
, dwFlags
);
3048 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
3049 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
3050 lpResults
->lStructSize
, lpResults
->lpOutString
, lpResults
->lpOrder
,
3051 lpResults
->lpDx
, lpResults
->lpCaretPos
, lpResults
->lpClass
,
3052 lpResults
->lpGlyphs
, lpResults
->nGlyphs
, lpResults
->nMaxFit
);
3054 if(dwFlags
&(~GCP_REORDER
)) FIXME("flags 0x%08x ignored\n", dwFlags
);
3055 if(lpResults
->lpClass
) FIXME("classes not implemented\n");
3056 if (lpResults
->lpCaretPos
&& (dwFlags
& GCP_REORDER
))
3057 FIXME("Caret positions for complex scripts not implemented\n");
3059 nSet
= (UINT
)uCount
;
3060 if(nSet
> lpResults
->nGlyphs
)
3061 nSet
= lpResults
->nGlyphs
;
3063 /* return number of initialized fields */
3064 lpResults
->nGlyphs
= nSet
;
3066 if((dwFlags
&GCP_REORDER
)==0 )
3068 /* Treat the case where no special handling was requested in a fastpath way */
3069 /* copy will do if the GCP_REORDER flag is not set */
3070 if(lpResults
->lpOutString
)
3071 memcpy( lpResults
->lpOutString
, lpString
, nSet
* sizeof(WCHAR
));
3073 if(lpResults
->lpOrder
)
3075 for(i
= 0; i
< nSet
; i
++)
3076 lpResults
->lpOrder
[i
] = i
;
3080 BIDI_Reorder( lpString
, uCount
, dwFlags
, WINE_GCPW_FORCE_LTR
, lpResults
->lpOutString
,
3081 nSet
, lpResults
->lpOrder
);
3084 /* FIXME: Will use the placement chars */
3085 if (lpResults
->lpDx
)
3088 for (i
= 0; i
< nSet
; i
++)
3090 if (GetCharWidth32W(hdc
, lpString
[i
], lpString
[i
], &c
))
3091 lpResults
->lpDx
[i
]= c
;
3095 if (lpResults
->lpCaretPos
&& !(dwFlags
& GCP_REORDER
))
3099 lpResults
->lpCaretPos
[0] = 0;
3100 for (i
= 1; i
< nSet
; i
++)
3101 if (GetTextExtentPoint32W(hdc
, &(lpString
[i
- 1]), 1, &size
))
3102 lpResults
->lpCaretPos
[i
] = (pos
+= size
.cx
);
3105 if(lpResults
->lpGlyphs
)
3106 GetGlyphIndicesW(hdc
, lpString
, nSet
, lpResults
->lpGlyphs
, 0);
3108 if (GetTextExtentPoint32W(hdc
, lpString
, uCount
, &size
))
3109 ret
= MAKELONG(size
.cx
, size
.cy
);
3114 /*************************************************************************
3115 * GetCharABCWidthsFloatA [GDI32.@]
3117 * See GetCharABCWidthsFloatW.
3119 BOOL WINAPI
GetCharABCWidthsFloatA( HDC hdc
, UINT first
, UINT last
, LPABCFLOAT abcf
)
3121 INT i
, wlen
, count
= (INT
)(last
- first
+ 1);
3126 if (count
<= 0) return FALSE
;
3128 str
= HeapAlloc(GetProcessHeap(), 0, count
);
3130 for(i
= 0; i
< count
; i
++)
3131 str
[i
] = (BYTE
)(first
+ i
);
3133 wstr
= FONT_mbtowc( hdc
, str
, count
, &wlen
, NULL
);
3135 for (i
= 0; i
< wlen
; i
++)
3137 if (!GetCharABCWidthsFloatW( hdc
, wstr
[i
], wstr
[i
], abcf
))
3145 HeapFree( GetProcessHeap(), 0, str
);
3146 HeapFree( GetProcessHeap(), 0, wstr
);
3151 /*************************************************************************
3152 * GetCharABCWidthsFloatW [GDI32.@]
3154 * Retrieves widths of a range of characters.
3157 * hdc [I] Handle to device context.
3158 * first [I] First character in range to query.
3159 * last [I] Last character in range to query.
3160 * abcf [O] Array of LPABCFLOAT structures.
3167 * Only works with TrueType fonts. It also doesn't return real
3168 * floats but converted integers because it's implemented on
3169 * top of GetCharABCWidthsW.
3171 BOOL WINAPI
GetCharABCWidthsFloatW( HDC hdc
, UINT first
, UINT last
, LPABCFLOAT abcf
)
3174 unsigned int i
, size
= sizeof(ABC
) * (last
- first
+ 1);
3177 TRACE("%p, %d, %d, %p - partial stub\n", hdc
, first
, last
, abcf
);
3179 abc
= HeapAlloc( GetProcessHeap(), 0, size
);
3180 if (!abc
) return FALSE
;
3182 ret
= GetCharABCWidthsW( hdc
, first
, last
, abc
);
3185 for (i
= first
; i
<= last
; i
++, abc
++, abcf
++)
3187 abcf
->abcfA
= abc
->abcA
;
3188 abcf
->abcfB
= abc
->abcB
;
3189 abcf
->abcfC
= abc
->abcC
;
3192 HeapFree( GetProcessHeap(), 0, abc
);
3196 /*************************************************************************
3197 * GetCharWidthFloatA [GDI32.@]
3199 BOOL WINAPI
GetCharWidthFloatA(HDC hdc
, UINT iFirstChar
,
3200 UINT iLastChar
, PFLOAT pxBuffer
)
3202 FIXME("%p, %u, %u, %p: stub!\n", hdc
, iFirstChar
, iLastChar
, pxBuffer
);
3206 /*************************************************************************
3207 * GetCharWidthFloatW [GDI32.@]
3209 BOOL WINAPI
GetCharWidthFloatW(HDC hdc
, UINT iFirstChar
,
3210 UINT iLastChar
, PFLOAT pxBuffer
)
3212 FIXME("%p, %u, %u, %p: stub!\n", hdc
, iFirstChar
, iLastChar
, pxBuffer
);
3217 /***********************************************************************
3219 * Font Resource API *
3221 ***********************************************************************/
3223 /***********************************************************************
3224 * AddFontResourceA (GDI32.@)
3226 INT WINAPI
AddFontResourceA( LPCSTR str
)
3228 return AddFontResourceExA( str
, 0, NULL
);
3231 /***********************************************************************
3232 * AddFontResourceW (GDI32.@)
3234 INT WINAPI
AddFontResourceW( LPCWSTR str
)
3236 return AddFontResourceExW(str
, 0, NULL
);
3240 /***********************************************************************
3241 * AddFontResourceExA (GDI32.@)
3243 INT WINAPI
AddFontResourceExA( LPCSTR str
, DWORD fl
, PVOID pdv
)
3245 DWORD len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
3246 LPWSTR strW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3249 MultiByteToWideChar(CP_ACP
, 0, str
, -1, strW
, len
);
3250 ret
= AddFontResourceExW(strW
, fl
, pdv
);
3251 HeapFree(GetProcessHeap(), 0, strW
);
3255 static BOOL CALLBACK
load_enumed_resource(HMODULE hModule
, LPCWSTR type
, LPWSTR name
, LONG_PTR lParam
)
3257 HRSRC rsrc
= FindResourceW(hModule
, name
, type
);
3258 HGLOBAL hMem
= LoadResource(hModule
, rsrc
);
3259 LPVOID
*pMem
= LockResource(hMem
);
3260 int *num_total
= (int *)lParam
;
3263 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type
));
3264 if (!AddFontMemResourceEx(pMem
, SizeofResource(hModule
, rsrc
), NULL
, &num_in_res
))
3266 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule
, hMem
);
3270 *num_total
+= num_in_res
;
3274 /***********************************************************************
3275 * AddFontResourceExW (GDI32.@)
3277 INT WINAPI
AddFontResourceExW( LPCWSTR str
, DWORD fl
, PVOID pdv
)
3279 int ret
= WineEngAddFontResourceEx(str
, fl
, pdv
);
3282 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3283 HMODULE hModule
= LoadLibraryExW(str
, NULL
, LOAD_LIBRARY_AS_DATAFILE
);
3284 if (hModule
!= NULL
)
3286 int num_resources
= 0;
3287 LPWSTR rt_font
= (LPWSTR
)((ULONG_PTR
)8); /* we don't want to include winuser.h */
3289 TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3290 wine_dbgstr_w(str
));
3291 if (EnumResourceNamesW(hModule
, rt_font
, load_enumed_resource
, (LONG_PTR
)&num_resources
))
3292 ret
= num_resources
;
3293 FreeLibrary(hModule
);
3299 /***********************************************************************
3300 * RemoveFontResourceA (GDI32.@)
3302 BOOL WINAPI
RemoveFontResourceA( LPCSTR str
)
3304 return RemoveFontResourceExA(str
, 0, 0);
3307 /***********************************************************************
3308 * RemoveFontResourceW (GDI32.@)
3310 BOOL WINAPI
RemoveFontResourceW( LPCWSTR str
)
3312 return RemoveFontResourceExW(str
, 0, 0);
3315 /***********************************************************************
3316 * AddFontMemResourceEx (GDI32.@)
3318 HANDLE WINAPI
AddFontMemResourceEx( PVOID pbFont
, DWORD cbFont
, PVOID pdv
, DWORD
*pcFonts
)
3320 return WineEngAddFontMemResourceEx(pbFont
, cbFont
, pdv
, pcFonts
);
3323 /***********************************************************************
3324 * RemoveFontMemResourceEx (GDI32.@)
3326 BOOL WINAPI
RemoveFontMemResourceEx( HANDLE fh
)
3328 FIXME("(%p) stub\n", fh
);
3332 /***********************************************************************
3333 * RemoveFontResourceExA (GDI32.@)
3335 BOOL WINAPI
RemoveFontResourceExA( LPCSTR str
, DWORD fl
, PVOID pdv
)
3337 DWORD len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
3338 LPWSTR strW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3341 MultiByteToWideChar(CP_ACP
, 0, str
, -1, strW
, len
);
3342 ret
= RemoveFontResourceExW(strW
, fl
, pdv
);
3343 HeapFree(GetProcessHeap(), 0, strW
);
3347 /***********************************************************************
3348 * RemoveFontResourceExW (GDI32.@)
3350 BOOL WINAPI
RemoveFontResourceExW( LPCWSTR str
, DWORD fl
, PVOID pdv
)
3352 return WineEngRemoveFontResourceEx(str
, fl
, pdv
);
3355 /***********************************************************************
3356 * GetTextCharset (GDI32.@)
3358 UINT WINAPI
GetTextCharset(HDC hdc
)
3360 /* MSDN docs say this is equivalent */
3361 return GetTextCharsetInfo(hdc
, NULL
, 0);
3364 /***********************************************************************
3365 * GetTextCharsetInfo (GDI32.@)
3367 UINT WINAPI
GetTextCharsetInfo(HDC hdc
, LPFONTSIGNATURE fs
, DWORD flags
)
3369 UINT ret
= DEFAULT_CHARSET
;
3370 DC
*dc
= DC_GetDCPtr(hdc
);
3375 ret
= WineEngGetTextCharsetInfo(dc
->gdiFont
, fs
, flags
);
3377 DC_ReleaseDCPtr( dc
);
3380 if (ret
== DEFAULT_CHARSET
&& fs
)
3381 memset(fs
, 0, sizeof(FONTSIGNATURE
));
3385 /***********************************************************************
3386 * GdiGetCharDimensions (GDI32.@)
3388 * Gets the average width of the characters in the English alphabet.
3391 * hdc [I] Handle to the device context to measure on.
3392 * lptm [O] Pointer to memory to store the text metrics into.
3393 * height [O] On exit, the maximum height of characters in the English alphabet.
3396 * The average width of characters in the English alphabet.
3399 * This function is used by the dialog manager to get the size of a dialog
3400 * unit. It should also be used by other pieces of code that need to know
3401 * the size of a dialog unit in logical units without having access to the
3402 * window handle of the dialog.
3403 * Windows caches the font metrics from this function, but we don't and
3404 * there doesn't appear to be an immediate advantage to do so.
3407 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3409 LONG WINAPI
GdiGetCharDimensions(HDC hdc
, LPTEXTMETRICW lptm
, LONG
*height
)
3412 static const WCHAR alphabet
[] = {
3413 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3414 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3415 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3417 if(lptm
&& !GetTextMetricsW(hdc
, lptm
)) return 0;
3419 if(!GetTextExtentPointW(hdc
, alphabet
, 52, &sz
)) return 0;
3421 if (height
) *height
= sz
.cy
;
3422 return (sz
.cx
/ 26 + 1) / 2;
3425 BOOL WINAPI
EnableEUDC(BOOL fEnableEUDC
)
3427 FIXME("(%d): stub\n", fEnableEUDC
);
3431 /***********************************************************************
3432 * GetCharWidthI (GDI32.@)
3434 * Retrieve widths of characters.
3437 * hdc [I] Handle to a device context.
3438 * first [I] First glyph in range to query.
3439 * count [I] Number of glyph indices to query.
3440 * glyphs [I] Array of glyphs to query.
3441 * buffer [O] Buffer to receive character widths.
3444 * Only works with TrueType fonts.
3450 BOOL WINAPI
GetCharWidthI(HDC hdc
, UINT first
, UINT count
, LPWORD glyphs
, LPINT buffer
)
3455 TRACE("(%p, %d, %d, %p, %p)\n", hdc
, first
, count
, glyphs
, buffer
);
3457 if (!(abc
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(ABC
))))
3460 if (!GetCharABCWidthsI(hdc
, first
, count
, glyphs
, abc
))
3462 HeapFree(GetProcessHeap(), 0, abc
);
3466 for (i
= 0; i
< count
; i
++)
3467 buffer
[i
] = abc
->abcA
+ abc
->abcB
+ abc
->abcC
;
3469 HeapFree(GetProcessHeap(), 0, abc
);
3473 /***********************************************************************
3474 * GetFontUnicodeRanges (GDI32.@)
3476 * Retrieve a list of supported Unicode characters in a font.
3479 * hdc [I] Handle to a device context.
3480 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3483 * Success: Number of bytes written to the buffer pointed to by lpgs.
3487 DWORD WINAPI
GetFontUnicodeRanges(HDC hdc
, LPGLYPHSET lpgs
)
3490 DC
*dc
= DC_GetDCPtr(hdc
);
3492 TRACE("(%p, %p)\n", hdc
, lpgs
);
3496 if (dc
->gdiFont
) ret
= WineEngGetFontUnicodeRanges(dc
->gdiFont
, lpgs
);
3497 DC_ReleaseDCPtr(dc
);
3502 /*************************************************************
3503 * FontIsLinked (GDI32.@)
3505 BOOL WINAPI
FontIsLinked(HDC hdc
)
3507 DC
*dc
= DC_GetDCPtr(hdc
);
3510 if (!dc
) return FALSE
;
3511 if (dc
->gdiFont
) ret
= WineEngFontIsLinked(dc
->gdiFont
);
3512 DC_ReleaseDCPtr(dc
);
3513 TRACE("returning %d\n", ret
);