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 FS(x) {{0,0,0,0},{0x1<<(x),0}}
145 #define MAXTCIINDEX 32
146 static const CHARSETINFO FONT_tci
[MAXTCIINDEX
] = {
148 { ANSI_CHARSET
, 1252, FS(0)},
149 { EASTEUROPE_CHARSET
, 1250, FS(1)},
150 { RUSSIAN_CHARSET
, 1251, FS(2)},
151 { GREEK_CHARSET
, 1253, FS(3)},
152 { TURKISH_CHARSET
, 1254, FS(4)},
153 { HEBREW_CHARSET
, 1255, FS(5)},
154 { ARABIC_CHARSET
, 1256, FS(6)},
155 { BALTIC_CHARSET
, 1257, FS(7)},
156 { VIETNAMESE_CHARSET
, 1258, FS(8)},
157 /* reserved by ANSI */
158 { DEFAULT_CHARSET
, 0, FS(0)},
159 { DEFAULT_CHARSET
, 0, FS(0)},
160 { DEFAULT_CHARSET
, 0, FS(0)},
161 { DEFAULT_CHARSET
, 0, FS(0)},
162 { DEFAULT_CHARSET
, 0, FS(0)},
163 { DEFAULT_CHARSET
, 0, FS(0)},
164 { DEFAULT_CHARSET
, 0, FS(0)},
166 { THAI_CHARSET
, 874, FS(16)},
167 { SHIFTJIS_CHARSET
, 932, FS(17)},
168 { GB2312_CHARSET
, 936, FS(18)},
169 { HANGEUL_CHARSET
, 949, FS(19)},
170 { CHINESEBIG5_CHARSET
, 950, FS(20)},
171 { JOHAB_CHARSET
, 1361, FS(21)},
172 /* reserved for alternate ANSI and OEM */
173 { DEFAULT_CHARSET
, 0, FS(0)},
174 { DEFAULT_CHARSET
, 0, FS(0)},
175 { DEFAULT_CHARSET
, 0, FS(0)},
176 { DEFAULT_CHARSET
, 0, FS(0)},
177 { DEFAULT_CHARSET
, 0, FS(0)},
178 { DEFAULT_CHARSET
, 0, FS(0)},
179 { DEFAULT_CHARSET
, 0, FS(0)},
180 { DEFAULT_CHARSET
, 0, FS(0)},
181 /* reserved for system */
182 { DEFAULT_CHARSET
, 0, FS(0)},
183 { SYMBOL_CHARSET
, CP_SYMBOL
, FS(31)},
186 /***********************************************************************
187 * LOGFONT conversion functions.
189 static void FONT_LogFontWTo16( const LOGFONTW
* font32
, LPLOGFONT16 font16
)
191 font16
->lfHeight
= font32
->lfHeight
;
192 font16
->lfWidth
= font32
->lfWidth
;
193 font16
->lfEscapement
= font32
->lfEscapement
;
194 font16
->lfOrientation
= font32
->lfOrientation
;
195 font16
->lfWeight
= font32
->lfWeight
;
196 font16
->lfItalic
= font32
->lfItalic
;
197 font16
->lfUnderline
= font32
->lfUnderline
;
198 font16
->lfStrikeOut
= font32
->lfStrikeOut
;
199 font16
->lfCharSet
= font32
->lfCharSet
;
200 font16
->lfOutPrecision
= font32
->lfOutPrecision
;
201 font16
->lfClipPrecision
= font32
->lfClipPrecision
;
202 font16
->lfQuality
= font32
->lfQuality
;
203 font16
->lfPitchAndFamily
= font32
->lfPitchAndFamily
;
204 WideCharToMultiByte( CP_ACP
, 0, font32
->lfFaceName
, -1,
205 font16
->lfFaceName
, LF_FACESIZE
, NULL
, NULL
);
206 font16
->lfFaceName
[LF_FACESIZE
-1] = 0;
209 static void FONT_LogFont16ToW( const LOGFONT16
*font16
, LPLOGFONTW font32
)
211 font32
->lfHeight
= font16
->lfHeight
;
212 font32
->lfWidth
= font16
->lfWidth
;
213 font32
->lfEscapement
= font16
->lfEscapement
;
214 font32
->lfOrientation
= font16
->lfOrientation
;
215 font32
->lfWeight
= font16
->lfWeight
;
216 font32
->lfItalic
= font16
->lfItalic
;
217 font32
->lfUnderline
= font16
->lfUnderline
;
218 font32
->lfStrikeOut
= font16
->lfStrikeOut
;
219 font32
->lfCharSet
= font16
->lfCharSet
;
220 font32
->lfOutPrecision
= font16
->lfOutPrecision
;
221 font32
->lfClipPrecision
= font16
->lfClipPrecision
;
222 font32
->lfQuality
= font16
->lfQuality
;
223 font32
->lfPitchAndFamily
= font16
->lfPitchAndFamily
;
224 MultiByteToWideChar( CP_ACP
, 0, font16
->lfFaceName
, -1, font32
->lfFaceName
, LF_FACESIZE
);
225 font32
->lfFaceName
[LF_FACESIZE
-1] = 0;
228 static void FONT_LogFontAToW( const LOGFONTA
*fontA
, LPLOGFONTW fontW
)
230 memcpy(fontW
, fontA
, sizeof(LOGFONTA
) - LF_FACESIZE
);
231 MultiByteToWideChar(CP_ACP
, 0, fontA
->lfFaceName
, -1, fontW
->lfFaceName
,
233 fontW
->lfFaceName
[LF_FACESIZE
-1] = 0;
236 static void FONT_LogFontWToA( const LOGFONTW
*fontW
, LPLOGFONTA fontA
)
238 memcpy(fontA
, fontW
, sizeof(LOGFONTA
) - LF_FACESIZE
);
239 WideCharToMultiByte(CP_ACP
, 0, fontW
->lfFaceName
, -1, fontA
->lfFaceName
,
240 LF_FACESIZE
, NULL
, NULL
);
241 fontA
->lfFaceName
[LF_FACESIZE
-1] = 0;
244 static void FONT_EnumLogFontExWTo16( const ENUMLOGFONTEXW
*fontW
, LPENUMLOGFONTEX16 font16
)
246 FONT_LogFontWTo16( (const LOGFONTW
*)fontW
, (LPLOGFONT16
)font16
);
248 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfFullName
, -1,
249 (LPSTR
) font16
->elfFullName
, LF_FULLFACESIZE
, NULL
, NULL
);
250 font16
->elfFullName
[LF_FULLFACESIZE
-1] = '\0';
251 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfStyle
, -1,
252 (LPSTR
) font16
->elfStyle
, LF_FACESIZE
, NULL
, NULL
);
253 font16
->elfStyle
[LF_FACESIZE
-1] = '\0';
254 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfScript
, -1,
255 (LPSTR
) font16
->elfScript
, LF_FACESIZE
, NULL
, NULL
);
256 font16
->elfScript
[LF_FACESIZE
-1] = '\0';
259 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW
*fontW
, LPENUMLOGFONTEXA fontA
)
261 FONT_LogFontWToA( (const LOGFONTW
*)fontW
, (LPLOGFONTA
)fontA
);
263 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfFullName
, -1,
264 (LPSTR
) fontA
->elfFullName
, LF_FULLFACESIZE
, NULL
, NULL
);
265 fontA
->elfFullName
[LF_FULLFACESIZE
-1] = '\0';
266 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfStyle
, -1,
267 (LPSTR
) fontA
->elfStyle
, LF_FACESIZE
, NULL
, NULL
);
268 fontA
->elfStyle
[LF_FACESIZE
-1] = '\0';
269 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfScript
, -1,
270 (LPSTR
) fontA
->elfScript
, LF_FACESIZE
, NULL
, NULL
);
271 fontA
->elfScript
[LF_FACESIZE
-1] = '\0';
274 /***********************************************************************
275 * TEXTMETRIC conversion functions.
277 static void FONT_TextMetricWToA(const TEXTMETRICW
*ptmW
, LPTEXTMETRICA ptmA
)
279 ptmA
->tmHeight
= ptmW
->tmHeight
;
280 ptmA
->tmAscent
= ptmW
->tmAscent
;
281 ptmA
->tmDescent
= ptmW
->tmDescent
;
282 ptmA
->tmInternalLeading
= ptmW
->tmInternalLeading
;
283 ptmA
->tmExternalLeading
= ptmW
->tmExternalLeading
;
284 ptmA
->tmAveCharWidth
= ptmW
->tmAveCharWidth
;
285 ptmA
->tmMaxCharWidth
= ptmW
->tmMaxCharWidth
;
286 ptmA
->tmWeight
= ptmW
->tmWeight
;
287 ptmA
->tmOverhang
= ptmW
->tmOverhang
;
288 ptmA
->tmDigitizedAspectX
= ptmW
->tmDigitizedAspectX
;
289 ptmA
->tmDigitizedAspectY
= ptmW
->tmDigitizedAspectY
;
290 ptmA
->tmFirstChar
= min(ptmW
->tmFirstChar
, 255);
291 if (ptmW
->tmCharSet
== SYMBOL_CHARSET
)
293 UINT last_char
= ptmW
->tmLastChar
;
294 if (last_char
> 0xf000) last_char
-= 0xf000;
295 ptmA
->tmLastChar
= min(last_char
, 255);
298 ptmA
->tmLastChar
= min(ptmW
->tmLastChar
, 255);
299 ptmA
->tmDefaultChar
= min(ptmW
->tmDefaultChar
, 255);
300 ptmA
->tmBreakChar
= min(ptmW
->tmBreakChar
, 255);
301 ptmA
->tmItalic
= ptmW
->tmItalic
;
302 ptmA
->tmUnderlined
= ptmW
->tmUnderlined
;
303 ptmA
->tmStruckOut
= ptmW
->tmStruckOut
;
304 ptmA
->tmPitchAndFamily
= ptmW
->tmPitchAndFamily
;
305 ptmA
->tmCharSet
= ptmW
->tmCharSet
;
309 static void FONT_NewTextMetricExWTo16(const NEWTEXTMETRICEXW
*ptmW
, LPNEWTEXTMETRICEX16 ptm16
)
311 ptm16
->ntmTm
.tmHeight
= ptmW
->ntmTm
.tmHeight
;
312 ptm16
->ntmTm
.tmAscent
= ptmW
->ntmTm
.tmAscent
;
313 ptm16
->ntmTm
.tmDescent
= ptmW
->ntmTm
.tmDescent
;
314 ptm16
->ntmTm
.tmInternalLeading
= ptmW
->ntmTm
.tmInternalLeading
;
315 ptm16
->ntmTm
.tmExternalLeading
= ptmW
->ntmTm
.tmExternalLeading
;
316 ptm16
->ntmTm
.tmAveCharWidth
= ptmW
->ntmTm
.tmAveCharWidth
;
317 ptm16
->ntmTm
.tmMaxCharWidth
= ptmW
->ntmTm
.tmMaxCharWidth
;
318 ptm16
->ntmTm
.tmWeight
= ptmW
->ntmTm
.tmWeight
;
319 ptm16
->ntmTm
.tmOverhang
= ptmW
->ntmTm
.tmOverhang
;
320 ptm16
->ntmTm
.tmDigitizedAspectX
= ptmW
->ntmTm
.tmDigitizedAspectX
;
321 ptm16
->ntmTm
.tmDigitizedAspectY
= ptmW
->ntmTm
.tmDigitizedAspectY
;
322 ptm16
->ntmTm
.tmFirstChar
= ptmW
->ntmTm
.tmFirstChar
> 255 ? 255 : ptmW
->ntmTm
.tmFirstChar
;
323 ptm16
->ntmTm
.tmLastChar
= ptmW
->ntmTm
.tmLastChar
> 255 ? 255 : ptmW
->ntmTm
.tmLastChar
;
324 ptm16
->ntmTm
.tmDefaultChar
= ptmW
->ntmTm
.tmDefaultChar
> 255 ? 255 : ptmW
->ntmTm
.tmDefaultChar
;
325 ptm16
->ntmTm
.tmBreakChar
= ptmW
->ntmTm
.tmBreakChar
> 255 ? 255 : ptmW
->ntmTm
.tmBreakChar
;
326 ptm16
->ntmTm
.tmItalic
= ptmW
->ntmTm
.tmItalic
;
327 ptm16
->ntmTm
.tmUnderlined
= ptmW
->ntmTm
.tmUnderlined
;
328 ptm16
->ntmTm
.tmStruckOut
= ptmW
->ntmTm
.tmStruckOut
;
329 ptm16
->ntmTm
.tmPitchAndFamily
= ptmW
->ntmTm
.tmPitchAndFamily
;
330 ptm16
->ntmTm
.tmCharSet
= ptmW
->ntmTm
.tmCharSet
;
331 ptm16
->ntmTm
.ntmFlags
= ptmW
->ntmTm
.ntmFlags
;
332 ptm16
->ntmTm
.ntmSizeEM
= ptmW
->ntmTm
.ntmSizeEM
;
333 ptm16
->ntmTm
.ntmCellHeight
= ptmW
->ntmTm
.ntmCellHeight
;
334 ptm16
->ntmTm
.ntmAvgWidth
= ptmW
->ntmTm
.ntmAvgWidth
;
335 memcpy(&ptm16
->ntmFontSig
, &ptmW
->ntmFontSig
, sizeof(FONTSIGNATURE
));
338 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW
*ptmW
, NEWTEXTMETRICEXA
*ptmA
)
340 FONT_TextMetricWToA((const TEXTMETRICW
*)ptmW
, (LPTEXTMETRICA
)ptmA
);
341 ptmA
->ntmTm
.ntmFlags
= ptmW
->ntmTm
.ntmFlags
;
342 ptmA
->ntmTm
.ntmSizeEM
= ptmW
->ntmTm
.ntmSizeEM
;
343 ptmA
->ntmTm
.ntmCellHeight
= ptmW
->ntmTm
.ntmCellHeight
;
344 ptmA
->ntmTm
.ntmAvgWidth
= ptmW
->ntmTm
.ntmAvgWidth
;
345 memcpy(&ptmA
->ntmFontSig
, &ptmW
->ntmFontSig
, sizeof(FONTSIGNATURE
));
349 /***********************************************************************
350 * GdiGetCodePage (GDI32.@)
352 DWORD WINAPI
GdiGetCodePage( HDC hdc
)
356 int charset
= GetTextCharset(hdc
);
358 /* Hmm, nicely designed api this one! */
359 if(TranslateCharsetInfo(ULongToPtr(charset
), &csi
, TCI_SRCCHARSET
))
366 case DEFAULT_CHARSET
:
377 /* FIXME: These have no place here, but because x11drv
378 enumerates fonts with these (made up) charsets some apps
379 might use them and then the FIXME below would become
380 annoying. Now we could pick the intended codepage for
381 each of these, but since it's broken anyway we'll just
382 use CP_ACP and hope it'll go away...
388 FIXME("Can't find codepage for charset %d\n", charset
);
393 TRACE("charset %d => cp %d\n", charset
, cp
);
397 /***********************************************************************
400 * Returns a Unicode translation of str using the charset of the
401 * currently selected font in hdc. If count is -1 then str is assumed
402 * to be '\0' terminated, otherwise it contains the number of bytes to
403 * convert. If plenW is non-NULL, on return it will point to the
404 * number of WCHARs that have been written. If pCP is non-NULL, on
405 * return it will point to the codepage used in the conversion. The
406 * caller should free the returned LPWSTR from the process heap
409 static LPWSTR
FONT_mbtowc(HDC hdc
, LPCSTR str
, INT count
, INT
*plenW
, UINT
*pCP
)
415 cp
= GdiGetCodePage( hdc
);
417 if(count
== -1) count
= strlen(str
);
418 lenW
= MultiByteToWideChar(cp
, 0, str
, count
, NULL
, 0);
419 strW
= HeapAlloc(GetProcessHeap(), 0, lenW
*sizeof(WCHAR
));
420 MultiByteToWideChar(cp
, 0, str
, count
, strW
, lenW
);
421 TRACE("mapped %s -> %s\n", debugstr_an(str
, count
), debugstr_wn(strW
, lenW
));
422 if(plenW
) *plenW
= lenW
;
428 /***********************************************************************
429 * CreateFontIndirectA (GDI32.@)
431 HFONT WINAPI
CreateFontIndirectA( const LOGFONTA
*plfA
)
436 FONT_LogFontAToW( plfA
, &lfW
);
437 return CreateFontIndirectW( &lfW
);
439 return CreateFontIndirectW( NULL
);
443 /***********************************************************************
444 * CreateFontIndirectW (GDI32.@)
446 HFONT WINAPI
CreateFontIndirectW( const LOGFONTW
*plf
)
453 if ((fontPtr
= GDI_AllocObject( sizeof(FONTOBJ
), FONT_MAGIC
,
454 (HGDIOBJ
*)&hFont
, &font_funcs
)))
456 static const WCHAR ItalicW
[] = {' ','I','t','a','l','i','c','\0'};
457 static const WCHAR BoldW
[] = {' ','B','o','l','d','\0'};
458 WCHAR
*pFaceNameItalicSuffix
, *pFaceNameBoldSuffix
;
459 WCHAR
* pFaceNameSuffix
= NULL
;
461 memcpy( &fontPtr
->logfont
, plf
, sizeof(LOGFONTW
) );
463 TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
464 plf
->lfHeight
, plf
->lfWidth
,
465 plf
->lfEscapement
, plf
->lfOrientation
,
466 plf
->lfPitchAndFamily
,
467 plf
->lfOutPrecision
, plf
->lfClipPrecision
,
468 plf
->lfQuality
, plf
->lfCharSet
,
469 debugstr_w(plf
->lfFaceName
),
470 plf
->lfWeight
> 400 ? "Bold" : "",
471 plf
->lfItalic
? "Italic" : "",
472 plf
->lfUnderline
? "Underline" : "", hFont
);
474 if (plf
->lfEscapement
!= plf
->lfOrientation
) {
475 /* this should really depend on whether GM_ADVANCED is set */
476 fontPtr
->logfont
.lfOrientation
= fontPtr
->logfont
.lfEscapement
;
477 WARN("orientation angle %f set to "
478 "escapement angle %f for new font %p\n",
479 plf
->lfOrientation
/10., plf
->lfEscapement
/10., hFont
);
482 pFaceNameItalicSuffix
= strstrW(fontPtr
->logfont
.lfFaceName
, ItalicW
);
483 if (pFaceNameItalicSuffix
) {
484 fontPtr
->logfont
.lfItalic
= TRUE
;
485 pFaceNameSuffix
= pFaceNameItalicSuffix
;
488 pFaceNameBoldSuffix
= strstrW(fontPtr
->logfont
.lfFaceName
, BoldW
);
489 if (pFaceNameBoldSuffix
) {
490 if (fontPtr
->logfont
.lfWeight
< FW_BOLD
) {
491 fontPtr
->logfont
.lfWeight
= FW_BOLD
;
493 if (!pFaceNameSuffix
||
494 (pFaceNameBoldSuffix
< pFaceNameSuffix
)) {
495 pFaceNameSuffix
= pFaceNameBoldSuffix
;
499 if (pFaceNameSuffix
) *pFaceNameSuffix
= 0;
501 GDI_ReleaseObj( hFont
);
504 else WARN("(NULL) => NULL\n");
509 /*************************************************************************
510 * CreateFontA (GDI32.@)
512 HFONT WINAPI
CreateFontA( INT height
, INT width
, INT esc
,
513 INT orient
, INT weight
, DWORD italic
,
514 DWORD underline
, DWORD strikeout
, DWORD charset
,
515 DWORD outpres
, DWORD clippres
, DWORD quality
,
516 DWORD pitch
, LPCSTR name
)
520 logfont
.lfHeight
= height
;
521 logfont
.lfWidth
= width
;
522 logfont
.lfEscapement
= esc
;
523 logfont
.lfOrientation
= orient
;
524 logfont
.lfWeight
= weight
;
525 logfont
.lfItalic
= italic
;
526 logfont
.lfUnderline
= underline
;
527 logfont
.lfStrikeOut
= strikeout
;
528 logfont
.lfCharSet
= charset
;
529 logfont
.lfOutPrecision
= outpres
;
530 logfont
.lfClipPrecision
= clippres
;
531 logfont
.lfQuality
= quality
;
532 logfont
.lfPitchAndFamily
= pitch
;
535 lstrcpynA(logfont
.lfFaceName
,name
,sizeof(logfont
.lfFaceName
));
537 logfont
.lfFaceName
[0] = '\0';
539 return CreateFontIndirectA( &logfont
);
542 /*************************************************************************
543 * CreateFontW (GDI32.@)
545 HFONT WINAPI
CreateFontW( INT height
, INT width
, INT esc
,
546 INT orient
, INT weight
, DWORD italic
,
547 DWORD underline
, DWORD strikeout
, DWORD charset
,
548 DWORD outpres
, DWORD clippres
, DWORD quality
,
549 DWORD pitch
, LPCWSTR name
)
553 logfont
.lfHeight
= height
;
554 logfont
.lfWidth
= width
;
555 logfont
.lfEscapement
= esc
;
556 logfont
.lfOrientation
= orient
;
557 logfont
.lfWeight
= weight
;
558 logfont
.lfItalic
= italic
;
559 logfont
.lfUnderline
= underline
;
560 logfont
.lfStrikeOut
= strikeout
;
561 logfont
.lfCharSet
= charset
;
562 logfont
.lfOutPrecision
= outpres
;
563 logfont
.lfClipPrecision
= clippres
;
564 logfont
.lfQuality
= quality
;
565 logfont
.lfPitchAndFamily
= pitch
;
568 lstrcpynW(logfont
.lfFaceName
, name
,
569 sizeof(logfont
.lfFaceName
) / sizeof(WCHAR
));
571 logfont
.lfFaceName
[0] = '\0';
573 return CreateFontIndirectW( &logfont
);
577 /***********************************************************************
580 * If the driver supports vector fonts we create a gdi font first and
581 * then call the driver to give it a chance to supply its own device
582 * font. If the driver wants to do this it returns TRUE and we can
583 * delete the gdi font, if the driver wants to use the gdi font it
584 * should return FALSE, to signal an error return GDI_ERROR. For
585 * drivers that don't support vector fonts they must supply their own
588 static HGDIOBJ
FONT_SelectObject( HGDIOBJ handle
, HDC hdc
)
591 DC
*dc
= get_dc_ptr( hdc
);
595 if (!GDI_inc_ref_count( handle
))
597 release_dc_ptr( dc
);
601 if (dc
->hFont
!= handle
|| dc
->gdiFont
== NULL
)
603 if(GetDeviceCaps(dc
->hSelf
, TEXTCAPS
) & TC_VA_ABLE
)
605 FONTOBJ
*font
= GDI_GetObjPtr( handle
, FONT_MAGIC
); /* to grab the GDI lock (FIXME) */
606 dc
->gdiFont
= WineEngCreateFontInstance(dc
, handle
);
607 if (font
) GDI_ReleaseObj( handle
);
611 if (dc
->funcs
->pSelectFont
) ret
= dc
->funcs
->pSelectFont( dc
->physDev
, handle
, dc
->gdiFont
);
613 if (ret
&& dc
->gdiFont
) dc
->gdiFont
= 0;
615 if (ret
== HGDI_ERROR
)
617 GDI_dec_ref_count( handle
);
618 ret
= 0; /* SelectObject returns 0 on error */
624 GDI_dec_ref_count( ret
);
626 release_dc_ptr( dc
);
631 /***********************************************************************
634 static INT
FONT_GetObject16( HGDIOBJ handle
, void *obj
, INT count
, LPVOID buffer
)
639 FONT_LogFontWTo16( &font
->logfont
, &lf16
);
641 if (count
> sizeof(LOGFONT16
)) count
= sizeof(LOGFONT16
);
642 memcpy( buffer
, &lf16
, count
);
646 /***********************************************************************
649 static INT
FONT_GetObjectA( HGDIOBJ handle
, void *obj
, INT count
, LPVOID buffer
)
656 FONT_LogFontWToA( &font
->logfont
, &lfA
);
658 if (count
> sizeof(lfA
)) count
= sizeof(lfA
);
659 memcpy( buffer
, &lfA
, count
);
663 /***********************************************************************
666 static INT
FONT_GetObjectW( HGDIOBJ handle
, void *obj
, INT count
, LPVOID buffer
)
670 return sizeof(LOGFONTW
);
671 if (count
> sizeof(LOGFONTW
)) count
= sizeof(LOGFONTW
);
672 memcpy( buffer
, &font
->logfont
, count
);
677 /***********************************************************************
680 static BOOL
FONT_DeleteObject( HGDIOBJ handle
, void *obj
)
682 WineEngDestroyFontInstance( handle
);
683 return GDI_FreeObject( handle
, obj
);
687 /***********************************************************************
688 * FONT_EnumInstance16
690 * Called by the device driver layer to pass font info
691 * down to the application.
693 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
694 * We have to use other types because of the FONTENUMPROCW definition.
696 static INT CALLBACK
FONT_EnumInstance16( const LOGFONTW
*plf
, const TEXTMETRICW
*ptm
,
697 DWORD fType
, LPARAM lp
)
699 fontEnum16
*pfe
= (fontEnum16
*)lp
;
703 if( pfe
->lpLogFontParam
->lfCharSet
== DEFAULT_CHARSET
||
704 pfe
->lpLogFontParam
->lfCharSet
== plf
->lfCharSet
)
709 FONT_EnumLogFontExWTo16((const ENUMLOGFONTEXW
*)plf
, pfe
->lpLogFont
);
710 FONT_NewTextMetricExWTo16((const NEWTEXTMETRICEXW
*)ptm
, pfe
->lpTextMetric
);
711 pfe
->dwFlags
|= ENUM_CALLED
;
712 DC_ReleaseDCPtr( pfe
->dc
); /* release the GDI lock */
714 args
[6] = SELECTOROF(pfe
->segLogFont
);
715 args
[5] = OFFSETOF(pfe
->segLogFont
);
716 args
[4] = SELECTOROF(pfe
->segTextMetric
);
717 args
[3] = OFFSETOF(pfe
->segTextMetric
);
719 args
[1] = HIWORD(pfe
->lpData
);
720 args
[0] = LOWORD(pfe
->lpData
);
721 WOWCallback16Ex( (DWORD
)pfe
->lpEnumFunc
, WCB16_PASCAL
, sizeof(args
), args
, &result
);
722 ret
= LOWORD(result
);
724 /* get the lock again and make sure the DC is still valid */
725 dc
= DC_GetDCPtr( pfe
->hdc
);
726 if (!dc
|| dc
!= pfe
->dc
|| dc
->physDev
!= pfe
->physDev
)
728 if (dc
) DC_ReleaseDCPtr( dc
);
729 pfe
->hdc
= 0; /* make sure we don't try to release it later on */
737 /***********************************************************************
740 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
741 * We have to use other types because of the FONTENUMPROCW definition.
743 static INT CALLBACK
FONT_EnumInstance( const LOGFONTW
*plf
, const TEXTMETRICW
*ptm
,
744 DWORD fType
, LPARAM lp
)
746 fontEnum32
*pfe
= (fontEnum32
*)lp
;
750 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
751 if((pfe
->lpLogFontParam
->lfCharSet
== DEFAULT_CHARSET
||
752 pfe
->lpLogFontParam
->lfCharSet
== plf
->lfCharSet
) &&
753 (!(fType
& RASTER_FONTTYPE
) || GetDeviceCaps(pfe
->hdc
, TEXTCAPS
) & TC_RA_ABLE
) )
755 /* convert font metrics */
756 ENUMLOGFONTEXA logfont
;
757 NEWTEXTMETRICEXA tmA
;
759 pfe
->dwFlags
|= ENUM_CALLED
;
760 if (!(pfe
->dwFlags
& ENUM_UNICODE
))
762 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW
*)plf
, &logfont
);
763 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW
*)ptm
, &tmA
);
764 plf
= (LOGFONTW
*)&logfont
.elfLogFont
;
765 ptm
= (TEXTMETRICW
*)&tmA
;
767 DC_ReleaseDCPtr( pfe
->dc
); /* release the GDI lock */
769 ret
= pfe
->lpEnumFunc( plf
, ptm
, fType
, pfe
->lpData
);
771 /* get the lock again and make sure the DC is still valid */
772 dc
= DC_GetDCPtr( pfe
->hdc
);
773 if (!dc
|| dc
!= pfe
->dc
|| dc
->physDev
!= pfe
->physDev
)
775 if (dc
) DC_ReleaseDCPtr( dc
);
776 pfe
->hdc
= 0; /* make sure we don't try to release it later on */
784 /***********************************************************************
785 * EnumFontFamiliesEx (GDI.613)
787 INT16 WINAPI
EnumFontFamiliesEx16( HDC16 hDC
, LPLOGFONT16 plf
,
788 FONTENUMPROC16 efproc
, LPARAM lParam
,
793 DC
* dc
= DC_GetDCPtr( HDC_32(hDC
) );
794 NEWTEXTMETRICEX16 tm16
;
795 ENUMLOGFONTEX16 lf16
;
800 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( &lfW
, FONT_EnumInstance16
, (LPARAM
)&fe16
);
824 fe16
.dwFlags
&= ~ENUM_CALLED
;
825 if (ret
&& dc
->funcs
->pEnumDeviceFonts
) {
826 ret2
= dc
->funcs
->pEnumDeviceFonts( dc
->physDev
, &lfW
, 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
);
851 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf
->lfFaceName
),
853 fe32
.lpLogFontParam
= plf
;
854 fe32
.lpEnumFunc
= efproc
;
855 fe32
.lpData
= lParam
;
856 fe32
.dwFlags
= dwUnicode
;
859 fe32
.physDev
= dc
->physDev
;
861 enum_gdi_fonts
= GetDeviceCaps(hDC
, TEXTCAPS
) & TC_VA_ABLE
;
863 if (!dc
->funcs
->pEnumDeviceFonts
&& !enum_gdi_fonts
)
870 ret
= WineEngEnumFonts( plf
, FONT_EnumInstance
, (LPARAM
)&fe32
);
871 fe32
.dwFlags
&= ~ENUM_CALLED
;
872 if (ret
&& dc
->funcs
->pEnumDeviceFonts
) {
873 ret2
= dc
->funcs
->pEnumDeviceFonts( dc
->physDev
, plf
, FONT_EnumInstance
, (LPARAM
)&fe32
);
874 if(fe32
.dwFlags
& ENUM_CALLED
) /* update ret iff a font gets enumed */
878 if (fe32
.dc
) DC_ReleaseDCPtr( fe32
.dc
);
882 /***********************************************************************
883 * EnumFontFamiliesExW (GDI32.@)
885 INT WINAPI
EnumFontFamiliesExW( HDC hDC
, LPLOGFONTW plf
,
886 FONTENUMPROCW efproc
,
887 LPARAM lParam
, DWORD dwFlags
)
889 return FONT_EnumFontFamiliesEx( hDC
, plf
, efproc
, lParam
, ENUM_UNICODE
);
892 /***********************************************************************
893 * EnumFontFamiliesExA (GDI32.@)
895 INT WINAPI
EnumFontFamiliesExA( HDC hDC
, LPLOGFONTA plf
,
896 FONTENUMPROCA efproc
,
897 LPARAM lParam
, DWORD dwFlags
)
900 FONT_LogFontAToW( plf
, &lfW
);
902 return FONT_EnumFontFamiliesEx( hDC
, &lfW
, (FONTENUMPROCW
)efproc
, lParam
, 0);
905 /***********************************************************************
906 * EnumFontFamilies (GDI.330)
908 INT16 WINAPI
EnumFontFamilies16( HDC16 hDC
, LPCSTR lpFamily
,
909 FONTENUMPROC16 efproc
, LPARAM lpData
)
913 lf
.lfCharSet
= DEFAULT_CHARSET
;
916 if (!*lpFamily
) return 1;
917 lstrcpynA( lf
.lfFaceName
, lpFamily
, LF_FACESIZE
);
919 else lf
.lfFaceName
[0] = '\0';
921 return EnumFontFamiliesEx16( hDC
, &lf
, efproc
, lpData
, 0 );
924 /***********************************************************************
925 * EnumFontFamiliesA (GDI32.@)
927 INT WINAPI
EnumFontFamiliesA( HDC hDC
, LPCSTR lpFamily
,
928 FONTENUMPROCA efproc
, LPARAM lpData
)
932 lf
.lfCharSet
= DEFAULT_CHARSET
;
935 if (!*lpFamily
) return 1;
936 lstrcpynA( lf
.lfFaceName
, lpFamily
, LF_FACESIZE
);
938 else lf
.lfFaceName
[0] = lf
.lfFaceName
[1] = '\0';
940 return EnumFontFamiliesExA( hDC
, &lf
, efproc
, lpData
, 0 );
943 /***********************************************************************
944 * EnumFontFamiliesW (GDI32.@)
946 INT WINAPI
EnumFontFamiliesW( HDC hDC
, LPCWSTR lpFamily
,
947 FONTENUMPROCW efproc
, LPARAM lpData
)
951 lf
.lfCharSet
= DEFAULT_CHARSET
;
954 if (!*lpFamily
) return 1;
955 lstrcpynW( lf
.lfFaceName
, lpFamily
, LF_FACESIZE
);
957 else lf
.lfFaceName
[0] = 0;
959 return EnumFontFamiliesExW( hDC
, &lf
, efproc
, lpData
, 0 );
962 /***********************************************************************
965 INT16 WINAPI
EnumFonts16( HDC16 hDC
, LPCSTR lpName
, FONTENUMPROC16 efproc
,
968 return EnumFontFamilies16( hDC
, lpName
, efproc
, lpData
);
971 /***********************************************************************
972 * EnumFontsA (GDI32.@)
974 INT WINAPI
EnumFontsA( HDC hDC
, LPCSTR lpName
, FONTENUMPROCA efproc
,
977 return EnumFontFamiliesA( hDC
, lpName
, efproc
, lpData
);
980 /***********************************************************************
981 * EnumFontsW (GDI32.@)
983 INT WINAPI
EnumFontsW( HDC hDC
, LPCWSTR lpName
, FONTENUMPROCW efproc
,
986 return EnumFontFamiliesW( hDC
, lpName
, efproc
, lpData
);
990 /***********************************************************************
991 * GetTextCharacterExtra (GDI32.@)
993 INT WINAPI
GetTextCharacterExtra( HDC hdc
)
996 DC
*dc
= DC_GetDCPtr( hdc
);
997 if (!dc
) return 0x80000000;
999 DC_ReleaseDCPtr( dc
);
1004 /***********************************************************************
1005 * SetTextCharacterExtra (GDI32.@)
1007 INT WINAPI
SetTextCharacterExtra( HDC hdc
, INT extra
)
1010 DC
* dc
= DC_GetDCPtr( hdc
);
1011 if (!dc
) return 0x80000000;
1012 if (dc
->funcs
->pSetTextCharacterExtra
)
1013 prev
= dc
->funcs
->pSetTextCharacterExtra( dc
->physDev
, extra
);
1016 prev
= dc
->charExtra
;
1017 dc
->charExtra
= extra
;
1019 DC_ReleaseDCPtr( dc
);
1024 /***********************************************************************
1025 * SetTextJustification (GDI32.@)
1027 BOOL WINAPI
SetTextJustification( HDC hdc
, INT extra
, INT breaks
)
1030 DC
* dc
= DC_GetDCPtr( hdc
);
1031 if (!dc
) return FALSE
;
1032 if (dc
->funcs
->pSetTextJustification
)
1033 ret
= dc
->funcs
->pSetTextJustification( dc
->physDev
, extra
, breaks
);
1036 extra
= abs((extra
* dc
->vportExtX
+ dc
->wndExtX
/ 2) / dc
->wndExtX
);
1037 if (!extra
) breaks
= 0;
1040 dc
->breakExtra
= extra
/ breaks
;
1041 dc
->breakRem
= extra
- (breaks
* dc
->breakExtra
);
1049 DC_ReleaseDCPtr( dc
);
1054 /***********************************************************************
1055 * GetTextFaceA (GDI32.@)
1057 INT WINAPI
GetTextFaceA( HDC hdc
, INT count
, LPSTR name
)
1059 INT res
= GetTextFaceW(hdc
, 0, NULL
);
1060 LPWSTR nameW
= HeapAlloc( GetProcessHeap(), 0, res
* 2 );
1061 GetTextFaceW( hdc
, res
, nameW
);
1065 if (count
&& !WideCharToMultiByte( CP_ACP
, 0, nameW
, -1, name
, count
, NULL
, NULL
))
1070 res
= WideCharToMultiByte( CP_ACP
, 0, nameW
, -1, NULL
, 0, NULL
, NULL
);
1071 HeapFree( GetProcessHeap(), 0, nameW
);
1075 /***********************************************************************
1076 * GetTextFaceW (GDI32.@)
1078 INT WINAPI
GetTextFaceW( HDC hdc
, INT count
, LPWSTR name
)
1083 DC
* dc
= DC_GetDCPtr( hdc
);
1087 ret
= WineEngGetTextFace(dc
->gdiFont
, count
, name
);
1088 else if ((font
= (FONTOBJ
*) GDI_GetObjPtr( dc
->hFont
, FONT_MAGIC
)))
1092 lstrcpynW( name
, font
->logfont
.lfFaceName
, count
);
1093 ret
= strlenW(name
);
1095 else ret
= strlenW(font
->logfont
.lfFaceName
) + 1;
1096 GDI_ReleaseObj( dc
->hFont
);
1098 DC_ReleaseDCPtr( dc
);
1103 /***********************************************************************
1104 * GetTextExtentPoint32A (GDI32.@)
1106 * See GetTextExtentPoint32W.
1108 BOOL WINAPI
GetTextExtentPoint32A( HDC hdc
, LPCSTR str
, INT count
,
1113 LPWSTR p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
1116 ret
= GetTextExtentPoint32W( hdc
, p
, wlen
, size
);
1117 HeapFree( GetProcessHeap(), 0, p
);
1120 TRACE("(%p %s %d %p): returning %d x %d\n",
1121 hdc
, debugstr_an (str
, count
), count
, size
, size
->cx
, size
->cy
);
1126 /***********************************************************************
1127 * GetTextExtentPoint32W [GDI32.@]
1129 * Computes width/height for a string.
1131 * Computes width and height of the specified string.
1137 BOOL WINAPI
GetTextExtentPoint32W(
1138 HDC hdc
, /* [in] Handle of device context */
1139 LPCWSTR str
, /* [in] Address of text string */
1140 INT count
, /* [in] Number of characters in string */
1141 LPSIZE size
) /* [out] Address of structure for string size */
1143 return GetTextExtentExPointW(hdc
, str
, count
, 0, NULL
, NULL
, size
);
1146 /***********************************************************************
1147 * GetTextExtentPointI [GDI32.@]
1149 * Computes width and height of the array of glyph indices.
1155 BOOL WINAPI
GetTextExtentPointI(
1156 HDC hdc
, /* [in] Handle of device context */
1157 const WORD
*indices
, /* [in] Address of glyph index array */
1158 INT count
, /* [in] Number of glyphs in array */
1159 LPSIZE size
) /* [out] Address of structure for string size */
1162 DC
* dc
= DC_GetDCPtr( hdc
);
1163 if (!dc
) return FALSE
;
1166 ret
= WineEngGetTextExtentPointI(dc
->gdiFont
, indices
, count
, size
);
1167 size
->cx
= abs(INTERNAL_XDSTOWS(dc
, size
->cx
));
1168 size
->cy
= abs(INTERNAL_YDSTOWS(dc
, size
->cy
));
1169 size
->cx
+= count
* dc
->charExtra
;
1171 else if(dc
->funcs
->pGetTextExtentExPoint
) {
1172 FIXME("calling GetTextExtentExPoint\n");
1173 ret
= dc
->funcs
->pGetTextExtentExPoint( dc
->physDev
, (LPCWSTR
)indices
,
1174 count
, 0, NULL
, NULL
, size
);
1177 DC_ReleaseDCPtr( dc
);
1179 TRACE("(%p %p %d %p): returning %d x %d\n",
1180 hdc
, indices
, count
, size
, size
->cx
, size
->cy
);
1185 /***********************************************************************
1186 * GetTextExtentPointA (GDI32.@)
1188 BOOL WINAPI
GetTextExtentPointA( HDC hdc
, LPCSTR str
, INT count
,
1191 TRACE("not bug compatible.\n");
1192 return GetTextExtentPoint32A( hdc
, str
, count
, size
);
1195 /***********************************************************************
1196 * GetTextExtentPointW (GDI32.@)
1198 BOOL WINAPI
GetTextExtentPointW( HDC hdc
, LPCWSTR str
, INT count
,
1201 TRACE("not bug compatible.\n");
1202 return GetTextExtentPoint32W( hdc
, str
, count
, size
);
1206 /***********************************************************************
1207 * GetTextExtentExPointA (GDI32.@)
1209 BOOL WINAPI
GetTextExtentExPointA( HDC hdc
, LPCSTR str
, INT count
,
1210 INT maxExt
, LPINT lpnFit
,
1211 LPINT alpDx
, LPSIZE size
)
1219 NULL
== (walpDx
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(INT
))))
1222 p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
1223 ret
= GetTextExtentExPointW( hdc
, p
, wlen
, maxExt
, lpnFit
, walpDx
, size
);
1226 INT n
= lpnFit
? *lpnFit
: wlen
;
1228 for(i
= 0, j
= 0; i
< n
; i
++, j
++)
1230 alpDx
[j
] = walpDx
[i
];
1231 if (IsDBCSLeadByte(str
[j
])) alpDx
[++j
] = walpDx
[i
];
1234 if (lpnFit
) *lpnFit
= WideCharToMultiByte(CP_ACP
,0,p
,*lpnFit
,NULL
,0,NULL
,NULL
);
1235 HeapFree( GetProcessHeap(), 0, p
);
1236 HeapFree( GetProcessHeap(), 0, walpDx
);
1241 /***********************************************************************
1242 * GetTextExtentExPointW (GDI32.@)
1244 * Return the size of the string as it would be if it was output properly by
1247 * This should include
1248 * - Intercharacter spacing
1249 * - justification spacing (not yet done)
1250 * - kerning? see below
1252 * Kerning. Since kerning would be carried out by the rendering code it should
1253 * be done by the driver. However they don't support it yet. Also I am not
1254 * yet persuaded that (certainly under Win95) any kerning is actually done.
1256 * str: According to MSDN this should be null-terminated. That is not true; a
1257 * null will not terminate it early.
1258 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1259 * than count. I have seen it be either the size of the full string or
1260 * 1 less than the size of the full string. I have not seen it bear any
1261 * resemblance to the portion that would fit.
1262 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1263 * trailing intercharacter spacing and any trailing justification.
1266 * Currently we do this by measuring each character etc. We should do it by
1267 * passing the request to the driver, perhaps by extending the
1268 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1269 * thinking about kerning issues and rounding issues in the justification.
1272 BOOL WINAPI
GetTextExtentExPointW( HDC hdc
, LPCWSTR str
, INT count
,
1273 INT maxExt
, LPINT lpnFit
,
1274 LPINT alpDx
, LPSIZE size
)
1282 TRACE("(%p, %s, %d)\n",hdc
,debugstr_wn(str
,count
),maxExt
);
1284 dc
= DC_GetDCPtr(hdc
);
1288 GetTextMetricsW(hdc
, &tm
);
1290 /* If we need to calculate nFit, then we need the partial extents even if
1291 the user hasn't provided us with an array. */
1294 dxs
= alpDx
? alpDx
: HeapAlloc(GetProcessHeap(), 0, count
* sizeof alpDx
[0]);
1297 DC_ReleaseDCPtr(dc
);
1298 SetLastError(ERROR_OUTOFMEMORY
);
1306 ret
= WineEngGetTextExtentExPoint(dc
->gdiFont
, str
, count
,
1307 0, NULL
, dxs
, size
);
1308 else if (dc
->funcs
->pGetTextExtentExPoint
)
1309 ret
= dc
->funcs
->pGetTextExtentExPoint(dc
->physDev
, str
, count
,
1310 0, NULL
, dxs
, size
);
1312 /* Perform device size to world size transformations. */
1315 INT extra
= dc
->charExtra
,
1316 breakExtra
= dc
->breakExtra
,
1317 breakRem
= dc
->breakRem
,
1322 for (i
= 0; i
< count
; ++i
)
1324 dxs
[i
] = abs(INTERNAL_XDSTOWS(dc
, dxs
[i
]));
1325 dxs
[i
] += (i
+1) * extra
;
1326 if (count
> 1 && (breakExtra
|| breakRem
) && str
[i
] == tm
.tmBreakChar
)
1328 dxs
[i
] += breakExtra
;
1335 if (dxs
[i
] <= maxExt
)
1338 breakRem
= dc
->breakRem
;
1340 size
->cx
= abs(INTERNAL_XDSTOWS(dc
, size
->cx
));
1341 size
->cy
= abs(INTERNAL_YDSTOWS(dc
, size
->cy
));
1343 if (!dxs
&& count
> 1 && (breakExtra
|| breakRem
))
1345 for (i
= 0; i
< count
; i
++)
1347 if (str
[i
] == tm
.tmBreakChar
)
1349 size
->cx
+= breakExtra
;
1364 HeapFree(GetProcessHeap(), 0, dxs
);
1366 DC_ReleaseDCPtr( dc
);
1368 TRACE("returning %d %d x %d\n",nFit
,size
->cx
,size
->cy
);
1372 /***********************************************************************
1373 * GetTextMetricsA (GDI32.@)
1375 BOOL WINAPI
GetTextMetricsA( HDC hdc
, TEXTMETRICA
*metrics
)
1379 if (!GetTextMetricsW( hdc
, &tm32
)) return FALSE
;
1380 FONT_TextMetricWToA( &tm32
, metrics
);
1384 /***********************************************************************
1385 * GetTextMetricsW (GDI32.@)
1387 BOOL WINAPI
GetTextMetricsW( HDC hdc
, TEXTMETRICW
*metrics
)
1390 DC
* dc
= DC_GetDCPtr( hdc
);
1391 if (!dc
) return FALSE
;
1394 ret
= WineEngGetTextMetrics(dc
->gdiFont
, metrics
);
1395 else if (dc
->funcs
->pGetTextMetrics
)
1396 ret
= dc
->funcs
->pGetTextMetrics( dc
->physDev
, metrics
);
1400 /* device layer returns values in device units
1401 * therefore we have to convert them to logical */
1403 metrics
->tmDigitizedAspectX
= GetDeviceCaps(hdc
, LOGPIXELSX
);
1404 metrics
->tmDigitizedAspectY
= GetDeviceCaps(hdc
, LOGPIXELSY
);
1406 #define WDPTOLP(x) ((x<0)? \
1407 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1408 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1409 #define HDPTOLP(y) ((y<0)? \
1410 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1411 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1413 metrics
->tmHeight
= HDPTOLP(metrics
->tmHeight
);
1414 metrics
->tmAscent
= HDPTOLP(metrics
->tmAscent
);
1415 metrics
->tmDescent
= HDPTOLP(metrics
->tmDescent
);
1416 metrics
->tmInternalLeading
= HDPTOLP(metrics
->tmInternalLeading
);
1417 metrics
->tmExternalLeading
= HDPTOLP(metrics
->tmExternalLeading
);
1418 metrics
->tmAveCharWidth
= WDPTOLP(metrics
->tmAveCharWidth
);
1419 metrics
->tmMaxCharWidth
= WDPTOLP(metrics
->tmMaxCharWidth
);
1420 metrics
->tmOverhang
= WDPTOLP(metrics
->tmOverhang
);
1424 TRACE("text metrics:\n"
1425 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1426 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1427 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1428 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1429 " PitchAndFamily = %02x\n"
1430 " --------------------\n"
1431 " InternalLeading = %i\n"
1435 metrics
->tmWeight
, metrics
->tmFirstChar
, metrics
->tmAveCharWidth
,
1436 metrics
->tmItalic
, metrics
->tmLastChar
, metrics
->tmMaxCharWidth
,
1437 metrics
->tmUnderlined
, metrics
->tmDefaultChar
, metrics
->tmOverhang
,
1438 metrics
->tmStruckOut
, metrics
->tmBreakChar
, metrics
->tmCharSet
,
1439 metrics
->tmPitchAndFamily
,
1440 metrics
->tmInternalLeading
,
1443 metrics
->tmHeight
);
1445 DC_ReleaseDCPtr( dc
);
1450 /***********************************************************************
1451 * GetOutlineTextMetrics [GDI.308] Gets metrics for TrueType fonts.
1454 * lpOTM should be LPOUTLINETEXTMETRIC
1457 * Success: Non-zero or size of required buffer
1460 UINT16 WINAPI
GetOutlineTextMetrics16(
1461 HDC16 hdc
, /* [in] Handle of device context */
1462 UINT16 cbData
, /* [in] Size of metric data array */
1463 LPOUTLINETEXTMETRIC16 lpOTM
) /* [out] Address of metric data array */
1465 FIXME("(%04x,%04x,%p): stub\n", hdc
,cbData
,lpOTM
);
1470 /***********************************************************************
1471 * GetOutlineTextMetricsA (GDI32.@)
1472 * Gets metrics for TrueType fonts.
1475 * If the supplied buffer isn't big enough Windows partially fills it up to
1476 * its given length and returns that length.
1479 * Success: Non-zero or size of required buffer
1482 UINT WINAPI
GetOutlineTextMetricsA(
1483 HDC hdc
, /* [in] Handle of device context */
1484 UINT cbData
, /* [in] Size of metric data array */
1485 LPOUTLINETEXTMETRICA lpOTM
) /* [out] Address of metric data array */
1487 char buf
[512], *ptr
;
1489 OUTLINETEXTMETRICW
*lpOTMW
= (OUTLINETEXTMETRICW
*)buf
;
1490 OUTLINETEXTMETRICA
*output
= lpOTM
;
1493 if((ret
= GetOutlineTextMetricsW(hdc
, 0, NULL
)) == 0)
1495 if(ret
> sizeof(buf
))
1496 lpOTMW
= HeapAlloc(GetProcessHeap(), 0, ret
);
1497 GetOutlineTextMetricsW(hdc
, ret
, lpOTMW
);
1499 needed
= sizeof(OUTLINETEXTMETRICA
);
1500 if(lpOTMW
->otmpFamilyName
)
1501 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1502 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFamilyName
), -1,
1503 NULL
, 0, NULL
, NULL
);
1504 if(lpOTMW
->otmpFaceName
)
1505 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1506 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFaceName
), -1,
1507 NULL
, 0, NULL
, NULL
);
1508 if(lpOTMW
->otmpStyleName
)
1509 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1510 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpStyleName
), -1,
1511 NULL
, 0, NULL
, NULL
);
1512 if(lpOTMW
->otmpFullName
)
1513 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1514 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFullName
), -1,
1515 NULL
, 0, NULL
, NULL
);
1522 TRACE("needed = %d\n", needed
);
1524 /* Since the supplied buffer isn't big enough, we'll alloc one
1525 that is and memcpy the first cbData bytes into the lpOTM at
1527 output
= HeapAlloc(GetProcessHeap(), 0, needed
);
1529 ret
= output
->otmSize
= min(needed
, cbData
);
1530 FONT_TextMetricWToA( &lpOTMW
->otmTextMetrics
, &output
->otmTextMetrics
);
1531 output
->otmFiller
= 0;
1532 output
->otmPanoseNumber
= lpOTMW
->otmPanoseNumber
;
1533 output
->otmfsSelection
= lpOTMW
->otmfsSelection
;
1534 output
->otmfsType
= lpOTMW
->otmfsType
;
1535 output
->otmsCharSlopeRise
= lpOTMW
->otmsCharSlopeRise
;
1536 output
->otmsCharSlopeRun
= lpOTMW
->otmsCharSlopeRun
;
1537 output
->otmItalicAngle
= lpOTMW
->otmItalicAngle
;
1538 output
->otmEMSquare
= lpOTMW
->otmEMSquare
;
1539 output
->otmAscent
= lpOTMW
->otmAscent
;
1540 output
->otmDescent
= lpOTMW
->otmDescent
;
1541 output
->otmLineGap
= lpOTMW
->otmLineGap
;
1542 output
->otmsCapEmHeight
= lpOTMW
->otmsCapEmHeight
;
1543 output
->otmsXHeight
= lpOTMW
->otmsXHeight
;
1544 output
->otmrcFontBox
= lpOTMW
->otmrcFontBox
;
1545 output
->otmMacAscent
= lpOTMW
->otmMacAscent
;
1546 output
->otmMacDescent
= lpOTMW
->otmMacDescent
;
1547 output
->otmMacLineGap
= lpOTMW
->otmMacLineGap
;
1548 output
->otmusMinimumPPEM
= lpOTMW
->otmusMinimumPPEM
;
1549 output
->otmptSubscriptSize
= lpOTMW
->otmptSubscriptSize
;
1550 output
->otmptSubscriptOffset
= lpOTMW
->otmptSubscriptOffset
;
1551 output
->otmptSuperscriptSize
= lpOTMW
->otmptSuperscriptSize
;
1552 output
->otmptSuperscriptOffset
= lpOTMW
->otmptSuperscriptOffset
;
1553 output
->otmsStrikeoutSize
= lpOTMW
->otmsStrikeoutSize
;
1554 output
->otmsStrikeoutPosition
= lpOTMW
->otmsStrikeoutPosition
;
1555 output
->otmsUnderscoreSize
= lpOTMW
->otmsUnderscoreSize
;
1556 output
->otmsUnderscorePosition
= lpOTMW
->otmsUnderscorePosition
;
1559 ptr
= (char*)(output
+ 1);
1560 left
= needed
- sizeof(*output
);
1562 if(lpOTMW
->otmpFamilyName
) {
1563 output
->otmpFamilyName
= (LPSTR
)(ptr
- (char*)output
);
1564 len
= WideCharToMultiByte(CP_ACP
, 0,
1565 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFamilyName
), -1,
1566 ptr
, left
, NULL
, NULL
);
1570 output
->otmpFamilyName
= 0;
1572 if(lpOTMW
->otmpFaceName
) {
1573 output
->otmpFaceName
= (LPSTR
)(ptr
- (char*)output
);
1574 len
= WideCharToMultiByte(CP_ACP
, 0,
1575 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFaceName
), -1,
1576 ptr
, left
, NULL
, NULL
);
1580 output
->otmpFaceName
= 0;
1582 if(lpOTMW
->otmpStyleName
) {
1583 output
->otmpStyleName
= (LPSTR
)(ptr
- (char*)output
);
1584 len
= WideCharToMultiByte(CP_ACP
, 0,
1585 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpStyleName
), -1,
1586 ptr
, left
, NULL
, NULL
);
1590 output
->otmpStyleName
= 0;
1592 if(lpOTMW
->otmpFullName
) {
1593 output
->otmpFullName
= (LPSTR
)(ptr
- (char*)output
);
1594 len
= WideCharToMultiByte(CP_ACP
, 0,
1595 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFullName
), -1,
1596 ptr
, left
, NULL
, NULL
);
1599 output
->otmpFullName
= 0;
1603 if(output
!= lpOTM
) {
1604 memcpy(lpOTM
, output
, cbData
);
1605 HeapFree(GetProcessHeap(), 0, output
);
1607 /* check if the string offsets really fit into the provided size */
1608 /* FIXME: should we check string length as well? */
1609 /* make sure that we don't read/write beyond the provided buffer */
1610 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFamilyName
) + sizeof(LPSTR
))
1612 if ((UINT_PTR
)lpOTM
->otmpFamilyName
>= lpOTM
->otmSize
)
1613 lpOTM
->otmpFamilyName
= 0; /* doesn't fit */
1616 /* make sure that we don't read/write beyond the provided buffer */
1617 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFaceName
) + sizeof(LPSTR
))
1619 if ((UINT_PTR
)lpOTM
->otmpFaceName
>= lpOTM
->otmSize
)
1620 lpOTM
->otmpFaceName
= 0; /* doesn't fit */
1623 /* make sure that we don't read/write beyond the provided buffer */
1624 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpStyleName
) + sizeof(LPSTR
))
1626 if ((UINT_PTR
)lpOTM
->otmpStyleName
>= lpOTM
->otmSize
)
1627 lpOTM
->otmpStyleName
= 0; /* doesn't fit */
1630 /* make sure that we don't read/write beyond the provided buffer */
1631 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFullName
) + sizeof(LPSTR
))
1633 if ((UINT_PTR
)lpOTM
->otmpFullName
>= lpOTM
->otmSize
)
1634 lpOTM
->otmpFullName
= 0; /* doesn't fit */
1639 if(lpOTMW
!= (OUTLINETEXTMETRICW
*)buf
)
1640 HeapFree(GetProcessHeap(), 0, lpOTMW
);
1646 /***********************************************************************
1647 * GetOutlineTextMetricsW [GDI32.@]
1649 UINT WINAPI
GetOutlineTextMetricsW(
1650 HDC hdc
, /* [in] Handle of device context */
1651 UINT cbData
, /* [in] Size of metric data array */
1652 LPOUTLINETEXTMETRICW lpOTM
) /* [out] Address of metric data array */
1654 DC
*dc
= DC_GetDCPtr( hdc
);
1655 OUTLINETEXTMETRICW
*output
= lpOTM
;
1658 TRACE("(%p,%d,%p)\n", hdc
, cbData
, lpOTM
);
1662 ret
= WineEngGetOutlineTextMetrics(dc
->gdiFont
, cbData
, output
);
1665 output
= HeapAlloc(GetProcessHeap(), 0, ret
);
1666 WineEngGetOutlineTextMetrics(dc
->gdiFont
, ret
, output
);
1669 #define WDPTOLP(x) ((x<0)? \
1670 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1671 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1672 #define HDPTOLP(y) ((y<0)? \
1673 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1674 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1676 output
->otmTextMetrics
.tmHeight
= HDPTOLP(output
->otmTextMetrics
.tmHeight
);
1677 output
->otmTextMetrics
.tmAscent
= HDPTOLP(output
->otmTextMetrics
.tmAscent
);
1678 output
->otmTextMetrics
.tmDescent
= HDPTOLP(output
->otmTextMetrics
.tmDescent
);
1679 output
->otmTextMetrics
.tmInternalLeading
= HDPTOLP(output
->otmTextMetrics
.tmInternalLeading
);
1680 output
->otmTextMetrics
.tmExternalLeading
= HDPTOLP(output
->otmTextMetrics
.tmExternalLeading
);
1681 output
->otmTextMetrics
.tmAveCharWidth
= WDPTOLP(output
->otmTextMetrics
.tmAveCharWidth
);
1682 output
->otmTextMetrics
.tmMaxCharWidth
= WDPTOLP(output
->otmTextMetrics
.tmMaxCharWidth
);
1683 output
->otmTextMetrics
.tmOverhang
= WDPTOLP(output
->otmTextMetrics
.tmOverhang
);
1684 output
->otmAscent
= HDPTOLP(output
->otmAscent
);
1685 output
->otmDescent
= HDPTOLP(output
->otmDescent
);
1686 output
->otmLineGap
= HDPTOLP(output
->otmLineGap
);
1687 output
->otmsCapEmHeight
= HDPTOLP(output
->otmsCapEmHeight
);
1688 output
->otmsXHeight
= HDPTOLP(output
->otmsXHeight
);
1689 output
->otmrcFontBox
.top
= HDPTOLP(output
->otmrcFontBox
.top
);
1690 output
->otmrcFontBox
.bottom
= HDPTOLP(output
->otmrcFontBox
.bottom
);
1691 output
->otmrcFontBox
.left
= WDPTOLP(output
->otmrcFontBox
.left
);
1692 output
->otmrcFontBox
.right
= WDPTOLP(output
->otmrcFontBox
.right
);
1693 output
->otmMacAscent
= HDPTOLP(output
->otmMacAscent
);
1694 output
->otmMacDescent
= HDPTOLP(output
->otmMacDescent
);
1695 output
->otmMacLineGap
= HDPTOLP(output
->otmMacLineGap
);
1696 output
->otmptSubscriptSize
.x
= WDPTOLP(output
->otmptSubscriptSize
.x
);
1697 output
->otmptSubscriptSize
.y
= HDPTOLP(output
->otmptSubscriptSize
.y
);
1698 output
->otmptSubscriptOffset
.x
= WDPTOLP(output
->otmptSubscriptOffset
.x
);
1699 output
->otmptSubscriptOffset
.y
= HDPTOLP(output
->otmptSubscriptOffset
.y
);
1700 output
->otmptSuperscriptSize
.x
= WDPTOLP(output
->otmptSuperscriptSize
.x
);
1701 output
->otmptSuperscriptSize
.y
= HDPTOLP(output
->otmptSuperscriptSize
.y
);
1702 output
->otmptSuperscriptOffset
.x
= WDPTOLP(output
->otmptSuperscriptOffset
.x
);
1703 output
->otmptSuperscriptOffset
.y
= HDPTOLP(output
->otmptSuperscriptOffset
.y
);
1704 output
->otmsStrikeoutSize
= HDPTOLP(output
->otmsStrikeoutSize
);
1705 output
->otmsStrikeoutPosition
= HDPTOLP(output
->otmsStrikeoutPosition
);
1706 output
->otmsUnderscoreSize
= HDPTOLP(output
->otmsUnderscoreSize
);
1707 output
->otmsUnderscorePosition
= HDPTOLP(output
->otmsUnderscorePosition
);
1710 if(output
!= lpOTM
) {
1711 memcpy(lpOTM
, output
, cbData
);
1712 HeapFree(GetProcessHeap(), 0, output
);
1718 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1719 but really this should just be a return 0. */
1721 ret
= sizeof(*lpOTM
);
1726 memset(lpOTM
, 0, ret
);
1727 lpOTM
->otmSize
= sizeof(*lpOTM
);
1728 GetTextMetricsW(hdc
, &lpOTM
->otmTextMetrics
);
1730 Further fill of the structure not implemented,
1731 Needs real values for the structure members
1736 DC_ReleaseDCPtr(dc
);
1741 /***********************************************************************
1742 * GetCharWidthW (GDI32.@)
1743 * GetCharWidth32W (GDI32.@)
1745 BOOL WINAPI
GetCharWidth32W( HDC hdc
, UINT firstChar
, UINT lastChar
,
1750 DC
* dc
= DC_GetDCPtr( hdc
);
1751 if (!dc
) return FALSE
;
1754 ret
= WineEngGetCharWidth( dc
->gdiFont
, firstChar
, lastChar
, buffer
);
1755 else if (dc
->funcs
->pGetCharWidth
)
1756 ret
= dc
->funcs
->pGetCharWidth( dc
->physDev
, firstChar
, lastChar
, buffer
);
1760 /* convert device units to logical */
1761 for( i
= firstChar
; i
<= lastChar
; i
++, buffer
++ )
1762 *buffer
= INTERNAL_XDSTOWS(dc
, *buffer
);
1765 DC_ReleaseDCPtr( dc
);
1770 /***********************************************************************
1771 * GetCharWidthA (GDI32.@)
1772 * GetCharWidth32A (GDI32.@)
1774 BOOL WINAPI
GetCharWidth32A( HDC hdc
, UINT firstChar
, UINT lastChar
,
1777 INT i
, wlen
, count
= (INT
)(lastChar
- firstChar
+ 1);
1782 if(count
<= 0) return FALSE
;
1784 str
= HeapAlloc(GetProcessHeap(), 0, count
);
1785 for(i
= 0; i
< count
; i
++)
1786 str
[i
] = (BYTE
)(firstChar
+ i
);
1788 wstr
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
1790 for(i
= 0; i
< wlen
; i
++)
1792 if(!GetCharWidth32W(hdc
, wstr
[i
], wstr
[i
], buffer
))
1800 HeapFree(GetProcessHeap(), 0, str
);
1801 HeapFree(GetProcessHeap(), 0, wstr
);
1807 /***********************************************************************
1808 * ExtTextOutA (GDI32.@)
1812 BOOL WINAPI
ExtTextOutA( HDC hdc
, INT x
, INT y
, UINT flags
,
1813 const RECT
*lprect
, LPCSTR str
, UINT count
, const INT
*lpDx
)
1821 if (flags
& ETO_GLYPH_INDEX
)
1822 return ExtTextOutW( hdc
, x
, y
, flags
, lprect
, (LPCWSTR
)str
, count
, lpDx
);
1824 p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, &codepage
);
1827 unsigned int i
= 0, j
= 0;
1829 lpDxW
= HeapAlloc( GetProcessHeap(), 0, wlen
*sizeof(INT
));
1831 if(IsDBCSLeadByteEx(codepage
, str
[i
])) {
1832 lpDxW
[j
++] = lpDx
[i
] + lpDx
[i
+1];
1835 lpDxW
[j
++] = lpDx
[i
];
1841 ret
= ExtTextOutW( hdc
, x
, y
, flags
, lprect
, p
, wlen
, lpDxW
);
1843 HeapFree( GetProcessHeap(), 0, p
);
1844 HeapFree( GetProcessHeap(), 0, lpDxW
);
1849 /***********************************************************************
1850 * ExtTextOutW (GDI32.@)
1852 * Draws text using the currently selected font, background color, and text color.
1856 * x,y [I] coordinates of string
1858 * ETO_GRAYED - undocumented on MSDN
1859 * ETO_OPAQUE - use background color for fill the rectangle
1860 * ETO_CLIPPED - clipping text to the rectangle
1861 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1862 * than encoded characters. Implies ETO_IGNORELANGUAGE
1863 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1864 * Affects BiDi ordering
1865 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1866 * ETO_PDY - unimplemented
1867 * ETO_NUMERICSLATIN - unimplemented always assumed -
1868 * do not translate numbers into locale representations
1869 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1870 * lprect [I] dimensions for clipping or/and opaquing
1871 * str [I] text string
1872 * count [I] number of symbols in string
1873 * lpDx [I] optional parameter with distance between drawing characters
1879 BOOL WINAPI
ExtTextOutW( HDC hdc
, INT x
, INT y
, UINT flags
,
1880 const RECT
*lprect
, LPCWSTR str
, UINT count
, const INT
*lpDx
)
1883 LPWSTR reordered_str
= (LPWSTR
)str
;
1884 WORD
*glyphs
= NULL
;
1885 UINT align
= GetTextAlign( hdc
);
1889 double cosEsc
, sinEsc
;
1890 INT
*deltas
= NULL
, char_extra
;
1893 BOOL done_extents
= FALSE
;
1894 INT width
= 0, xwidth
= 0, ywidth
= 0;
1896 DC
* dc
= get_dc_ptr( hdc
);
1899 if (!dc
) return FALSE
;
1901 breakRem
= dc
->breakRem
;
1903 if (flags
& (ETO_NUMERICSLOCAL
| ETO_NUMERICSLATIN
| ETO_PDY
))
1904 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY unimplemented\n");
1906 if (!dc
->funcs
->pExtTextOut
&& !PATH_IsPathOpen(dc
->path
))
1908 release_dc_ptr( dc
);
1913 type
= GetObjectType(hdc
);
1914 if(type
== OBJ_METADC
|| type
== OBJ_ENHMETADC
)
1916 ret
= dc
->funcs
->pExtTextOut(dc
->physDev
, x
, y
, flags
, lprect
, str
, count
, lpDx
);
1917 release_dc_ptr( dc
);
1922 flags
&= ~ETO_CLIPPED
;
1924 if( !(flags
& (ETO_GLYPH_INDEX
| ETO_IGNORELANGUAGE
)) && count
> 0 )
1926 reordered_str
= HeapAlloc(GetProcessHeap(), 0, count
*sizeof(WCHAR
));
1928 BIDI_Reorder( str
, count
, GCP_REORDER
,
1929 ((flags
&ETO_RTLREADING
)!=0 || (GetTextAlign(hdc
)&TA_RTLREADING
)!=0)?
1930 WINE_GCPW_FORCE_RTL
:WINE_GCPW_FORCE_LTR
,
1931 reordered_str
, count
, NULL
);
1933 flags
|= ETO_IGNORELANGUAGE
;
1936 TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc
, x
, y
, flags
,
1937 lprect
, debugstr_wn(str
, count
), count
, lpDx
);
1939 if(flags
& ETO_GLYPH_INDEX
)
1940 glyphs
= reordered_str
;
1943 TRACE("rect: %d,%d - %d,%d\n", lprect
->left
, lprect
->top
, lprect
->right
,
1945 TRACE("align = %x bkmode = %x mapmode = %x\n", align
, GetBkMode(hdc
), GetMapMode(hdc
));
1947 if(align
& TA_UPDATECP
)
1949 GetCurrentPositionEx( hdc
, &pt
);
1954 GetTextMetricsW(hdc
, &tm
);
1955 GetObjectW(GetCurrentObject(hdc
, OBJ_FONT
), sizeof(lf
), &lf
);
1957 if(!(tm
.tmPitchAndFamily
& TMPF_VECTOR
)) /* Non-scalable fonts shouldn't be rotated */
1958 lf
.lfEscapement
= 0;
1960 if(lf
.lfEscapement
!= 0)
1962 cosEsc
= cos(lf
.lfEscapement
* M_PI
/ 1800);
1963 sinEsc
= sin(lf
.lfEscapement
* M_PI
/ 1800);
1971 if(flags
& (ETO_CLIPPED
| ETO_OPAQUE
))
1975 if(flags
& ETO_GLYPH_INDEX
)
1976 GetTextExtentPointI(hdc
, glyphs
, count
, &sz
);
1978 GetTextExtentPointW(hdc
, reordered_str
, count
, &sz
);
1980 done_extents
= TRUE
;
1983 rc
.right
= x
+ sz
.cx
;
1984 rc
.bottom
= y
+ sz
.cy
;
1991 LPtoDP(hdc
, (POINT
*)&rc
, 2);
1993 if(rc
.left
> rc
.right
) {INT tmp
= rc
.left
; rc
.left
= rc
.right
; rc
.right
= tmp
;}
1994 if(rc
.top
> rc
.bottom
) {INT tmp
= rc
.top
; rc
.top
= rc
.bottom
; rc
.bottom
= tmp
;}
1997 if ((flags
& ETO_OPAQUE
) && !PATH_IsPathOpen(dc
->path
))
1998 dc
->funcs
->pExtTextOut(dc
->physDev
, 0, 0, ETO_OPAQUE
, &rc
, NULL
, 0, NULL
);
2008 LPtoDP(hdc
, &pt
, 1);
2012 char_extra
= GetTextCharacterExtra(hdc
);
2013 if(char_extra
|| dc
->breakExtra
|| breakRem
|| lpDx
|| lf
.lfEscapement
!= 0)
2017 deltas
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(INT
));
2018 for(i
= 0; i
< count
; i
++)
2020 if(lpDx
&& (flags
& ETO_PDY
))
2021 deltas
[i
] = lpDx
[i
*2] + char_extra
;
2023 deltas
[i
] = lpDx
[i
] + char_extra
;
2026 if(flags
& ETO_GLYPH_INDEX
)
2027 GetTextExtentPointI(hdc
, glyphs
+ i
, 1, &tmpsz
);
2029 GetTextExtentPointW(hdc
, reordered_str
+ i
, 1, &tmpsz
);
2031 deltas
[i
] = tmpsz
.cx
;
2034 if (!(flags
& ETO_GLYPH_INDEX
) && (dc
->breakExtra
|| breakRem
) && reordered_str
[i
] == tm
.tmBreakChar
)
2036 deltas
[i
] = deltas
[i
] + dc
->breakExtra
;
2043 deltas
[i
] = INTERNAL_XWSTODS(dc
, deltas
[i
]);
2051 if(flags
& ETO_GLYPH_INDEX
)
2052 GetTextExtentPointI(hdc
, glyphs
, count
, &sz
);
2054 GetTextExtentPointW(hdc
, reordered_str
, count
, &sz
);
2055 done_extents
= TRUE
;
2057 width
= INTERNAL_XWSTODS(dc
, sz
.cx
);
2059 xwidth
= width
* cosEsc
;
2060 ywidth
= width
* sinEsc
;
2062 tm
.tmAscent
= abs(INTERNAL_YWSTODS(dc
, tm
.tmAscent
));
2063 tm
.tmDescent
= abs(INTERNAL_YWSTODS(dc
, tm
.tmDescent
));
2064 switch( align
& (TA_LEFT
| TA_RIGHT
| TA_CENTER
) )
2067 if (align
& TA_UPDATECP
)
2071 DPtoLP(hdc
, &pt
, 1);
2072 MoveToEx(hdc
, pt
.x
, pt
.y
, NULL
);
2084 if (align
& TA_UPDATECP
)
2088 DPtoLP(hdc
, &pt
, 1);
2089 MoveToEx(hdc
, pt
.x
, pt
.y
, NULL
);
2094 switch( align
& (TA_TOP
| TA_BOTTOM
| TA_BASELINE
) )
2097 y
+= tm
.tmAscent
* cosEsc
;
2098 x
+= tm
.tmAscent
* sinEsc
;
2102 y
-= tm
.tmDescent
* cosEsc
;
2103 x
-= tm
.tmDescent
* sinEsc
;
2110 if (GetBkMode(hdc
) != TRANSPARENT
&& !PATH_IsPathOpen(dc
->path
))
2112 if(!((flags
& ETO_CLIPPED
) && (flags
& ETO_OPAQUE
)))
2114 if(!(flags
& ETO_OPAQUE
) || x
< rc
.left
|| x
+ width
>= rc
.right
||
2115 y
- tm
.tmAscent
< rc
.top
|| y
+ tm
.tmDescent
>= rc
.bottom
)
2119 rc
.right
= x
+ width
;
2120 rc
.top
= y
- tm
.tmAscent
;
2121 rc
.bottom
= y
+ tm
.tmDescent
;
2122 dc
->funcs
->pExtTextOut(dc
->physDev
, 0, 0, ETO_OPAQUE
, &rc
, NULL
, 0, NULL
);
2127 if(FontIsLinked(hdc
) && !(flags
& ETO_GLYPH_INDEX
))
2129 HFONT orig_font
= dc
->hFont
, cur_font
;
2131 INT span
= 0, *offsets
= NULL
;
2134 glyphs
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(WORD
));
2135 for(i
= 0; i
< count
; i
++)
2137 WineEngGetLinkedHFont(dc
, reordered_str
[i
], &cur_font
, &glyph
);
2138 if(cur_font
!= dc
->hFont
)
2143 offsets
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(*deltas
));
2148 for(j
= 1; j
< count
; j
++)
2150 GetTextExtentPointW(hdc
, reordered_str
+ j
- 1, 1, &tmpsz
);
2151 offsets
[j
] = offsets
[j
-1] + INTERNAL_XWSTODS(dc
, tmpsz
.cx
);
2156 for(j
= 1; j
< count
; j
++)
2157 offsets
[j
] = offsets
[j
-1] + deltas
[j
];
2162 if (PATH_IsPathOpen(dc
->path
))
2163 ret
= PATH_ExtTextOut(dc
, x
+ offsets
[i
- span
] * cosEsc
, y
- offsets
[i
- span
] * sinEsc
,
2164 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
,
2165 glyphs
, span
, deltas
? deltas
+ i
- span
: NULL
);
2167 dc
->funcs
->pExtTextOut(dc
->physDev
, x
+ offsets
[i
- span
] * cosEsc
, y
- offsets
[i
- span
] * sinEsc
,
2168 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
,
2169 glyphs
, span
, deltas
? deltas
+ i
- span
: NULL
);
2172 SelectObject(hdc
, cur_font
);
2174 glyphs
[span
++] = glyph
;
2178 if (PATH_IsPathOpen(dc
->path
))
2179 ret
= PATH_ExtTextOut(dc
, x
+ (offsets
? offsets
[count
- span
] * cosEsc
: 0),
2180 y
- (offsets
? offsets
[count
- span
] * sinEsc
: 0),
2181 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
,
2182 glyphs
, span
, deltas
? deltas
+ count
- span
: NULL
);
2184 ret
= dc
->funcs
->pExtTextOut(dc
->physDev
, x
+ (offsets
? offsets
[count
- span
] * cosEsc
: 0),
2185 y
- (offsets
? offsets
[count
- span
] * sinEsc
: 0),
2186 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
,
2187 glyphs
, span
, deltas
? deltas
+ count
- span
: NULL
);
2188 SelectObject(hdc
, orig_font
);
2189 HeapFree(GetProcessHeap(), 0, offsets
);
2195 if(!(flags
& ETO_GLYPH_INDEX
) && dc
->gdiFont
)
2197 glyphs
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(WORD
));
2198 GetGlyphIndicesW(hdc
, reordered_str
, count
, glyphs
, 0);
2199 flags
|= ETO_GLYPH_INDEX
;
2202 if (PATH_IsPathOpen(dc
->path
))
2203 ret
= PATH_ExtTextOut(dc
, x
, y
, (flags
& ~ETO_OPAQUE
), &rc
,
2204 glyphs
? glyphs
: reordered_str
, count
, deltas
);
2206 ret
= dc
->funcs
->pExtTextOut(dc
->physDev
, x
, y
, (flags
& ~ETO_OPAQUE
), &rc
,
2207 glyphs
? glyphs
: reordered_str
, count
, deltas
);
2211 HeapFree(GetProcessHeap(), 0, deltas
);
2212 if(glyphs
!= reordered_str
)
2213 HeapFree(GetProcessHeap(), 0, glyphs
);
2214 if(reordered_str
!= str
)
2215 HeapFree(GetProcessHeap(), 0, reordered_str
);
2217 release_dc_ptr( dc
);
2219 if (ret
&& (lf
.lfUnderline
|| lf
.lfStrikeOut
))
2221 int underlinePos
, strikeoutPos
;
2222 int underlineWidth
, strikeoutWidth
;
2223 UINT size
= GetOutlineTextMetricsW(hdc
, 0, NULL
);
2224 OUTLINETEXTMETRICW
* otm
= NULL
;
2229 underlineWidth
= tm
.tmAscent
/ 20 + 1;
2230 strikeoutPos
= tm
.tmAscent
/ 2;
2231 strikeoutWidth
= underlineWidth
;
2235 otm
= HeapAlloc(GetProcessHeap(), 0, size
);
2236 GetOutlineTextMetricsW(hdc
, size
, otm
);
2237 underlinePos
= otm
->otmsUnderscorePosition
;
2238 underlineWidth
= otm
->otmsUnderscoreSize
;
2239 strikeoutPos
= otm
->otmsStrikeoutPosition
;
2240 strikeoutWidth
= otm
->otmsStrikeoutSize
;
2241 HeapFree(GetProcessHeap(), 0, otm
);
2244 if (PATH_IsPathOpen(dc
->path
))
2248 HBRUSH hbrush
= CreateSolidBrush(GetTextColor(hdc
));
2250 hbrush
= SelectObject(hdc
, hbrush
);
2251 hpen
= SelectObject(hdc
, GetStockObject(NULL_PEN
));
2255 pts
[0].x
= x
- underlinePos
* sinEsc
;
2256 pts
[0].y
= y
- underlinePos
* cosEsc
;
2257 pts
[1].x
= x
+ xwidth
- underlinePos
* sinEsc
;
2258 pts
[1].y
= y
- ywidth
- underlinePos
* cosEsc
;
2259 pts
[2].x
= pts
[1].x
+ underlineWidth
* sinEsc
;
2260 pts
[2].y
= pts
[1].y
+ underlineWidth
* cosEsc
;
2261 pts
[3].x
= pts
[0].x
+ underlineWidth
* sinEsc
;
2262 pts
[3].y
= pts
[0].y
+ underlineWidth
* cosEsc
;
2263 pts
[4].x
= pts
[0].x
;
2264 pts
[4].y
= pts
[0].y
;
2265 DPtoLP(hdc
, pts
, 5);
2266 Polygon(hdc
, pts
, 5);
2271 pts
[0].x
= x
- strikeoutPos
* sinEsc
;
2272 pts
[0].y
= y
- strikeoutPos
* cosEsc
;
2273 pts
[1].x
= x
+ xwidth
- strikeoutPos
* sinEsc
;
2274 pts
[1].y
= y
- ywidth
- strikeoutPos
* cosEsc
;
2275 pts
[2].x
= pts
[1].x
+ strikeoutWidth
* sinEsc
;
2276 pts
[2].y
= pts
[1].y
+ strikeoutWidth
* cosEsc
;
2277 pts
[3].x
= pts
[0].x
+ strikeoutWidth
* sinEsc
;
2278 pts
[3].y
= pts
[0].y
+ strikeoutWidth
* cosEsc
;
2279 pts
[4].x
= pts
[0].x
;
2280 pts
[4].y
= pts
[0].y
;
2281 DPtoLP(hdc
, pts
, 5);
2282 Polygon(hdc
, pts
, 5);
2285 SelectObject(hdc
, hpen
);
2286 hbrush
= SelectObject(hdc
, hbrush
);
2287 DeleteObject(hbrush
);
2291 POINT pts
[2], oldpt
;
2296 hpen
= CreatePen(PS_SOLID
, underlineWidth
, GetTextColor(hdc
));
2297 hpen
= SelectObject(hdc
, hpen
);
2300 pts
[1].x
= x
+ xwidth
;
2301 pts
[1].y
= y
- ywidth
;
2302 DPtoLP(hdc
, pts
, 2);
2303 MoveToEx(hdc
, pts
[0].x
- underlinePos
* sinEsc
, pts
[0].y
- underlinePos
* cosEsc
, &oldpt
);
2304 LineTo(hdc
, pts
[1].x
- underlinePos
* sinEsc
, pts
[1].y
- underlinePos
* cosEsc
);
2305 MoveToEx(hdc
, oldpt
.x
, oldpt
.y
, NULL
);
2306 DeleteObject(SelectObject(hdc
, hpen
));
2311 hpen
= CreatePen(PS_SOLID
, strikeoutWidth
, GetTextColor(hdc
));
2312 hpen
= SelectObject(hdc
, hpen
);
2315 pts
[1].x
= x
+ xwidth
;
2316 pts
[1].y
= y
- ywidth
;
2317 DPtoLP(hdc
, pts
, 2);
2318 MoveToEx(hdc
, pts
[0].x
- strikeoutPos
* sinEsc
, pts
[0].y
- strikeoutPos
* cosEsc
, &oldpt
);
2319 LineTo(hdc
, pts
[1].x
- strikeoutPos
* sinEsc
, pts
[1].y
- strikeoutPos
* cosEsc
);
2320 MoveToEx(hdc
, oldpt
.x
, oldpt
.y
, NULL
);
2321 DeleteObject(SelectObject(hdc
, hpen
));
2330 /***********************************************************************
2331 * TextOutA (GDI32.@)
2333 BOOL WINAPI
TextOutA( HDC hdc
, INT x
, INT y
, LPCSTR str
, INT count
)
2335 return ExtTextOutA( hdc
, x
, y
, 0, NULL
, str
, count
, NULL
);
2339 /***********************************************************************
2340 * TextOutW (GDI32.@)
2342 BOOL WINAPI
TextOutW(HDC hdc
, INT x
, INT y
, LPCWSTR str
, INT count
)
2344 return ExtTextOutW( hdc
, x
, y
, 0, NULL
, str
, count
, NULL
);
2348 /***********************************************************************
2349 * PolyTextOutA (GDI32.@)
2353 BOOL WINAPI
PolyTextOutA( HDC hdc
, const POLYTEXTA
*pptxt
, INT cStrings
)
2355 for (; cStrings
>0; cStrings
--, pptxt
++)
2356 if (!ExtTextOutA( hdc
, pptxt
->x
, pptxt
->y
, pptxt
->uiFlags
, &pptxt
->rcl
, pptxt
->lpstr
, pptxt
->n
, pptxt
->pdx
))
2363 /***********************************************************************
2364 * PolyTextOutW (GDI32.@)
2366 * Draw several Strings
2372 BOOL WINAPI
PolyTextOutW( HDC hdc
, const POLYTEXTW
*pptxt
, INT cStrings
)
2374 for (; cStrings
>0; cStrings
--, pptxt
++)
2375 if (!ExtTextOutW( hdc
, pptxt
->x
, pptxt
->y
, pptxt
->uiFlags
, &pptxt
->rcl
, pptxt
->lpstr
, pptxt
->n
, pptxt
->pdx
))
2381 /* FIXME: all following APIs ******************************************/
2384 /***********************************************************************
2385 * SetMapperFlags (GDI32.@)
2387 DWORD WINAPI
SetMapperFlags( HDC hDC
, DWORD dwFlag
)
2389 DC
*dc
= DC_GetDCPtr( hDC
);
2392 if(dc
->funcs
->pSetMapperFlags
)
2394 ret
= dc
->funcs
->pSetMapperFlags( dc
->physDev
, dwFlag
);
2395 /* FIXME: ret is just a success flag, we should return a proper value */
2398 FIXME("(%p, 0x%08x): stub - harmless\n", hDC
, dwFlag
);
2399 DC_ReleaseDCPtr( dc
);
2403 /***********************************************************************
2404 * GetAspectRatioFilterEx (GDI.486)
2406 BOOL16 WINAPI
GetAspectRatioFilterEx16( HDC16 hdc
, LPSIZE16 pAspectRatio
)
2408 FIXME("(%04x, %p): -- Empty Stub !\n", hdc
, pAspectRatio
);
2412 /***********************************************************************
2413 * GetAspectRatioFilterEx (GDI32.@)
2415 BOOL WINAPI
GetAspectRatioFilterEx( HDC hdc
, LPSIZE pAspectRatio
)
2417 FIXME("(%p, %p): -- Empty Stub !\n", hdc
, pAspectRatio
);
2422 /***********************************************************************
2423 * GetCharABCWidthsA (GDI32.@)
2425 * See GetCharABCWidthsW.
2427 BOOL WINAPI
GetCharABCWidthsA(HDC hdc
, UINT firstChar
, UINT lastChar
,
2430 INT i
, wlen
, count
= (INT
)(lastChar
- firstChar
+ 1);
2435 if(count
<= 0) return FALSE
;
2437 str
= HeapAlloc(GetProcessHeap(), 0, count
);
2438 for(i
= 0; i
< count
; i
++)
2439 str
[i
] = (BYTE
)(firstChar
+ i
);
2441 wstr
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
2443 for(i
= 0; i
< wlen
; i
++)
2445 if(!GetCharABCWidthsW(hdc
, wstr
[i
], wstr
[i
], abc
))
2453 HeapFree(GetProcessHeap(), 0, str
);
2454 HeapFree(GetProcessHeap(), 0, wstr
);
2460 /******************************************************************************
2461 * GetCharABCWidthsW [GDI32.@]
2463 * Retrieves widths of characters in range.
2466 * hdc [I] Handle of device context
2467 * firstChar [I] First character in range to query
2468 * lastChar [I] Last character in range to query
2469 * abc [O] Address of character-width structure
2472 * Only works with TrueType fonts
2478 BOOL WINAPI
GetCharABCWidthsW( HDC hdc
, UINT firstChar
, UINT lastChar
,
2481 DC
*dc
= DC_GetDCPtr(hdc
);
2485 if (!dc
) return FALSE
;
2488 ret
= WineEngGetCharABCWidths( dc
->gdiFont
, firstChar
, lastChar
, abc
);
2494 /* convert device units to logical */
2495 for( i
= firstChar
; i
<= lastChar
; i
++, abc
++ ) {
2496 abc
->abcA
= INTERNAL_XDSTOWS(dc
, abc
->abcA
);
2497 abc
->abcB
= INTERNAL_XDSTOWS(dc
, abc
->abcB
);
2498 abc
->abcC
= INTERNAL_XDSTOWS(dc
, abc
->abcC
);
2503 DC_ReleaseDCPtr( dc
);
2508 /******************************************************************************
2509 * GetCharABCWidthsI [GDI32.@]
2511 * Retrieves widths of characters in range.
2514 * hdc [I] Handle of device context
2515 * firstChar [I] First glyphs in range to query
2516 * count [I] Last glyphs in range to query
2517 * pgi [i] Array of glyphs to query
2518 * abc [O] Address of character-width structure
2521 * Only works with TrueType fonts
2527 BOOL WINAPI
GetCharABCWidthsI( HDC hdc
, UINT firstChar
, UINT count
,
2528 LPWORD pgi
, LPABC abc
)
2530 DC
*dc
= DC_GetDCPtr(hdc
);
2534 if (!dc
) return FALSE
;
2537 ret
= WineEngGetCharABCWidthsI( dc
->gdiFont
, firstChar
, count
, pgi
, abc
);
2543 /* convert device units to logical */
2544 for( i
= 0; i
< count
; i
++, abc
++ ) {
2545 abc
->abcA
= INTERNAL_XDSTOWS(dc
, abc
->abcA
);
2546 abc
->abcB
= INTERNAL_XDSTOWS(dc
, abc
->abcB
);
2547 abc
->abcC
= INTERNAL_XDSTOWS(dc
, abc
->abcC
);
2552 DC_ReleaseDCPtr( dc
);
2557 /***********************************************************************
2558 * GetGlyphOutlineA (GDI32.@)
2560 DWORD WINAPI
GetGlyphOutlineA( HDC hdc
, UINT uChar
, UINT fuFormat
,
2561 LPGLYPHMETRICS lpgm
, DWORD cbBuffer
,
2562 LPVOID lpBuffer
, const MAT2
*lpmat2
)
2568 if(!(fuFormat
& GGO_GLYPH_INDEX
)) {
2571 if(uChar
> 0xff) { /* but, 2 bytes character only */
2573 mbchs
[0] = (uChar
& 0xff00) >> 8;
2574 mbchs
[1] = (uChar
& 0xff);
2577 mbchs
[0] = (uChar
& 0xff);
2579 p
= FONT_mbtowc(hdc
, mbchs
, len
, NULL
, NULL
);
2583 ret
= GetGlyphOutlineW(hdc
, c
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
,
2585 HeapFree(GetProcessHeap(), 0, p
);
2589 /***********************************************************************
2590 * GetGlyphOutlineW (GDI32.@)
2592 DWORD WINAPI
GetGlyphOutlineW( HDC hdc
, UINT uChar
, UINT fuFormat
,
2593 LPGLYPHMETRICS lpgm
, DWORD cbBuffer
,
2594 LPVOID lpBuffer
, const MAT2
*lpmat2
)
2596 DC
*dc
= DC_GetDCPtr(hdc
);
2599 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2600 hdc
, uChar
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
, lpmat2
);
2602 if(!dc
) return GDI_ERROR
;
2605 ret
= WineEngGetGlyphOutline(dc
->gdiFont
, uChar
, fuFormat
, lpgm
,
2606 cbBuffer
, lpBuffer
, lpmat2
);
2610 DC_ReleaseDCPtr( dc
);
2615 /***********************************************************************
2616 * CreateScalableFontResourceA (GDI32.@)
2618 BOOL WINAPI
CreateScalableFontResourceA( DWORD fHidden
,
2619 LPCSTR lpszResourceFile
,
2620 LPCSTR lpszFontFile
,
2621 LPCSTR lpszCurrentPath
)
2625 /* fHidden=1 - only visible for the calling app, read-only, not
2626 * enumbered with EnumFonts/EnumFontFamilies
2627 * lpszCurrentPath can be NULL
2629 FIXME("(%d,%s,%s,%s): stub\n",
2630 fHidden
, debugstr_a(lpszResourceFile
), debugstr_a(lpszFontFile
),
2631 debugstr_a(lpszCurrentPath
) );
2633 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2634 if ((f
= CreateFileA(lpszResourceFile
, 0, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, 0)) != INVALID_HANDLE_VALUE
) {
2636 SetLastError(ERROR_FILE_EXISTS
);
2639 return FALSE
; /* create failed */
2642 /***********************************************************************
2643 * CreateScalableFontResourceW (GDI32.@)
2645 BOOL WINAPI
CreateScalableFontResourceW( DWORD fHidden
,
2646 LPCWSTR lpszResourceFile
,
2647 LPCWSTR lpszFontFile
,
2648 LPCWSTR lpszCurrentPath
)
2650 FIXME("(%d,%p,%p,%p): stub\n",
2651 fHidden
, lpszResourceFile
, lpszFontFile
, lpszCurrentPath
);
2652 return FALSE
; /* create failed */
2655 /*************************************************************************
2656 * GetKerningPairsA (GDI32.@)
2658 DWORD WINAPI
GetKerningPairsA( HDC hDC
, DWORD cPairs
,
2659 LPKERNINGPAIR kern_pairA
)
2664 DWORD i
, total_kern_pairs
, kern_pairs_copied
= 0;
2665 KERNINGPAIR
*kern_pairW
;
2667 if (!cPairs
&& kern_pairA
)
2669 SetLastError(ERROR_INVALID_PARAMETER
);
2673 charset
= GetTextCharset(hDC
);
2674 if (!TranslateCharsetInfo(ULongToPtr(charset
), &csi
, TCI_SRCCHARSET
))
2676 FIXME("Can't find codepage for charset %d\n", charset
);
2679 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2680 * to fail on an invalid character for CP_SYMBOL.
2682 cpi
.DefaultChar
[0] = 0;
2683 if (csi
.ciACP
!= CP_SYMBOL
&& !GetCPInfo(csi
.ciACP
, &cpi
))
2685 FIXME("Can't find codepage %u info\n", csi
.ciACP
);
2688 TRACE("charset %d => codepage %u\n", charset
, csi
.ciACP
);
2690 total_kern_pairs
= GetKerningPairsW(hDC
, 0, NULL
);
2691 if (!total_kern_pairs
) return 0;
2693 kern_pairW
= HeapAlloc(GetProcessHeap(), 0, total_kern_pairs
* sizeof(*kern_pairW
));
2694 GetKerningPairsW(hDC
, total_kern_pairs
, kern_pairW
);
2696 for (i
= 0; i
< total_kern_pairs
; i
++)
2700 if (!WideCharToMultiByte(csi
.ciACP
, 0, &kern_pairW
[i
].wFirst
, 1, &first
, 1, NULL
, NULL
))
2703 if (!WideCharToMultiByte(csi
.ciACP
, 0, &kern_pairW
[i
].wSecond
, 1, &second
, 1, NULL
, NULL
))
2706 if (first
== cpi
.DefaultChar
[0] || second
== cpi
.DefaultChar
[0])
2711 if (kern_pairs_copied
>= cPairs
) break;
2713 kern_pairA
->wFirst
= (BYTE
)first
;
2714 kern_pairA
->wSecond
= (BYTE
)second
;
2715 kern_pairA
->iKernAmount
= kern_pairW
[i
].iKernAmount
;
2718 kern_pairs_copied
++;
2721 HeapFree(GetProcessHeap(), 0, kern_pairW
);
2723 return kern_pairs_copied
;
2726 /*************************************************************************
2727 * GetKerningPairsW (GDI32.@)
2729 DWORD WINAPI
GetKerningPairsW( HDC hDC
, DWORD cPairs
,
2730 LPKERNINGPAIR lpKerningPairs
)
2735 TRACE("(%p,%d,%p)\n", hDC
, cPairs
, lpKerningPairs
);
2737 if (!cPairs
&& lpKerningPairs
)
2739 SetLastError(ERROR_INVALID_PARAMETER
);
2743 dc
= DC_GetDCPtr(hDC
);
2747 ret
= WineEngGetKerningPairs(dc
->gdiFont
, cPairs
, lpKerningPairs
);
2749 DC_ReleaseDCPtr( dc
);
2753 /*************************************************************************
2754 * TranslateCharsetInfo [GDI32.@]
2756 * Fills a CHARSETINFO structure for a character set, code page, or
2757 * font. This allows making the correspondance between different labelings
2758 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2759 * of the same encoding.
2761 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2762 * only one codepage should be set in *lpSrc.
2765 * TRUE on success, FALSE on failure.
2768 BOOL WINAPI
TranslateCharsetInfo(
2769 LPDWORD lpSrc
, /* [in]
2770 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2771 if flags == TCI_SRCCHARSET: a character set value
2772 if flags == TCI_SRCCODEPAGE: a code page value
2774 LPCHARSETINFO lpCs
, /* [out] structure to receive charset information */
2775 DWORD flags
/* [in] determines interpretation of lpSrc */)
2779 case TCI_SRCFONTSIG
:
2780 while (!(*lpSrc
>>index
& 0x0001) && index
<MAXTCIINDEX
) index
++;
2782 case TCI_SRCCODEPAGE
:
2783 while (PtrToUlong(lpSrc
) != FONT_tci
[index
].ciACP
&& index
< MAXTCIINDEX
) index
++;
2785 case TCI_SRCCHARSET
:
2786 while (PtrToUlong(lpSrc
) != FONT_tci
[index
].ciCharset
&& index
< MAXTCIINDEX
) index
++;
2791 if (index
>= MAXTCIINDEX
|| FONT_tci
[index
].ciCharset
== DEFAULT_CHARSET
) return FALSE
;
2792 memcpy(lpCs
, &FONT_tci
[index
], sizeof(CHARSETINFO
));
2796 /*************************************************************************
2797 * GetFontLanguageInfo (GDI32.@)
2799 DWORD WINAPI
GetFontLanguageInfo(HDC hdc
)
2801 FONTSIGNATURE fontsig
;
2802 static const DWORD GCP_DBCS_MASK
=0x003F0000,
2803 GCP_DIACRITIC_MASK
=0x00000000,
2804 FLI_GLYPHS_MASK
=0x00000000,
2805 GCP_GLYPHSHAPE_MASK
=0x00000040,
2806 GCP_KASHIDA_MASK
=0x00000000,
2807 GCP_LIGATE_MASK
=0x00000000,
2808 GCP_USEKERNING_MASK
=0x00000000,
2809 GCP_REORDER_MASK
=0x00000060;
2813 GetTextCharsetInfo( hdc
, &fontsig
, 0 );
2814 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2816 if( (fontsig
.fsCsb
[0]&GCP_DBCS_MASK
)!=0 )
2819 if( (fontsig
.fsCsb
[0]&GCP_DIACRITIC_MASK
)!=0 )
2820 result
|=GCP_DIACRITIC
;
2822 if( (fontsig
.fsCsb
[0]&FLI_GLYPHS_MASK
)!=0 )
2825 if( (fontsig
.fsCsb
[0]&GCP_GLYPHSHAPE_MASK
)!=0 )
2826 result
|=GCP_GLYPHSHAPE
;
2828 if( (fontsig
.fsCsb
[0]&GCP_KASHIDA_MASK
)!=0 )
2829 result
|=GCP_KASHIDA
;
2831 if( (fontsig
.fsCsb
[0]&GCP_LIGATE_MASK
)!=0 )
2834 if( (fontsig
.fsCsb
[0]&GCP_USEKERNING_MASK
)!=0 )
2835 result
|=GCP_USEKERNING
;
2837 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2838 if( GetTextAlign( hdc
) & TA_RTLREADING
)
2839 if( (fontsig
.fsCsb
[0]&GCP_REORDER_MASK
)!=0 )
2840 result
|=GCP_REORDER
;
2846 /*************************************************************************
2847 * GetFontData [GDI32.@]
2849 * Retrieve data for TrueType font.
2853 * success: Number of bytes returned
2854 * failure: GDI_ERROR
2858 * Calls SetLastError()
2861 DWORD WINAPI
GetFontData(HDC hdc
, DWORD table
, DWORD offset
,
2862 LPVOID buffer
, DWORD length
)
2864 DC
*dc
= DC_GetDCPtr(hdc
);
2865 DWORD ret
= GDI_ERROR
;
2867 if(!dc
) return GDI_ERROR
;
2870 ret
= WineEngGetFontData(dc
->gdiFont
, table
, offset
, buffer
, length
);
2872 DC_ReleaseDCPtr( dc
);
2876 /*************************************************************************
2877 * GetGlyphIndicesA [GDI32.@]
2879 DWORD WINAPI
GetGlyphIndicesA(HDC hdc
, LPCSTR lpstr
, INT count
,
2880 LPWORD pgi
, DWORD flags
)
2886 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2887 hdc
, debugstr_an(lpstr
, count
), count
, pgi
, flags
);
2889 lpstrW
= FONT_mbtowc(hdc
, lpstr
, count
, &countW
, NULL
);
2890 ret
= GetGlyphIndicesW(hdc
, lpstrW
, countW
, pgi
, flags
);
2891 HeapFree(GetProcessHeap(), 0, lpstrW
);
2896 /*************************************************************************
2897 * GetGlyphIndicesW [GDI32.@]
2899 DWORD WINAPI
GetGlyphIndicesW(HDC hdc
, LPCWSTR lpstr
, INT count
,
2900 LPWORD pgi
, DWORD flags
)
2902 DC
*dc
= DC_GetDCPtr(hdc
);
2903 DWORD ret
= GDI_ERROR
;
2905 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2906 hdc
, debugstr_wn(lpstr
, count
), count
, pgi
, flags
);
2908 if(!dc
) return GDI_ERROR
;
2911 ret
= WineEngGetGlyphIndices(dc
->gdiFont
, lpstr
, count
, pgi
, flags
);
2913 DC_ReleaseDCPtr( dc
);
2917 /*************************************************************************
2918 * GetCharacterPlacementA [GDI32.@]
2920 * See GetCharacterPlacementW.
2923 * the web browser control of ie4 calls this with dwFlags=0
2926 GetCharacterPlacementA(HDC hdc
, LPCSTR lpString
, INT uCount
,
2927 INT nMaxExtent
, GCP_RESULTSA
*lpResults
,
2932 GCP_RESULTSW resultsW
;
2936 TRACE("%s, %d, %d, 0x%08x\n",
2937 debugstr_an(lpString
, uCount
), uCount
, nMaxExtent
, dwFlags
);
2939 /* both structs are equal in size */
2940 memcpy(&resultsW
, lpResults
, sizeof(resultsW
));
2942 lpStringW
= FONT_mbtowc(hdc
, lpString
, uCount
, &uCountW
, &font_cp
);
2943 if(lpResults
->lpOutString
)
2944 resultsW
.lpOutString
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*uCountW
);
2946 ret
= GetCharacterPlacementW(hdc
, lpStringW
, uCountW
, nMaxExtent
, &resultsW
, dwFlags
);
2948 lpResults
->nGlyphs
= resultsW
.nGlyphs
;
2949 lpResults
->nMaxFit
= resultsW
.nMaxFit
;
2951 if(lpResults
->lpOutString
) {
2952 WideCharToMultiByte(font_cp
, 0, resultsW
.lpOutString
, uCountW
,
2953 lpResults
->lpOutString
, uCount
, NULL
, NULL
);
2956 HeapFree(GetProcessHeap(), 0, lpStringW
);
2957 HeapFree(GetProcessHeap(), 0, resultsW
.lpOutString
);
2962 /*************************************************************************
2963 * GetCharacterPlacementW [GDI32.@]
2965 * Retrieve information about a string. This includes the width, reordering,
2966 * Glyphing and so on.
2970 * The width and height of the string if successful, 0 if failed.
2974 * All flags except GCP_REORDER are not yet implemented.
2975 * Reordering is not 100% complient to the Windows BiDi method.
2976 * Caret positioning is not yet implemented for BiDi.
2977 * Classes are not yet implemented.
2981 GetCharacterPlacementW(
2982 HDC hdc
, /* [in] Device context for which the rendering is to be done */
2983 LPCWSTR lpString
, /* [in] The string for which information is to be returned */
2984 INT uCount
, /* [in] Number of WORDS in string. */
2985 INT nMaxExtent
, /* [in] Maximum extent the string is to take (in HDC logical units) */
2986 GCP_RESULTSW
*lpResults
,/* [in/out] A pointer to a GCP_RESULTSW struct */
2987 DWORD dwFlags
/* [in] Flags specifying how to process the string */
2994 TRACE("%s, %d, %d, 0x%08x\n",
2995 debugstr_wn(lpString
, uCount
), uCount
, nMaxExtent
, dwFlags
);
2997 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2998 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2999 lpResults
->lStructSize
, lpResults
->lpOutString
, lpResults
->lpOrder
,
3000 lpResults
->lpDx
, lpResults
->lpCaretPos
, lpResults
->lpClass
,
3001 lpResults
->lpGlyphs
, lpResults
->nGlyphs
, lpResults
->nMaxFit
);
3003 if(dwFlags
&(~GCP_REORDER
)) FIXME("flags 0x%08x ignored\n", dwFlags
);
3004 if(lpResults
->lpClass
) FIXME("classes not implemented\n");
3005 if (lpResults
->lpCaretPos
&& (dwFlags
& GCP_REORDER
))
3006 FIXME("Caret positions for complex scripts not implemented\n");
3008 nSet
= (UINT
)uCount
;
3009 if(nSet
> lpResults
->nGlyphs
)
3010 nSet
= lpResults
->nGlyphs
;
3012 /* return number of initialized fields */
3013 lpResults
->nGlyphs
= nSet
;
3015 if((dwFlags
&GCP_REORDER
)==0 )
3017 /* Treat the case where no special handling was requested in a fastpath way */
3018 /* copy will do if the GCP_REORDER flag is not set */
3019 if(lpResults
->lpOutString
)
3020 memcpy( lpResults
->lpOutString
, lpString
, nSet
* sizeof(WCHAR
));
3022 if(lpResults
->lpOrder
)
3024 for(i
= 0; i
< nSet
; i
++)
3025 lpResults
->lpOrder
[i
] = i
;
3029 BIDI_Reorder( lpString
, uCount
, dwFlags
, WINE_GCPW_FORCE_LTR
, lpResults
->lpOutString
,
3030 nSet
, lpResults
->lpOrder
);
3033 /* FIXME: Will use the placement chars */
3034 if (lpResults
->lpDx
)
3037 for (i
= 0; i
< nSet
; i
++)
3039 if (GetCharWidth32W(hdc
, lpString
[i
], lpString
[i
], &c
))
3040 lpResults
->lpDx
[i
]= c
;
3044 if (lpResults
->lpCaretPos
&& !(dwFlags
& GCP_REORDER
))
3048 lpResults
->lpCaretPos
[0] = 0;
3049 for (i
= 1; i
< nSet
; i
++)
3050 if (GetTextExtentPoint32W(hdc
, &(lpString
[i
- 1]), 1, &size
))
3051 lpResults
->lpCaretPos
[i
] = (pos
+= size
.cx
);
3054 if(lpResults
->lpGlyphs
)
3055 GetGlyphIndicesW(hdc
, lpString
, nSet
, lpResults
->lpGlyphs
, 0);
3057 if (GetTextExtentPoint32W(hdc
, lpString
, uCount
, &size
))
3058 ret
= MAKELONG(size
.cx
, size
.cy
);
3063 /*************************************************************************
3064 * GetCharABCWidthsFloatA [GDI32.@]
3066 * See GetCharABCWidthsFloatW.
3068 BOOL WINAPI
GetCharABCWidthsFloatA( HDC hdc
, UINT first
, UINT last
, LPABCFLOAT abcf
)
3070 INT i
, wlen
, count
= (INT
)(last
- first
+ 1);
3075 if (count
<= 0) return FALSE
;
3077 str
= HeapAlloc(GetProcessHeap(), 0, count
);
3079 for(i
= 0; i
< count
; i
++)
3080 str
[i
] = (BYTE
)(first
+ i
);
3082 wstr
= FONT_mbtowc( hdc
, str
, count
, &wlen
, NULL
);
3084 for (i
= 0; i
< wlen
; i
++)
3086 if (!GetCharABCWidthsFloatW( hdc
, wstr
[i
], wstr
[i
], abcf
))
3094 HeapFree( GetProcessHeap(), 0, str
);
3095 HeapFree( GetProcessHeap(), 0, wstr
);
3100 /*************************************************************************
3101 * GetCharABCWidthsFloatW [GDI32.@]
3103 * Retrieves widths of a range of characters.
3106 * hdc [I] Handle to device context.
3107 * first [I] First character in range to query.
3108 * last [I] Last character in range to query.
3109 * abcf [O] Array of LPABCFLOAT structures.
3116 * Only works with TrueType fonts. It also doesn't return real
3117 * floats but converted integers because it's implemented on
3118 * top of GetCharABCWidthsW.
3120 BOOL WINAPI
GetCharABCWidthsFloatW( HDC hdc
, UINT first
, UINT last
, LPABCFLOAT abcf
)
3123 unsigned int i
, size
= sizeof(ABC
) * (last
- first
+ 1);
3126 TRACE("%p, %d, %d, %p - partial stub\n", hdc
, first
, last
, abcf
);
3128 abc
= HeapAlloc( GetProcessHeap(), 0, size
);
3129 if (!abc
) return FALSE
;
3131 ret
= GetCharABCWidthsW( hdc
, first
, last
, abc
);
3134 for (i
= first
; i
<= last
; i
++, abc
++, abcf
++)
3136 abcf
->abcfA
= abc
->abcA
;
3137 abcf
->abcfB
= abc
->abcB
;
3138 abcf
->abcfC
= abc
->abcC
;
3141 HeapFree( GetProcessHeap(), 0, abc
);
3145 /*************************************************************************
3146 * GetCharWidthFloatA [GDI32.@]
3148 BOOL WINAPI
GetCharWidthFloatA(HDC hdc
, UINT iFirstChar
,
3149 UINT iLastChar
, PFLOAT pxBuffer
)
3151 FIXME("%p, %u, %u, %p: stub!\n", hdc
, iFirstChar
, iLastChar
, pxBuffer
);
3155 /*************************************************************************
3156 * GetCharWidthFloatW [GDI32.@]
3158 BOOL WINAPI
GetCharWidthFloatW(HDC hdc
, UINT iFirstChar
,
3159 UINT iLastChar
, PFLOAT pxBuffer
)
3161 FIXME("%p, %u, %u, %p: stub!\n", hdc
, iFirstChar
, iLastChar
, pxBuffer
);
3166 /***********************************************************************
3168 * Font Resource API *
3170 ***********************************************************************/
3172 /***********************************************************************
3173 * AddFontResourceA (GDI32.@)
3175 INT WINAPI
AddFontResourceA( LPCSTR str
)
3177 return AddFontResourceExA( str
, 0, NULL
);
3180 /***********************************************************************
3181 * AddFontResourceW (GDI32.@)
3183 INT WINAPI
AddFontResourceW( LPCWSTR str
)
3185 return AddFontResourceExW(str
, 0, NULL
);
3189 /***********************************************************************
3190 * AddFontResourceExA (GDI32.@)
3192 INT WINAPI
AddFontResourceExA( LPCSTR str
, DWORD fl
, PVOID pdv
)
3194 DWORD len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
3195 LPWSTR strW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3198 MultiByteToWideChar(CP_ACP
, 0, str
, -1, strW
, len
);
3199 ret
= AddFontResourceExW(strW
, fl
, pdv
);
3200 HeapFree(GetProcessHeap(), 0, strW
);
3204 static BOOL CALLBACK
load_enumed_resource(HMODULE hModule
, LPCWSTR type
, LPWSTR name
, LONG_PTR lParam
)
3206 HRSRC rsrc
= FindResourceW(hModule
, name
, type
);
3207 HGLOBAL hMem
= LoadResource(hModule
, rsrc
);
3208 LPVOID
*pMem
= LockResource(hMem
);
3209 int *num_total
= (int *)lParam
;
3212 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type
));
3213 if (!AddFontMemResourceEx(pMem
, SizeofResource(hModule
, rsrc
), NULL
, &num_in_res
))
3215 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule
, hMem
);
3219 *num_total
+= num_in_res
;
3223 /***********************************************************************
3224 * AddFontResourceExW (GDI32.@)
3226 INT WINAPI
AddFontResourceExW( LPCWSTR str
, DWORD fl
, PVOID pdv
)
3228 int ret
= WineEngAddFontResourceEx(str
, fl
, pdv
);
3231 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3232 HMODULE hModule
= LoadLibraryExW(str
, NULL
, LOAD_LIBRARY_AS_DATAFILE
);
3233 if (hModule
!= NULL
)
3235 int num_resources
= 0;
3236 LPWSTR rt_font
= (LPWSTR
)((ULONG_PTR
)8); /* we don't want to include winuser.h */
3238 TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3239 wine_dbgstr_w(str
));
3240 if (EnumResourceNamesW(hModule
, rt_font
, load_enumed_resource
, (LONG_PTR
)&num_resources
))
3241 ret
= num_resources
;
3242 FreeLibrary(hModule
);
3248 /***********************************************************************
3249 * RemoveFontResourceA (GDI32.@)
3251 BOOL WINAPI
RemoveFontResourceA( LPCSTR str
)
3253 return RemoveFontResourceExA(str
, 0, 0);
3256 /***********************************************************************
3257 * RemoveFontResourceW (GDI32.@)
3259 BOOL WINAPI
RemoveFontResourceW( LPCWSTR str
)
3261 return RemoveFontResourceExW(str
, 0, 0);
3264 /***********************************************************************
3265 * AddFontMemResourceEx (GDI32.@)
3267 HANDLE WINAPI
AddFontMemResourceEx( PVOID pbFont
, DWORD cbFont
, PVOID pdv
, DWORD
*pcFonts
)
3269 return WineEngAddFontMemResourceEx(pbFont
, cbFont
, pdv
, pcFonts
);
3272 /***********************************************************************
3273 * RemoveFontResourceExA (GDI32.@)
3275 BOOL WINAPI
RemoveFontResourceExA( LPCSTR str
, DWORD fl
, PVOID pdv
)
3277 DWORD len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
3278 LPWSTR strW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3281 MultiByteToWideChar(CP_ACP
, 0, str
, -1, strW
, len
);
3282 ret
= RemoveFontResourceExW(strW
, fl
, pdv
);
3283 HeapFree(GetProcessHeap(), 0, strW
);
3287 /***********************************************************************
3288 * RemoveFontResourceExW (GDI32.@)
3290 BOOL WINAPI
RemoveFontResourceExW( LPCWSTR str
, DWORD fl
, PVOID pdv
)
3292 return WineEngRemoveFontResourceEx(str
, fl
, pdv
);
3295 /***********************************************************************
3296 * GetTextCharset (GDI32.@)
3298 UINT WINAPI
GetTextCharset(HDC hdc
)
3300 /* MSDN docs say this is equivalent */
3301 return GetTextCharsetInfo(hdc
, NULL
, 0);
3304 /***********************************************************************
3305 * GetTextCharsetInfo (GDI32.@)
3307 UINT WINAPI
GetTextCharsetInfo(HDC hdc
, LPFONTSIGNATURE fs
, DWORD flags
)
3309 UINT ret
= DEFAULT_CHARSET
;
3310 DC
*dc
= DC_GetDCPtr(hdc
);
3315 ret
= WineEngGetTextCharsetInfo(dc
->gdiFont
, fs
, flags
);
3317 DC_ReleaseDCPtr( dc
);
3320 if (ret
== DEFAULT_CHARSET
&& fs
)
3321 memset(fs
, 0, sizeof(FONTSIGNATURE
));
3325 /***********************************************************************
3326 * GdiGetCharDimensions (GDI32.@)
3328 * Gets the average width of the characters in the English alphabet.
3331 * hdc [I] Handle to the device context to measure on.
3332 * lptm [O] Pointer to memory to store the text metrics into.
3333 * height [O] On exit, the maximum height of characters in the English alphabet.
3336 * The average width of characters in the English alphabet.
3339 * This function is used by the dialog manager to get the size of a dialog
3340 * unit. It should also be used by other pieces of code that need to know
3341 * the size of a dialog unit in logical units without having access to the
3342 * window handle of the dialog.
3343 * Windows caches the font metrics from this function, but we don't and
3344 * there doesn't appear to be an immediate advantage to do so.
3347 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3349 LONG WINAPI
GdiGetCharDimensions(HDC hdc
, LPTEXTMETRICW lptm
, LONG
*height
)
3352 static const WCHAR alphabet
[] = {
3353 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3354 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3355 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3357 if(lptm
&& !GetTextMetricsW(hdc
, lptm
)) return 0;
3359 if(!GetTextExtentPointW(hdc
, alphabet
, 52, &sz
)) return 0;
3361 if (height
) *height
= sz
.cy
;
3362 return (sz
.cx
/ 26 + 1) / 2;
3365 BOOL WINAPI
EnableEUDC(BOOL fEnableEUDC
)
3367 FIXME("(%d): stub\n", fEnableEUDC
);
3371 /***********************************************************************
3372 * GetCharWidthI (GDI32.@)
3374 * Retrieve widths of characters.
3377 * hdc [I] Handle to a device context.
3378 * first [I] First glyph in range to query.
3379 * count [I] Number of glyph indices to query.
3380 * glyphs [I] Array of glyphs to query.
3381 * buffer [O] Buffer to receive character widths.
3384 * Only works with TrueType fonts.
3390 BOOL WINAPI
GetCharWidthI(HDC hdc
, UINT first
, UINT count
, LPWORD glyphs
, LPINT buffer
)
3395 TRACE("(%p, %d, %d, %p, %p)\n", hdc
, first
, count
, glyphs
, buffer
);
3397 if (!(abc
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(ABC
))))
3400 if (!GetCharABCWidthsI(hdc
, first
, count
, glyphs
, abc
))
3402 HeapFree(GetProcessHeap(), 0, abc
);
3406 for (i
= 0; i
< count
; i
++)
3407 buffer
[i
] = abc
->abcA
+ abc
->abcB
+ abc
->abcC
;
3409 HeapFree(GetProcessHeap(), 0, abc
);
3413 /***********************************************************************
3414 * GetFontUnicodeRanges (GDI32.@)
3416 * Retrieve a list of supported Unicode characters in a font.
3419 * hdc [I] Handle to a device context.
3420 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3423 * Success: Number of bytes written to the buffer pointed to by lpgs.
3427 DWORD WINAPI
GetFontUnicodeRanges(HDC hdc
, LPGLYPHSET lpgs
)
3430 DC
*dc
= DC_GetDCPtr(hdc
);
3432 TRACE("(%p, %p)\n", hdc
, lpgs
);
3436 if (dc
->gdiFont
) ret
= WineEngGetFontUnicodeRanges(dc
->gdiFont
, lpgs
);
3437 DC_ReleaseDCPtr(dc
);
3442 /*************************************************************
3443 * FontIsLinked (GDI32.@)
3445 BOOL WINAPI
FontIsLinked(HDC hdc
)
3447 DC
*dc
= DC_GetDCPtr(hdc
);
3450 if (!dc
) return FALSE
;
3451 if (dc
->gdiFont
) ret
= WineEngFontIsLinked(dc
->gdiFont
);
3452 DC_ReleaseDCPtr(dc
);
3453 TRACE("returning %d\n", ret
);