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
;
130 LPLOGFONTW lpLogFontParam
;
131 FONTENUMPROCW lpEnumFunc
;
138 * For TranslateCharsetInfo
140 #define MAXTCIINDEX 32
141 static const CHARSETINFO FONT_tci
[MAXTCIINDEX
] = {
143 { ANSI_CHARSET
, 1252, {{0,0,0,0},{FS_LATIN1
,0}} },
144 { EASTEUROPE_CHARSET
, 1250, {{0,0,0,0},{FS_LATIN2
,0}} },
145 { RUSSIAN_CHARSET
, 1251, {{0,0,0,0},{FS_CYRILLIC
,0}} },
146 { GREEK_CHARSET
, 1253, {{0,0,0,0},{FS_GREEK
,0}} },
147 { TURKISH_CHARSET
, 1254, {{0,0,0,0},{FS_TURKISH
,0}} },
148 { HEBREW_CHARSET
, 1255, {{0,0,0,0},{FS_HEBREW
,0}} },
149 { ARABIC_CHARSET
, 1256, {{0,0,0,0},{FS_ARABIC
,0}} },
150 { BALTIC_CHARSET
, 1257, {{0,0,0,0},{FS_BALTIC
,0}} },
151 { VIETNAMESE_CHARSET
, 1258, {{0,0,0,0},{FS_VIETNAMESE
,0}} },
152 /* reserved by ANSI */
153 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
154 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
155 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
156 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
157 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
158 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
159 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
161 { THAI_CHARSET
, 874, {{0,0,0,0},{FS_THAI
,0}} },
162 { SHIFTJIS_CHARSET
, 932, {{0,0,0,0},{FS_JISJAPAN
,0}} },
163 { GB2312_CHARSET
, 936, {{0,0,0,0},{FS_CHINESESIMP
,0}} },
164 { HANGEUL_CHARSET
, 949, {{0,0,0,0},{FS_WANSUNG
,0}} },
165 { CHINESEBIG5_CHARSET
, 950, {{0,0,0,0},{FS_CHINESETRAD
,0}} },
166 { JOHAB_CHARSET
, 1361, {{0,0,0,0},{FS_JOHAB
,0}} },
167 /* reserved for alternate ANSI and OEM */
168 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
169 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
170 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
171 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
172 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
173 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
174 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
175 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
176 /* reserved for system */
177 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
178 { SYMBOL_CHARSET
, CP_SYMBOL
, {{0,0,0,0},{FS_SYMBOL
,0}} }
181 /***********************************************************************
182 * LOGFONT conversion functions.
184 static void FONT_LogFontWTo16( const LOGFONTW
* font32
, LPLOGFONT16 font16
)
186 font16
->lfHeight
= font32
->lfHeight
;
187 font16
->lfWidth
= font32
->lfWidth
;
188 font16
->lfEscapement
= font32
->lfEscapement
;
189 font16
->lfOrientation
= font32
->lfOrientation
;
190 font16
->lfWeight
= font32
->lfWeight
;
191 font16
->lfItalic
= font32
->lfItalic
;
192 font16
->lfUnderline
= font32
->lfUnderline
;
193 font16
->lfStrikeOut
= font32
->lfStrikeOut
;
194 font16
->lfCharSet
= font32
->lfCharSet
;
195 font16
->lfOutPrecision
= font32
->lfOutPrecision
;
196 font16
->lfClipPrecision
= font32
->lfClipPrecision
;
197 font16
->lfQuality
= font32
->lfQuality
;
198 font16
->lfPitchAndFamily
= font32
->lfPitchAndFamily
;
199 WideCharToMultiByte( CP_ACP
, 0, font32
->lfFaceName
, -1,
200 font16
->lfFaceName
, LF_FACESIZE
, NULL
, NULL
);
201 font16
->lfFaceName
[LF_FACESIZE
-1] = 0;
204 static void FONT_LogFont16ToW( const LOGFONT16
*font16
, LPLOGFONTW font32
)
206 font32
->lfHeight
= font16
->lfHeight
;
207 font32
->lfWidth
= font16
->lfWidth
;
208 font32
->lfEscapement
= font16
->lfEscapement
;
209 font32
->lfOrientation
= font16
->lfOrientation
;
210 font32
->lfWeight
= font16
->lfWeight
;
211 font32
->lfItalic
= font16
->lfItalic
;
212 font32
->lfUnderline
= font16
->lfUnderline
;
213 font32
->lfStrikeOut
= font16
->lfStrikeOut
;
214 font32
->lfCharSet
= font16
->lfCharSet
;
215 font32
->lfOutPrecision
= font16
->lfOutPrecision
;
216 font32
->lfClipPrecision
= font16
->lfClipPrecision
;
217 font32
->lfQuality
= font16
->lfQuality
;
218 font32
->lfPitchAndFamily
= font16
->lfPitchAndFamily
;
219 MultiByteToWideChar( CP_ACP
, 0, font16
->lfFaceName
, -1, font32
->lfFaceName
, LF_FACESIZE
);
220 font32
->lfFaceName
[LF_FACESIZE
-1] = 0;
223 static void FONT_LogFontAToW( const LOGFONTA
*fontA
, LPLOGFONTW fontW
)
225 memcpy(fontW
, fontA
, sizeof(LOGFONTA
) - LF_FACESIZE
);
226 MultiByteToWideChar(CP_ACP
, 0, fontA
->lfFaceName
, -1, fontW
->lfFaceName
,
228 fontW
->lfFaceName
[LF_FACESIZE
-1] = 0;
231 static void FONT_LogFontWToA( const LOGFONTW
*fontW
, LPLOGFONTA fontA
)
233 memcpy(fontA
, fontW
, sizeof(LOGFONTA
) - LF_FACESIZE
);
234 WideCharToMultiByte(CP_ACP
, 0, fontW
->lfFaceName
, -1, fontA
->lfFaceName
,
235 LF_FACESIZE
, NULL
, NULL
);
236 fontA
->lfFaceName
[LF_FACESIZE
-1] = 0;
239 static void FONT_EnumLogFontExWTo16( const ENUMLOGFONTEXW
*fontW
, LPENUMLOGFONTEX16 font16
)
241 FONT_LogFontWTo16( (const LOGFONTW
*)fontW
, (LPLOGFONT16
)font16
);
243 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfFullName
, -1,
244 (LPSTR
) font16
->elfFullName
, LF_FULLFACESIZE
, NULL
, NULL
);
245 font16
->elfFullName
[LF_FULLFACESIZE
-1] = '\0';
246 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfStyle
, -1,
247 (LPSTR
) font16
->elfStyle
, LF_FACESIZE
, NULL
, NULL
);
248 font16
->elfStyle
[LF_FACESIZE
-1] = '\0';
249 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfScript
, -1,
250 (LPSTR
) font16
->elfScript
, LF_FACESIZE
, NULL
, NULL
);
251 font16
->elfScript
[LF_FACESIZE
-1] = '\0';
254 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW
*fontW
, LPENUMLOGFONTEXA fontA
)
256 FONT_LogFontWToA( (const LOGFONTW
*)fontW
, (LPLOGFONTA
)fontA
);
258 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfFullName
, -1,
259 (LPSTR
) fontA
->elfFullName
, LF_FULLFACESIZE
, NULL
, NULL
);
260 fontA
->elfFullName
[LF_FULLFACESIZE
-1] = '\0';
261 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfStyle
, -1,
262 (LPSTR
) fontA
->elfStyle
, LF_FACESIZE
, NULL
, NULL
);
263 fontA
->elfStyle
[LF_FACESIZE
-1] = '\0';
264 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfScript
, -1,
265 (LPSTR
) fontA
->elfScript
, LF_FACESIZE
, NULL
, NULL
);
266 fontA
->elfScript
[LF_FACESIZE
-1] = '\0';
269 /***********************************************************************
270 * TEXTMETRIC conversion functions.
272 static void FONT_TextMetricWToA(const TEXTMETRICW
*ptmW
, LPTEXTMETRICA ptmA
)
274 ptmA
->tmHeight
= ptmW
->tmHeight
;
275 ptmA
->tmAscent
= ptmW
->tmAscent
;
276 ptmA
->tmDescent
= ptmW
->tmDescent
;
277 ptmA
->tmInternalLeading
= ptmW
->tmInternalLeading
;
278 ptmA
->tmExternalLeading
= ptmW
->tmExternalLeading
;
279 ptmA
->tmAveCharWidth
= ptmW
->tmAveCharWidth
;
280 ptmA
->tmMaxCharWidth
= ptmW
->tmMaxCharWidth
;
281 ptmA
->tmWeight
= ptmW
->tmWeight
;
282 ptmA
->tmOverhang
= ptmW
->tmOverhang
;
283 ptmA
->tmDigitizedAspectX
= ptmW
->tmDigitizedAspectX
;
284 ptmA
->tmDigitizedAspectY
= ptmW
->tmDigitizedAspectY
;
285 ptmA
->tmFirstChar
= min(ptmW
->tmFirstChar
, 255);
286 if (ptmW
->tmCharSet
== SYMBOL_CHARSET
)
288 UINT last_char
= ptmW
->tmLastChar
;
289 if (last_char
> 0xf000) last_char
-= 0xf000;
290 ptmA
->tmLastChar
= min(last_char
, 255);
293 ptmA
->tmLastChar
= min(ptmW
->tmLastChar
, 255);
294 ptmA
->tmDefaultChar
= min(ptmW
->tmDefaultChar
, 255);
295 ptmA
->tmBreakChar
= min(ptmW
->tmBreakChar
, 255);
296 ptmA
->tmItalic
= ptmW
->tmItalic
;
297 ptmA
->tmUnderlined
= ptmW
->tmUnderlined
;
298 ptmA
->tmStruckOut
= ptmW
->tmStruckOut
;
299 ptmA
->tmPitchAndFamily
= ptmW
->tmPitchAndFamily
;
300 ptmA
->tmCharSet
= ptmW
->tmCharSet
;
304 static void FONT_NewTextMetricExWTo16(const NEWTEXTMETRICEXW
*ptmW
, LPNEWTEXTMETRICEX16 ptm16
)
306 ptm16
->ntmTm
.tmHeight
= ptmW
->ntmTm
.tmHeight
;
307 ptm16
->ntmTm
.tmAscent
= ptmW
->ntmTm
.tmAscent
;
308 ptm16
->ntmTm
.tmDescent
= ptmW
->ntmTm
.tmDescent
;
309 ptm16
->ntmTm
.tmInternalLeading
= ptmW
->ntmTm
.tmInternalLeading
;
310 ptm16
->ntmTm
.tmExternalLeading
= ptmW
->ntmTm
.tmExternalLeading
;
311 ptm16
->ntmTm
.tmAveCharWidth
= ptmW
->ntmTm
.tmAveCharWidth
;
312 ptm16
->ntmTm
.tmMaxCharWidth
= ptmW
->ntmTm
.tmMaxCharWidth
;
313 ptm16
->ntmTm
.tmWeight
= ptmW
->ntmTm
.tmWeight
;
314 ptm16
->ntmTm
.tmOverhang
= ptmW
->ntmTm
.tmOverhang
;
315 ptm16
->ntmTm
.tmDigitizedAspectX
= ptmW
->ntmTm
.tmDigitizedAspectX
;
316 ptm16
->ntmTm
.tmDigitizedAspectY
= ptmW
->ntmTm
.tmDigitizedAspectY
;
317 ptm16
->ntmTm
.tmFirstChar
= ptmW
->ntmTm
.tmFirstChar
> 255 ? 255 : ptmW
->ntmTm
.tmFirstChar
;
318 ptm16
->ntmTm
.tmLastChar
= ptmW
->ntmTm
.tmLastChar
> 255 ? 255 : ptmW
->ntmTm
.tmLastChar
;
319 ptm16
->ntmTm
.tmDefaultChar
= ptmW
->ntmTm
.tmDefaultChar
> 255 ? 255 : ptmW
->ntmTm
.tmDefaultChar
;
320 ptm16
->ntmTm
.tmBreakChar
= ptmW
->ntmTm
.tmBreakChar
> 255 ? 255 : ptmW
->ntmTm
.tmBreakChar
;
321 ptm16
->ntmTm
.tmItalic
= ptmW
->ntmTm
.tmItalic
;
322 ptm16
->ntmTm
.tmUnderlined
= ptmW
->ntmTm
.tmUnderlined
;
323 ptm16
->ntmTm
.tmStruckOut
= ptmW
->ntmTm
.tmStruckOut
;
324 ptm16
->ntmTm
.tmPitchAndFamily
= ptmW
->ntmTm
.tmPitchAndFamily
;
325 ptm16
->ntmTm
.tmCharSet
= ptmW
->ntmTm
.tmCharSet
;
326 ptm16
->ntmTm
.ntmFlags
= ptmW
->ntmTm
.ntmFlags
;
327 ptm16
->ntmTm
.ntmSizeEM
= ptmW
->ntmTm
.ntmSizeEM
;
328 ptm16
->ntmTm
.ntmCellHeight
= ptmW
->ntmTm
.ntmCellHeight
;
329 ptm16
->ntmTm
.ntmAvgWidth
= ptmW
->ntmTm
.ntmAvgWidth
;
330 memcpy(&ptm16
->ntmFontSig
, &ptmW
->ntmFontSig
, sizeof(FONTSIGNATURE
));
333 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW
*ptmW
, NEWTEXTMETRICEXA
*ptmA
)
335 FONT_TextMetricWToA((const TEXTMETRICW
*)ptmW
, (LPTEXTMETRICA
)ptmA
);
336 ptmA
->ntmTm
.ntmFlags
= ptmW
->ntmTm
.ntmFlags
;
337 ptmA
->ntmTm
.ntmSizeEM
= ptmW
->ntmTm
.ntmSizeEM
;
338 ptmA
->ntmTm
.ntmCellHeight
= ptmW
->ntmTm
.ntmCellHeight
;
339 ptmA
->ntmTm
.ntmAvgWidth
= ptmW
->ntmTm
.ntmAvgWidth
;
340 memcpy(&ptmA
->ntmFontSig
, &ptmW
->ntmFontSig
, sizeof(FONTSIGNATURE
));
344 /***********************************************************************
345 * GdiGetCodePage (GDI32.@)
347 DWORD WINAPI
GdiGetCodePage( HDC hdc
)
351 int charset
= GetTextCharset(hdc
);
353 /* Hmm, nicely designed api this one! */
354 if(TranslateCharsetInfo(ULongToPtr(charset
), &csi
, TCI_SRCCHARSET
))
361 case DEFAULT_CHARSET
:
372 /* FIXME: These have no place here, but because x11drv
373 enumerates fonts with these (made up) charsets some apps
374 might use them and then the FIXME below would become
375 annoying. Now we could pick the intended codepage for
376 each of these, but since it's broken anyway we'll just
377 use CP_ACP and hope it'll go away...
383 FIXME("Can't find codepage for charset %d\n", charset
);
388 TRACE("charset %d => cp %d\n", charset
, cp
);
392 /***********************************************************************
395 * Returns a Unicode translation of str using the charset of the
396 * currently selected font in hdc. If count is -1 then str is assumed
397 * to be '\0' terminated, otherwise it contains the number of bytes to
398 * convert. If plenW is non-NULL, on return it will point to the
399 * number of WCHARs that have been written. If pCP is non-NULL, on
400 * return it will point to the codepage used in the conversion. The
401 * caller should free the returned LPWSTR from the process heap
404 static LPWSTR
FONT_mbtowc(HDC hdc
, LPCSTR str
, INT count
, INT
*plenW
, UINT
*pCP
)
410 cp
= GdiGetCodePage( hdc
);
412 if(count
== -1) count
= strlen(str
);
413 lenW
= MultiByteToWideChar(cp
, 0, str
, count
, NULL
, 0);
414 strW
= HeapAlloc(GetProcessHeap(), 0, lenW
*sizeof(WCHAR
));
415 MultiByteToWideChar(cp
, 0, str
, count
, strW
, lenW
);
416 TRACE("mapped %s -> %s\n", debugstr_an(str
, count
), debugstr_wn(strW
, lenW
));
417 if(plenW
) *plenW
= lenW
;
423 /***********************************************************************
424 * CreateFontIndirectA (GDI32.@)
426 HFONT WINAPI
CreateFontIndirectA( const LOGFONTA
*plfA
)
432 FONT_LogFontAToW( plfA
, &lfW
);
433 return CreateFontIndirectW( &lfW
);
436 /***********************************************************************
437 * CreateFontIndirectW (GDI32.@)
439 HFONT WINAPI
CreateFontIndirectW( const LOGFONTW
*plf
)
441 static const WCHAR ItalicW
[] = {' ','I','t','a','l','i','c','\0'};
442 static const WCHAR BoldW
[] = {' ','B','o','l','d','\0'};
443 WCHAR
*pFaceNameItalicSuffix
, *pFaceNameBoldSuffix
;
444 WCHAR
*pFaceNameSuffix
= NULL
;
450 if (!(fontPtr
= GDI_AllocObject( sizeof(FONTOBJ
), FONT_MAGIC
, (HGDIOBJ
*)&hFont
,
451 &font_funcs
))) return 0;
453 memcpy( &fontPtr
->logfont
, plf
, sizeof(LOGFONTW
) );
455 TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
456 plf
->lfHeight
, plf
->lfWidth
,
457 plf
->lfEscapement
, plf
->lfOrientation
,
458 plf
->lfPitchAndFamily
,
459 plf
->lfOutPrecision
, plf
->lfClipPrecision
,
460 plf
->lfQuality
, plf
->lfCharSet
,
461 debugstr_w(plf
->lfFaceName
),
462 plf
->lfWeight
> 400 ? "Bold" : "",
463 plf
->lfItalic
? "Italic" : "",
464 plf
->lfUnderline
? "Underline" : "", hFont
);
466 if (plf
->lfEscapement
!= plf
->lfOrientation
)
468 /* this should really depend on whether GM_ADVANCED is set */
469 fontPtr
->logfont
.lfOrientation
= fontPtr
->logfont
.lfEscapement
;
470 WARN("orientation angle %f set to "
471 "escapement angle %f for new font %p\n",
472 plf
->lfOrientation
/10., plf
->lfEscapement
/10., hFont
);
475 pFaceNameItalicSuffix
= strstrW(fontPtr
->logfont
.lfFaceName
, ItalicW
);
476 if (pFaceNameItalicSuffix
)
478 fontPtr
->logfont
.lfItalic
= TRUE
;
479 pFaceNameSuffix
= pFaceNameItalicSuffix
;
482 pFaceNameBoldSuffix
= strstrW(fontPtr
->logfont
.lfFaceName
, BoldW
);
483 if (pFaceNameBoldSuffix
)
485 if (fontPtr
->logfont
.lfWeight
< FW_BOLD
)
486 fontPtr
->logfont
.lfWeight
= FW_BOLD
;
487 if (!pFaceNameSuffix
|| (pFaceNameBoldSuffix
< pFaceNameSuffix
))
488 pFaceNameSuffix
= pFaceNameBoldSuffix
;
491 if (pFaceNameSuffix
) *pFaceNameSuffix
= 0;
493 GDI_ReleaseObj( hFont
);
497 /*************************************************************************
498 * CreateFontA (GDI32.@)
500 HFONT WINAPI
CreateFontA( INT height
, INT width
, INT esc
,
501 INT orient
, INT weight
, DWORD italic
,
502 DWORD underline
, DWORD strikeout
, DWORD charset
,
503 DWORD outpres
, DWORD clippres
, DWORD quality
,
504 DWORD pitch
, LPCSTR name
)
508 logfont
.lfHeight
= height
;
509 logfont
.lfWidth
= width
;
510 logfont
.lfEscapement
= esc
;
511 logfont
.lfOrientation
= orient
;
512 logfont
.lfWeight
= weight
;
513 logfont
.lfItalic
= italic
;
514 logfont
.lfUnderline
= underline
;
515 logfont
.lfStrikeOut
= strikeout
;
516 logfont
.lfCharSet
= charset
;
517 logfont
.lfOutPrecision
= outpres
;
518 logfont
.lfClipPrecision
= clippres
;
519 logfont
.lfQuality
= quality
;
520 logfont
.lfPitchAndFamily
= pitch
;
523 lstrcpynA(logfont
.lfFaceName
,name
,sizeof(logfont
.lfFaceName
));
525 logfont
.lfFaceName
[0] = '\0';
527 return CreateFontIndirectA( &logfont
);
530 /*************************************************************************
531 * CreateFontW (GDI32.@)
533 HFONT WINAPI
CreateFontW( INT height
, INT width
, INT esc
,
534 INT orient
, INT weight
, DWORD italic
,
535 DWORD underline
, DWORD strikeout
, DWORD charset
,
536 DWORD outpres
, DWORD clippres
, DWORD quality
,
537 DWORD pitch
, LPCWSTR name
)
541 logfont
.lfHeight
= height
;
542 logfont
.lfWidth
= width
;
543 logfont
.lfEscapement
= esc
;
544 logfont
.lfOrientation
= orient
;
545 logfont
.lfWeight
= weight
;
546 logfont
.lfItalic
= italic
;
547 logfont
.lfUnderline
= underline
;
548 logfont
.lfStrikeOut
= strikeout
;
549 logfont
.lfCharSet
= charset
;
550 logfont
.lfOutPrecision
= outpres
;
551 logfont
.lfClipPrecision
= clippres
;
552 logfont
.lfQuality
= quality
;
553 logfont
.lfPitchAndFamily
= pitch
;
556 lstrcpynW(logfont
.lfFaceName
, name
,
557 sizeof(logfont
.lfFaceName
) / sizeof(WCHAR
));
559 logfont
.lfFaceName
[0] = '\0';
561 return CreateFontIndirectW( &logfont
);
565 /***********************************************************************
568 * If the driver supports vector fonts we create a gdi font first and
569 * then call the driver to give it a chance to supply its own device
570 * font. If the driver wants to do this it returns TRUE and we can
571 * delete the gdi font, if the driver wants to use the gdi font it
572 * should return FALSE, to signal an error return GDI_ERROR. For
573 * drivers that don't support vector fonts they must supply their own
576 static HGDIOBJ
FONT_SelectObject( HGDIOBJ handle
, HDC hdc
)
579 DC
*dc
= get_dc_ptr( hdc
);
583 if (!GDI_inc_ref_count( handle
))
585 release_dc_ptr( dc
);
589 if (dc
->hFont
!= handle
|| dc
->gdiFont
== NULL
)
591 if(GetDeviceCaps(dc
->hSelf
, TEXTCAPS
) & TC_VA_ABLE
)
593 FONTOBJ
*font
= GDI_GetObjPtr( handle
, FONT_MAGIC
); /* to grab the GDI lock (FIXME) */
594 dc
->gdiFont
= WineEngCreateFontInstance(dc
, handle
);
595 if (font
) GDI_ReleaseObj( handle
);
599 if (dc
->funcs
->pSelectFont
) ret
= dc
->funcs
->pSelectFont( dc
->physDev
, handle
, dc
->gdiFont
);
601 if (ret
&& dc
->gdiFont
) dc
->gdiFont
= 0;
603 if (ret
== HGDI_ERROR
)
605 GDI_dec_ref_count( handle
);
606 ret
= 0; /* SelectObject returns 0 on error */
612 GDI_dec_ref_count( ret
);
614 release_dc_ptr( dc
);
619 /***********************************************************************
622 static INT
FONT_GetObject16( HGDIOBJ handle
, void *obj
, INT count
, LPVOID buffer
)
627 FONT_LogFontWTo16( &font
->logfont
, &lf16
);
629 if (count
> sizeof(LOGFONT16
)) count
= sizeof(LOGFONT16
);
630 memcpy( buffer
, &lf16
, count
);
634 /***********************************************************************
637 static INT
FONT_GetObjectA( HGDIOBJ handle
, void *obj
, INT count
, LPVOID buffer
)
644 FONT_LogFontWToA( &font
->logfont
, &lfA
);
646 if (count
> sizeof(lfA
)) count
= sizeof(lfA
);
647 memcpy( buffer
, &lfA
, count
);
651 /***********************************************************************
654 static INT
FONT_GetObjectW( HGDIOBJ handle
, void *obj
, INT count
, LPVOID buffer
)
658 return sizeof(LOGFONTW
);
659 if (count
> sizeof(LOGFONTW
)) count
= sizeof(LOGFONTW
);
660 memcpy( buffer
, &font
->logfont
, count
);
665 /***********************************************************************
668 static BOOL
FONT_DeleteObject( HGDIOBJ handle
, void *obj
)
670 WineEngDestroyFontInstance( handle
);
671 return GDI_FreeObject( handle
, obj
);
675 /***********************************************************************
676 * FONT_EnumInstance16
678 * Called by the device driver layer to pass font info
679 * down to the application.
681 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
682 * We have to use other types because of the FONTENUMPROCW definition.
684 static INT CALLBACK
FONT_EnumInstance16( const LOGFONTW
*plf
, const TEXTMETRICW
*ptm
,
685 DWORD fType
, LPARAM lp
)
687 fontEnum16
*pfe
= (fontEnum16
*)lp
;
690 if (!pfe
->lpLogFontParam
||
691 pfe
->lpLogFontParam
->lfCharSet
== DEFAULT_CHARSET
||
692 pfe
->lpLogFontParam
->lfCharSet
== plf
->lfCharSet
)
697 FONT_EnumLogFontExWTo16((const ENUMLOGFONTEXW
*)plf
, pfe
->lpLogFont
);
698 FONT_NewTextMetricExWTo16((const NEWTEXTMETRICEXW
*)ptm
, pfe
->lpTextMetric
);
699 pfe
->dwFlags
|= ENUM_CALLED
;
701 args
[6] = SELECTOROF(pfe
->segLogFont
);
702 args
[5] = OFFSETOF(pfe
->segLogFont
);
703 args
[4] = SELECTOROF(pfe
->segTextMetric
);
704 args
[3] = OFFSETOF(pfe
->segTextMetric
);
706 args
[1] = HIWORD(pfe
->lpData
);
707 args
[0] = LOWORD(pfe
->lpData
);
708 WOWCallback16Ex( (DWORD
)pfe
->lpEnumFunc
, WCB16_PASCAL
, sizeof(args
), args
, &result
);
709 ret
= LOWORD(result
);
714 /***********************************************************************
717 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
718 * We have to use other types because of the FONTENUMPROCW definition.
720 static INT CALLBACK
FONT_EnumInstance( const LOGFONTW
*plf
, const TEXTMETRICW
*ptm
,
721 DWORD fType
, LPARAM lp
)
723 fontEnum32
*pfe
= (fontEnum32
*)lp
;
726 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
727 if ((!pfe
->lpLogFontParam
||
728 pfe
->lpLogFontParam
->lfCharSet
== DEFAULT_CHARSET
||
729 pfe
->lpLogFontParam
->lfCharSet
== plf
->lfCharSet
) &&
730 (!(fType
& RASTER_FONTTYPE
) || GetDeviceCaps(pfe
->hdc
, TEXTCAPS
) & TC_RA_ABLE
) )
732 /* convert font metrics */
733 ENUMLOGFONTEXA logfont
;
734 NEWTEXTMETRICEXA tmA
;
736 pfe
->dwFlags
|= ENUM_CALLED
;
737 if (!(pfe
->dwFlags
& ENUM_UNICODE
))
739 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW
*)plf
, &logfont
);
740 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW
*)ptm
, &tmA
);
741 plf
= (LOGFONTW
*)&logfont
.elfLogFont
;
742 ptm
= (TEXTMETRICW
*)&tmA
;
745 ret
= pfe
->lpEnumFunc( plf
, ptm
, fType
, pfe
->lpData
);
750 /***********************************************************************
751 * EnumFontFamiliesEx (GDI.613)
753 INT16 WINAPI
EnumFontFamiliesEx16( HDC16 hDC
, LPLOGFONT16 plf
,
754 FONTENUMPROC16 efproc
, LPARAM lParam
,
759 DC
* dc
= get_dc_ptr( HDC_32(hDC
) );
760 NEWTEXTMETRICEX16 tm16
;
761 ENUMLOGFONTEX16 lf16
;
769 FONT_LogFont16ToW(plf
, &lfW
);
774 fe16
.hdc
= HDC_32(hDC
);
775 fe16
.lpLogFontParam
= plf
;
776 fe16
.lpEnumFunc
= efproc
;
777 fe16
.lpData
= lParam
;
778 fe16
.lpTextMetric
= &tm16
;
779 fe16
.lpLogFont
= &lf16
;
780 fe16
.segTextMetric
= MapLS( &tm16
);
781 fe16
.segLogFont
= MapLS( &lf16
);
784 enum_gdi_fonts
= GetDeviceCaps(fe16
.hdc
, TEXTCAPS
) & TC_VA_ABLE
;
786 if (!dc
->funcs
->pEnumDeviceFonts
&& !enum_gdi_fonts
)
793 ret
= WineEngEnumFonts( plfW
, FONT_EnumInstance16
, (LPARAM
)&fe16
);
794 fe16
.dwFlags
&= ~ENUM_CALLED
;
795 if (ret
&& dc
->funcs
->pEnumDeviceFonts
) {
796 ret2
= dc
->funcs
->pEnumDeviceFonts( dc
->physDev
, plfW
, FONT_EnumInstance16
, (LPARAM
)&fe16
);
797 if(fe16
.dwFlags
& ENUM_CALLED
) /* update ret iff a font gets enumed */
801 UnMapLS( fe16
.segTextMetric
);
802 UnMapLS( fe16
.segLogFont
);
803 release_dc_ptr( dc
);
807 /***********************************************************************
808 * FONT_EnumFontFamiliesEx
810 static INT
FONT_EnumFontFamiliesEx( HDC hDC
, LPLOGFONTW plf
,
811 FONTENUMPROCW efproc
,
812 LPARAM lParam
, DWORD dwUnicode
)
815 DC
*dc
= get_dc_ptr( hDC
);
822 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf
->lfFaceName
),
824 fe32
.lpLogFontParam
= plf
;
825 fe32
.lpEnumFunc
= efproc
;
826 fe32
.lpData
= lParam
;
827 fe32
.dwFlags
= dwUnicode
;
830 enum_gdi_fonts
= GetDeviceCaps(hDC
, TEXTCAPS
) & TC_VA_ABLE
;
832 if (!dc
->funcs
->pEnumDeviceFonts
&& !enum_gdi_fonts
)
839 ret
= WineEngEnumFonts( plf
, FONT_EnumInstance
, (LPARAM
)&fe32
);
840 fe32
.dwFlags
&= ~ENUM_CALLED
;
841 if (ret
&& dc
->funcs
->pEnumDeviceFonts
) {
842 ret2
= dc
->funcs
->pEnumDeviceFonts( dc
->physDev
, plf
, FONT_EnumInstance
, (LPARAM
)&fe32
);
843 if(fe32
.dwFlags
& ENUM_CALLED
) /* update ret iff a font gets enumed */
847 release_dc_ptr( dc
);
851 /***********************************************************************
852 * EnumFontFamiliesExW (GDI32.@)
854 INT WINAPI
EnumFontFamiliesExW( HDC hDC
, LPLOGFONTW plf
,
855 FONTENUMPROCW efproc
,
856 LPARAM lParam
, DWORD dwFlags
)
858 return FONT_EnumFontFamiliesEx( hDC
, plf
, efproc
, lParam
, ENUM_UNICODE
);
861 /***********************************************************************
862 * EnumFontFamiliesExA (GDI32.@)
864 INT WINAPI
EnumFontFamiliesExA( HDC hDC
, LPLOGFONTA plf
,
865 FONTENUMPROCA efproc
,
866 LPARAM lParam
, DWORD dwFlags
)
872 FONT_LogFontAToW( plf
, &lfW
);
877 return FONT_EnumFontFamiliesEx( hDC
, plfW
, (FONTENUMPROCW
)efproc
, lParam
, 0);
880 /***********************************************************************
881 * EnumFontFamilies (GDI.330)
883 INT16 WINAPI
EnumFontFamilies16( HDC16 hDC
, LPCSTR lpFamily
,
884 FONTENUMPROC16 efproc
, LPARAM lpData
)
890 if (!*lpFamily
) return 1;
891 lstrcpynA( lf
.lfFaceName
, lpFamily
, LF_FACESIZE
);
892 lf
.lfCharSet
= DEFAULT_CHARSET
;
893 lf
.lfPitchAndFamily
= 0;
898 return EnumFontFamiliesEx16( hDC
, plf
, efproc
, lpData
, 0 );
901 /***********************************************************************
902 * EnumFontFamiliesA (GDI32.@)
904 INT WINAPI
EnumFontFamiliesA( HDC hDC
, LPCSTR lpFamily
,
905 FONTENUMPROCA efproc
, LPARAM lpData
)
911 if (!*lpFamily
) return 1;
912 lstrcpynA( lf
.lfFaceName
, lpFamily
, LF_FACESIZE
);
913 lf
.lfCharSet
= DEFAULT_CHARSET
;
914 lf
.lfPitchAndFamily
= 0;
919 return EnumFontFamiliesExA( hDC
, plf
, efproc
, lpData
, 0 );
922 /***********************************************************************
923 * EnumFontFamiliesW (GDI32.@)
925 INT WINAPI
EnumFontFamiliesW( HDC hDC
, LPCWSTR lpFamily
,
926 FONTENUMPROCW efproc
, LPARAM lpData
)
932 if (!*lpFamily
) return 1;
933 lstrcpynW( lf
.lfFaceName
, lpFamily
, LF_FACESIZE
);
934 lf
.lfCharSet
= DEFAULT_CHARSET
;
935 lf
.lfPitchAndFamily
= 0;
940 return EnumFontFamiliesExW( hDC
, plf
, efproc
, lpData
, 0 );
943 /***********************************************************************
946 INT16 WINAPI
EnumFonts16( HDC16 hDC
, LPCSTR lpName
, FONTENUMPROC16 efproc
,
949 return EnumFontFamilies16( hDC
, lpName
, efproc
, lpData
);
952 /***********************************************************************
953 * EnumFontsA (GDI32.@)
955 INT WINAPI
EnumFontsA( HDC hDC
, LPCSTR lpName
, FONTENUMPROCA efproc
,
958 return EnumFontFamiliesA( hDC
, lpName
, efproc
, lpData
);
961 /***********************************************************************
962 * EnumFontsW (GDI32.@)
964 INT WINAPI
EnumFontsW( HDC hDC
, LPCWSTR lpName
, FONTENUMPROCW efproc
,
967 return EnumFontFamiliesW( hDC
, lpName
, efproc
, lpData
);
971 /***********************************************************************
972 * GetTextCharacterExtra (GDI32.@)
974 INT WINAPI
GetTextCharacterExtra( HDC hdc
)
977 DC
*dc
= get_dc_ptr( hdc
);
978 if (!dc
) return 0x80000000;
980 release_dc_ptr( dc
);
985 /***********************************************************************
986 * SetTextCharacterExtra (GDI32.@)
988 INT WINAPI
SetTextCharacterExtra( HDC hdc
, INT extra
)
991 DC
* dc
= get_dc_ptr( hdc
);
992 if (!dc
) return 0x80000000;
993 if (dc
->funcs
->pSetTextCharacterExtra
)
994 prev
= dc
->funcs
->pSetTextCharacterExtra( dc
->physDev
, extra
);
997 prev
= dc
->charExtra
;
998 dc
->charExtra
= extra
;
1000 release_dc_ptr( dc
);
1005 /***********************************************************************
1006 * SetTextJustification (GDI32.@)
1008 BOOL WINAPI
SetTextJustification( HDC hdc
, INT extra
, INT breaks
)
1011 DC
* dc
= get_dc_ptr( hdc
);
1012 if (!dc
) return FALSE
;
1013 if (dc
->funcs
->pSetTextJustification
)
1014 ret
= dc
->funcs
->pSetTextJustification( dc
->physDev
, extra
, breaks
);
1017 extra
= abs((extra
* dc
->vportExtX
+ dc
->wndExtX
/ 2) / dc
->wndExtX
);
1018 if (!extra
) breaks
= 0;
1021 dc
->breakExtra
= extra
/ breaks
;
1022 dc
->breakRem
= extra
- (breaks
* dc
->breakExtra
);
1030 release_dc_ptr( dc
);
1035 /***********************************************************************
1036 * GetTextFaceA (GDI32.@)
1038 INT WINAPI
GetTextFaceA( HDC hdc
, INT count
, LPSTR name
)
1040 INT res
= GetTextFaceW(hdc
, 0, NULL
);
1041 LPWSTR nameW
= HeapAlloc( GetProcessHeap(), 0, res
* 2 );
1042 GetTextFaceW( hdc
, res
, nameW
);
1046 if (count
&& !WideCharToMultiByte( CP_ACP
, 0, nameW
, -1, name
, count
, NULL
, NULL
))
1051 res
= WideCharToMultiByte( CP_ACP
, 0, nameW
, -1, NULL
, 0, NULL
, NULL
);
1052 HeapFree( GetProcessHeap(), 0, nameW
);
1056 /***********************************************************************
1057 * GetTextFaceW (GDI32.@)
1059 INT WINAPI
GetTextFaceW( HDC hdc
, INT count
, LPWSTR name
)
1064 DC
* dc
= get_dc_ptr( hdc
);
1068 ret
= WineEngGetTextFace(dc
->gdiFont
, count
, name
);
1069 else if ((font
= (FONTOBJ
*) GDI_GetObjPtr( dc
->hFont
, FONT_MAGIC
)))
1073 lstrcpynW( name
, font
->logfont
.lfFaceName
, count
);
1074 ret
= strlenW(name
);
1076 else ret
= strlenW(font
->logfont
.lfFaceName
) + 1;
1077 GDI_ReleaseObj( dc
->hFont
);
1079 release_dc_ptr( dc
);
1084 /***********************************************************************
1085 * GetTextExtentPoint32A (GDI32.@)
1087 * See GetTextExtentPoint32W.
1089 BOOL WINAPI
GetTextExtentPoint32A( HDC hdc
, LPCSTR str
, INT count
,
1094 LPWSTR p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
1097 ret
= GetTextExtentPoint32W( hdc
, p
, wlen
, size
);
1098 HeapFree( GetProcessHeap(), 0, p
);
1101 TRACE("(%p %s %d %p): returning %d x %d\n",
1102 hdc
, debugstr_an (str
, count
), count
, size
, size
->cx
, size
->cy
);
1107 /***********************************************************************
1108 * GetTextExtentPoint32W [GDI32.@]
1110 * Computes width/height for a string.
1112 * Computes width and height of the specified string.
1118 BOOL WINAPI
GetTextExtentPoint32W(
1119 HDC hdc
, /* [in] Handle of device context */
1120 LPCWSTR str
, /* [in] Address of text string */
1121 INT count
, /* [in] Number of characters in string */
1122 LPSIZE size
) /* [out] Address of structure for string size */
1124 return GetTextExtentExPointW(hdc
, str
, count
, 0, NULL
, NULL
, size
);
1127 /***********************************************************************
1128 * GetTextExtentExPointI [GDI32.@]
1130 * Computes width and height of the array of glyph indices.
1133 * hdc [I] Handle of device context.
1134 * indices [I] Glyph index array.
1135 * count [I] Number of glyphs in array.
1136 * max_ext [I] Maximum width in glyphs.
1137 * nfit [O] Maximum number of characters.
1138 * dxs [O] Partial string widths.
1139 * size [O] Returned string size.
1145 BOOL WINAPI
GetTextExtentExPointI( HDC hdc
, const WORD
*indices
, INT count
, INT max_ext
,
1146 LPINT nfit
, LPINT dxs
, LPSIZE size
)
1149 DC
* dc
= get_dc_ptr( hdc
);
1150 if (!dc
) return FALSE
;
1153 ret
= WineEngGetTextExtentExPointI(dc
->gdiFont
, indices
, count
, max_ext
, nfit
, dxs
, size
);
1154 size
->cx
= abs(INTERNAL_XDSTOWS(dc
, size
->cx
));
1155 size
->cy
= abs(INTERNAL_YDSTOWS(dc
, size
->cy
));
1156 size
->cx
+= count
* dc
->charExtra
;
1158 else if(dc
->funcs
->pGetTextExtentExPoint
) {
1159 FIXME("calling GetTextExtentExPoint\n");
1160 ret
= dc
->funcs
->pGetTextExtentExPoint( dc
->physDev
, (LPCWSTR
)indices
,
1161 count
, max_ext
, nfit
, dxs
, size
);
1164 release_dc_ptr( dc
);
1166 TRACE("(%p %p %d %p): returning %d x %d\n",
1167 hdc
, indices
, count
, size
, size
->cx
, size
->cy
);
1171 /***********************************************************************
1172 * GetTextExtentPointI [GDI32.@]
1174 * Computes width and height of the array of glyph indices.
1177 * hdc [I] Handle of device context.
1178 * indices [I] Glyph index array.
1179 * count [I] Number of glyphs in array.
1180 * size [O] Returned string size.
1186 BOOL WINAPI
GetTextExtentPointI( HDC hdc
, const WORD
*indices
, INT count
, LPSIZE size
)
1188 return GetTextExtentExPointI( hdc
, indices
, count
, 0, NULL
, NULL
, size
);
1192 /***********************************************************************
1193 * GetTextExtentPointA (GDI32.@)
1195 BOOL WINAPI
GetTextExtentPointA( HDC hdc
, LPCSTR str
, INT count
,
1198 TRACE("not bug compatible.\n");
1199 return GetTextExtentPoint32A( hdc
, str
, count
, size
);
1202 /***********************************************************************
1203 * GetTextExtentPointW (GDI32.@)
1205 BOOL WINAPI
GetTextExtentPointW( HDC hdc
, LPCWSTR str
, INT count
,
1208 TRACE("not bug compatible.\n");
1209 return GetTextExtentPoint32W( hdc
, str
, count
, size
);
1213 /***********************************************************************
1214 * GetTextExtentExPointA (GDI32.@)
1216 BOOL WINAPI
GetTextExtentExPointA( HDC hdc
, LPCSTR str
, INT count
,
1217 INT maxExt
, LPINT lpnFit
,
1218 LPINT alpDx
, LPSIZE size
)
1226 NULL
== (walpDx
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(INT
))))
1229 p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
1230 ret
= GetTextExtentExPointW( hdc
, p
, wlen
, maxExt
, lpnFit
, walpDx
, size
);
1233 INT n
= lpnFit
? *lpnFit
: wlen
;
1235 for(i
= 0, j
= 0; i
< n
; i
++, j
++)
1237 alpDx
[j
] = walpDx
[i
];
1238 if (IsDBCSLeadByte(str
[j
])) alpDx
[++j
] = walpDx
[i
];
1241 if (lpnFit
) *lpnFit
= WideCharToMultiByte(CP_ACP
,0,p
,*lpnFit
,NULL
,0,NULL
,NULL
);
1242 HeapFree( GetProcessHeap(), 0, p
);
1243 HeapFree( GetProcessHeap(), 0, walpDx
);
1248 /***********************************************************************
1249 * GetTextExtentExPointW (GDI32.@)
1251 * Return the size of the string as it would be if it was output properly by
1254 * This should include
1255 * - Intercharacter spacing
1256 * - justification spacing (not yet done)
1257 * - kerning? see below
1259 * Kerning. Since kerning would be carried out by the rendering code it should
1260 * be done by the driver. However they don't support it yet. Also I am not
1261 * yet persuaded that (certainly under Win95) any kerning is actually done.
1263 * str: According to MSDN this should be null-terminated. That is not true; a
1264 * null will not terminate it early.
1265 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1266 * than count. I have seen it be either the size of the full string or
1267 * 1 less than the size of the full string. I have not seen it bear any
1268 * resemblance to the portion that would fit.
1269 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1270 * trailing intercharacter spacing and any trailing justification.
1273 * Currently we do this by measuring each character etc. We should do it by
1274 * passing the request to the driver, perhaps by extending the
1275 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1276 * thinking about kerning issues and rounding issues in the justification.
1279 BOOL WINAPI
GetTextExtentExPointW( HDC hdc
, LPCWSTR str
, INT count
,
1280 INT maxExt
, LPINT lpnFit
,
1281 LPINT alpDx
, LPSIZE size
)
1289 TRACE("(%p, %s, %d)\n",hdc
,debugstr_wn(str
,count
),maxExt
);
1291 dc
= get_dc_ptr(hdc
);
1295 GetTextMetricsW(hdc
, &tm
);
1297 /* If we need to calculate nFit, then we need the partial extents even if
1298 the user hasn't provided us with an array. */
1301 dxs
= alpDx
? alpDx
: HeapAlloc(GetProcessHeap(), 0, count
* sizeof alpDx
[0]);
1305 SetLastError(ERROR_OUTOFMEMORY
);
1313 ret
= WineEngGetTextExtentExPoint(dc
->gdiFont
, str
, count
,
1314 0, NULL
, dxs
, size
);
1315 else if (dc
->funcs
->pGetTextExtentExPoint
)
1316 ret
= dc
->funcs
->pGetTextExtentExPoint(dc
->physDev
, str
, count
,
1317 0, NULL
, dxs
, size
);
1319 /* Perform device size to world size transformations. */
1322 INT extra
= dc
->charExtra
,
1323 breakExtra
= dc
->breakExtra
,
1324 breakRem
= dc
->breakRem
,
1329 for (i
= 0; i
< count
; ++i
)
1331 dxs
[i
] = abs(INTERNAL_XDSTOWS(dc
, dxs
[i
]));
1332 dxs
[i
] += (i
+1) * extra
;
1333 if (count
> 1 && (breakExtra
|| breakRem
) && str
[i
] == tm
.tmBreakChar
)
1335 dxs
[i
] += breakExtra
;
1342 if (dxs
[i
] <= maxExt
)
1345 breakRem
= dc
->breakRem
;
1347 size
->cx
= abs(INTERNAL_XDSTOWS(dc
, size
->cx
));
1348 size
->cy
= abs(INTERNAL_YDSTOWS(dc
, size
->cy
));
1350 if (!dxs
&& count
> 1 && (breakExtra
|| breakRem
))
1352 for (i
= 0; i
< count
; i
++)
1354 if (str
[i
] == tm
.tmBreakChar
)
1356 size
->cx
+= breakExtra
;
1371 HeapFree(GetProcessHeap(), 0, dxs
);
1373 release_dc_ptr( dc
);
1375 TRACE("returning %d %d x %d\n",nFit
,size
->cx
,size
->cy
);
1379 /***********************************************************************
1380 * GetTextMetricsA (GDI32.@)
1382 BOOL WINAPI
GetTextMetricsA( HDC hdc
, TEXTMETRICA
*metrics
)
1386 if (!GetTextMetricsW( hdc
, &tm32
)) return FALSE
;
1387 FONT_TextMetricWToA( &tm32
, metrics
);
1391 /***********************************************************************
1392 * GetTextMetricsW (GDI32.@)
1394 BOOL WINAPI
GetTextMetricsW( HDC hdc
, TEXTMETRICW
*metrics
)
1397 DC
* dc
= get_dc_ptr( hdc
);
1398 if (!dc
) return FALSE
;
1401 ret
= WineEngGetTextMetrics(dc
->gdiFont
, metrics
);
1402 else if (dc
->funcs
->pGetTextMetrics
)
1403 ret
= dc
->funcs
->pGetTextMetrics( dc
->physDev
, metrics
);
1407 /* device layer returns values in device units
1408 * therefore we have to convert them to logical */
1410 metrics
->tmDigitizedAspectX
= GetDeviceCaps(hdc
, LOGPIXELSX
);
1411 metrics
->tmDigitizedAspectY
= GetDeviceCaps(hdc
, LOGPIXELSY
);
1413 #define WDPTOLP(x) ((x<0)? \
1414 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1415 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1416 #define HDPTOLP(y) ((y<0)? \
1417 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1418 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1420 metrics
->tmHeight
= HDPTOLP(metrics
->tmHeight
);
1421 metrics
->tmAscent
= HDPTOLP(metrics
->tmAscent
);
1422 metrics
->tmDescent
= HDPTOLP(metrics
->tmDescent
);
1423 metrics
->tmInternalLeading
= HDPTOLP(metrics
->tmInternalLeading
);
1424 metrics
->tmExternalLeading
= HDPTOLP(metrics
->tmExternalLeading
);
1425 metrics
->tmAveCharWidth
= WDPTOLP(metrics
->tmAveCharWidth
);
1426 metrics
->tmMaxCharWidth
= WDPTOLP(metrics
->tmMaxCharWidth
);
1427 metrics
->tmOverhang
= WDPTOLP(metrics
->tmOverhang
);
1431 TRACE("text metrics:\n"
1432 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1433 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1434 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1435 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1436 " PitchAndFamily = %02x\n"
1437 " --------------------\n"
1438 " InternalLeading = %i\n"
1442 metrics
->tmWeight
, metrics
->tmFirstChar
, metrics
->tmAveCharWidth
,
1443 metrics
->tmItalic
, metrics
->tmLastChar
, metrics
->tmMaxCharWidth
,
1444 metrics
->tmUnderlined
, metrics
->tmDefaultChar
, metrics
->tmOverhang
,
1445 metrics
->tmStruckOut
, metrics
->tmBreakChar
, metrics
->tmCharSet
,
1446 metrics
->tmPitchAndFamily
,
1447 metrics
->tmInternalLeading
,
1450 metrics
->tmHeight
);
1452 release_dc_ptr( dc
);
1457 /***********************************************************************
1458 * GetOutlineTextMetrics [GDI.308] Gets metrics for TrueType fonts.
1461 * lpOTM should be LPOUTLINETEXTMETRIC
1464 * Success: Non-zero or size of required buffer
1467 UINT16 WINAPI
GetOutlineTextMetrics16(
1468 HDC16 hdc
, /* [in] Handle of device context */
1469 UINT16 cbData
, /* [in] Size of metric data array */
1470 LPOUTLINETEXTMETRIC16 lpOTM
) /* [out] Address of metric data array */
1472 FIXME("(%04x,%04x,%p): stub\n", hdc
,cbData
,lpOTM
);
1477 /***********************************************************************
1478 * GetOutlineTextMetricsA (GDI32.@)
1479 * Gets metrics for TrueType fonts.
1482 * If the supplied buffer isn't big enough Windows partially fills it up to
1483 * its given length and returns that length.
1486 * Success: Non-zero or size of required buffer
1489 UINT WINAPI
GetOutlineTextMetricsA(
1490 HDC hdc
, /* [in] Handle of device context */
1491 UINT cbData
, /* [in] Size of metric data array */
1492 LPOUTLINETEXTMETRICA lpOTM
) /* [out] Address of metric data array */
1494 char buf
[512], *ptr
;
1496 OUTLINETEXTMETRICW
*lpOTMW
= (OUTLINETEXTMETRICW
*)buf
;
1497 OUTLINETEXTMETRICA
*output
= lpOTM
;
1500 if((ret
= GetOutlineTextMetricsW(hdc
, 0, NULL
)) == 0)
1502 if(ret
> sizeof(buf
))
1503 lpOTMW
= HeapAlloc(GetProcessHeap(), 0, ret
);
1504 GetOutlineTextMetricsW(hdc
, ret
, lpOTMW
);
1506 needed
= sizeof(OUTLINETEXTMETRICA
);
1507 if(lpOTMW
->otmpFamilyName
)
1508 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1509 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFamilyName
), -1,
1510 NULL
, 0, NULL
, NULL
);
1511 if(lpOTMW
->otmpFaceName
)
1512 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1513 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFaceName
), -1,
1514 NULL
, 0, NULL
, NULL
);
1515 if(lpOTMW
->otmpStyleName
)
1516 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1517 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpStyleName
), -1,
1518 NULL
, 0, NULL
, NULL
);
1519 if(lpOTMW
->otmpFullName
)
1520 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1521 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFullName
), -1,
1522 NULL
, 0, NULL
, NULL
);
1529 TRACE("needed = %d\n", needed
);
1531 /* Since the supplied buffer isn't big enough, we'll alloc one
1532 that is and memcpy the first cbData bytes into the lpOTM at
1534 output
= HeapAlloc(GetProcessHeap(), 0, needed
);
1536 ret
= output
->otmSize
= min(needed
, cbData
);
1537 FONT_TextMetricWToA( &lpOTMW
->otmTextMetrics
, &output
->otmTextMetrics
);
1538 output
->otmFiller
= 0;
1539 output
->otmPanoseNumber
= lpOTMW
->otmPanoseNumber
;
1540 output
->otmfsSelection
= lpOTMW
->otmfsSelection
;
1541 output
->otmfsType
= lpOTMW
->otmfsType
;
1542 output
->otmsCharSlopeRise
= lpOTMW
->otmsCharSlopeRise
;
1543 output
->otmsCharSlopeRun
= lpOTMW
->otmsCharSlopeRun
;
1544 output
->otmItalicAngle
= lpOTMW
->otmItalicAngle
;
1545 output
->otmEMSquare
= lpOTMW
->otmEMSquare
;
1546 output
->otmAscent
= lpOTMW
->otmAscent
;
1547 output
->otmDescent
= lpOTMW
->otmDescent
;
1548 output
->otmLineGap
= lpOTMW
->otmLineGap
;
1549 output
->otmsCapEmHeight
= lpOTMW
->otmsCapEmHeight
;
1550 output
->otmsXHeight
= lpOTMW
->otmsXHeight
;
1551 output
->otmrcFontBox
= lpOTMW
->otmrcFontBox
;
1552 output
->otmMacAscent
= lpOTMW
->otmMacAscent
;
1553 output
->otmMacDescent
= lpOTMW
->otmMacDescent
;
1554 output
->otmMacLineGap
= lpOTMW
->otmMacLineGap
;
1555 output
->otmusMinimumPPEM
= lpOTMW
->otmusMinimumPPEM
;
1556 output
->otmptSubscriptSize
= lpOTMW
->otmptSubscriptSize
;
1557 output
->otmptSubscriptOffset
= lpOTMW
->otmptSubscriptOffset
;
1558 output
->otmptSuperscriptSize
= lpOTMW
->otmptSuperscriptSize
;
1559 output
->otmptSuperscriptOffset
= lpOTMW
->otmptSuperscriptOffset
;
1560 output
->otmsStrikeoutSize
= lpOTMW
->otmsStrikeoutSize
;
1561 output
->otmsStrikeoutPosition
= lpOTMW
->otmsStrikeoutPosition
;
1562 output
->otmsUnderscoreSize
= lpOTMW
->otmsUnderscoreSize
;
1563 output
->otmsUnderscorePosition
= lpOTMW
->otmsUnderscorePosition
;
1566 ptr
= (char*)(output
+ 1);
1567 left
= needed
- sizeof(*output
);
1569 if(lpOTMW
->otmpFamilyName
) {
1570 output
->otmpFamilyName
= (LPSTR
)(ptr
- (char*)output
);
1571 len
= WideCharToMultiByte(CP_ACP
, 0,
1572 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFamilyName
), -1,
1573 ptr
, left
, NULL
, NULL
);
1577 output
->otmpFamilyName
= 0;
1579 if(lpOTMW
->otmpFaceName
) {
1580 output
->otmpFaceName
= (LPSTR
)(ptr
- (char*)output
);
1581 len
= WideCharToMultiByte(CP_ACP
, 0,
1582 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFaceName
), -1,
1583 ptr
, left
, NULL
, NULL
);
1587 output
->otmpFaceName
= 0;
1589 if(lpOTMW
->otmpStyleName
) {
1590 output
->otmpStyleName
= (LPSTR
)(ptr
- (char*)output
);
1591 len
= WideCharToMultiByte(CP_ACP
, 0,
1592 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpStyleName
), -1,
1593 ptr
, left
, NULL
, NULL
);
1597 output
->otmpStyleName
= 0;
1599 if(lpOTMW
->otmpFullName
) {
1600 output
->otmpFullName
= (LPSTR
)(ptr
- (char*)output
);
1601 len
= WideCharToMultiByte(CP_ACP
, 0,
1602 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFullName
), -1,
1603 ptr
, left
, NULL
, NULL
);
1606 output
->otmpFullName
= 0;
1610 if(output
!= lpOTM
) {
1611 memcpy(lpOTM
, output
, cbData
);
1612 HeapFree(GetProcessHeap(), 0, output
);
1614 /* check if the string offsets really fit into the provided size */
1615 /* FIXME: should we check string length as well? */
1616 /* make sure that we don't read/write beyond the provided buffer */
1617 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFamilyName
) + sizeof(LPSTR
))
1619 if ((UINT_PTR
)lpOTM
->otmpFamilyName
>= lpOTM
->otmSize
)
1620 lpOTM
->otmpFamilyName
= 0; /* doesn't fit */
1623 /* make sure that we don't read/write beyond the provided buffer */
1624 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFaceName
) + sizeof(LPSTR
))
1626 if ((UINT_PTR
)lpOTM
->otmpFaceName
>= lpOTM
->otmSize
)
1627 lpOTM
->otmpFaceName
= 0; /* doesn't fit */
1630 /* make sure that we don't read/write beyond the provided buffer */
1631 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpStyleName
) + sizeof(LPSTR
))
1633 if ((UINT_PTR
)lpOTM
->otmpStyleName
>= lpOTM
->otmSize
)
1634 lpOTM
->otmpStyleName
= 0; /* doesn't fit */
1637 /* make sure that we don't read/write beyond the provided buffer */
1638 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFullName
) + sizeof(LPSTR
))
1640 if ((UINT_PTR
)lpOTM
->otmpFullName
>= lpOTM
->otmSize
)
1641 lpOTM
->otmpFullName
= 0; /* doesn't fit */
1646 if(lpOTMW
!= (OUTLINETEXTMETRICW
*)buf
)
1647 HeapFree(GetProcessHeap(), 0, lpOTMW
);
1653 /***********************************************************************
1654 * GetOutlineTextMetricsW [GDI32.@]
1656 UINT WINAPI
GetOutlineTextMetricsW(
1657 HDC hdc
, /* [in] Handle of device context */
1658 UINT cbData
, /* [in] Size of metric data array */
1659 LPOUTLINETEXTMETRICW lpOTM
) /* [out] Address of metric data array */
1661 DC
*dc
= get_dc_ptr( hdc
);
1662 OUTLINETEXTMETRICW
*output
= lpOTM
;
1665 TRACE("(%p,%d,%p)\n", hdc
, cbData
, lpOTM
);
1669 ret
= WineEngGetOutlineTextMetrics(dc
->gdiFont
, cbData
, output
);
1672 output
= HeapAlloc(GetProcessHeap(), 0, ret
);
1673 WineEngGetOutlineTextMetrics(dc
->gdiFont
, ret
, output
);
1676 #define WDPTOLP(x) ((x<0)? \
1677 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1678 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1679 #define HDPTOLP(y) ((y<0)? \
1680 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1681 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1683 output
->otmTextMetrics
.tmHeight
= HDPTOLP(output
->otmTextMetrics
.tmHeight
);
1684 output
->otmTextMetrics
.tmAscent
= HDPTOLP(output
->otmTextMetrics
.tmAscent
);
1685 output
->otmTextMetrics
.tmDescent
= HDPTOLP(output
->otmTextMetrics
.tmDescent
);
1686 output
->otmTextMetrics
.tmInternalLeading
= HDPTOLP(output
->otmTextMetrics
.tmInternalLeading
);
1687 output
->otmTextMetrics
.tmExternalLeading
= HDPTOLP(output
->otmTextMetrics
.tmExternalLeading
);
1688 output
->otmTextMetrics
.tmAveCharWidth
= WDPTOLP(output
->otmTextMetrics
.tmAveCharWidth
);
1689 output
->otmTextMetrics
.tmMaxCharWidth
= WDPTOLP(output
->otmTextMetrics
.tmMaxCharWidth
);
1690 output
->otmTextMetrics
.tmOverhang
= WDPTOLP(output
->otmTextMetrics
.tmOverhang
);
1691 output
->otmAscent
= HDPTOLP(output
->otmAscent
);
1692 output
->otmDescent
= HDPTOLP(output
->otmDescent
);
1693 output
->otmLineGap
= HDPTOLP(output
->otmLineGap
);
1694 output
->otmsCapEmHeight
= HDPTOLP(output
->otmsCapEmHeight
);
1695 output
->otmsXHeight
= HDPTOLP(output
->otmsXHeight
);
1696 output
->otmrcFontBox
.top
= HDPTOLP(output
->otmrcFontBox
.top
);
1697 output
->otmrcFontBox
.bottom
= HDPTOLP(output
->otmrcFontBox
.bottom
);
1698 output
->otmrcFontBox
.left
= WDPTOLP(output
->otmrcFontBox
.left
);
1699 output
->otmrcFontBox
.right
= WDPTOLP(output
->otmrcFontBox
.right
);
1700 output
->otmMacAscent
= HDPTOLP(output
->otmMacAscent
);
1701 output
->otmMacDescent
= HDPTOLP(output
->otmMacDescent
);
1702 output
->otmMacLineGap
= HDPTOLP(output
->otmMacLineGap
);
1703 output
->otmptSubscriptSize
.x
= WDPTOLP(output
->otmptSubscriptSize
.x
);
1704 output
->otmptSubscriptSize
.y
= HDPTOLP(output
->otmptSubscriptSize
.y
);
1705 output
->otmptSubscriptOffset
.x
= WDPTOLP(output
->otmptSubscriptOffset
.x
);
1706 output
->otmptSubscriptOffset
.y
= HDPTOLP(output
->otmptSubscriptOffset
.y
);
1707 output
->otmptSuperscriptSize
.x
= WDPTOLP(output
->otmptSuperscriptSize
.x
);
1708 output
->otmptSuperscriptSize
.y
= HDPTOLP(output
->otmptSuperscriptSize
.y
);
1709 output
->otmptSuperscriptOffset
.x
= WDPTOLP(output
->otmptSuperscriptOffset
.x
);
1710 output
->otmptSuperscriptOffset
.y
= HDPTOLP(output
->otmptSuperscriptOffset
.y
);
1711 output
->otmsStrikeoutSize
= HDPTOLP(output
->otmsStrikeoutSize
);
1712 output
->otmsStrikeoutPosition
= HDPTOLP(output
->otmsStrikeoutPosition
);
1713 output
->otmsUnderscoreSize
= HDPTOLP(output
->otmsUnderscoreSize
);
1714 output
->otmsUnderscorePosition
= HDPTOLP(output
->otmsUnderscorePosition
);
1717 if(output
!= lpOTM
) {
1718 memcpy(lpOTM
, output
, cbData
);
1719 HeapFree(GetProcessHeap(), 0, output
);
1725 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1726 but really this should just be a return 0. */
1728 ret
= sizeof(*lpOTM
);
1733 memset(lpOTM
, 0, ret
);
1734 lpOTM
->otmSize
= sizeof(*lpOTM
);
1735 GetTextMetricsW(hdc
, &lpOTM
->otmTextMetrics
);
1737 Further fill of the structure not implemented,
1738 Needs real values for the structure members
1748 /***********************************************************************
1749 * GetCharWidthW (GDI32.@)
1750 * GetCharWidth32W (GDI32.@)
1752 BOOL WINAPI
GetCharWidth32W( HDC hdc
, UINT firstChar
, UINT lastChar
,
1757 DC
* dc
= get_dc_ptr( hdc
);
1758 if (!dc
) return FALSE
;
1761 ret
= WineEngGetCharWidth( dc
->gdiFont
, firstChar
, lastChar
, buffer
);
1762 else if (dc
->funcs
->pGetCharWidth
)
1763 ret
= dc
->funcs
->pGetCharWidth( dc
->physDev
, firstChar
, lastChar
, buffer
);
1767 /* convert device units to logical */
1768 for( i
= firstChar
; i
<= lastChar
; i
++, buffer
++ )
1769 *buffer
= INTERNAL_XDSTOWS(dc
, *buffer
);
1772 release_dc_ptr( dc
);
1777 /***********************************************************************
1778 * GetCharWidthA (GDI32.@)
1779 * GetCharWidth32A (GDI32.@)
1781 BOOL WINAPI
GetCharWidth32A( HDC hdc
, UINT firstChar
, UINT lastChar
,
1784 INT i
, wlen
, count
= (INT
)(lastChar
- firstChar
+ 1);
1789 if(count
<= 0) return FALSE
;
1791 str
= HeapAlloc(GetProcessHeap(), 0, count
);
1792 for(i
= 0; i
< count
; i
++)
1793 str
[i
] = (BYTE
)(firstChar
+ i
);
1795 wstr
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
1797 for(i
= 0; i
< wlen
; i
++)
1799 if(!GetCharWidth32W(hdc
, wstr
[i
], wstr
[i
], buffer
))
1807 HeapFree(GetProcessHeap(), 0, str
);
1808 HeapFree(GetProcessHeap(), 0, wstr
);
1814 /***********************************************************************
1815 * ExtTextOutA (GDI32.@)
1819 BOOL WINAPI
ExtTextOutA( HDC hdc
, INT x
, INT y
, UINT flags
,
1820 const RECT
*lprect
, LPCSTR str
, UINT count
, const INT
*lpDx
)
1828 if (flags
& ETO_GLYPH_INDEX
)
1829 return ExtTextOutW( hdc
, x
, y
, flags
, lprect
, (LPCWSTR
)str
, count
, lpDx
);
1831 p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, &codepage
);
1834 unsigned int i
= 0, j
= 0;
1836 lpDxW
= HeapAlloc( GetProcessHeap(), 0, wlen
*sizeof(INT
));
1838 if(IsDBCSLeadByteEx(codepage
, str
[i
])) {
1839 lpDxW
[j
++] = lpDx
[i
] + lpDx
[i
+1];
1842 lpDxW
[j
++] = lpDx
[i
];
1848 ret
= ExtTextOutW( hdc
, x
, y
, flags
, lprect
, p
, wlen
, lpDxW
);
1850 HeapFree( GetProcessHeap(), 0, p
);
1851 HeapFree( GetProcessHeap(), 0, lpDxW
);
1856 /***********************************************************************
1857 * ExtTextOutW (GDI32.@)
1859 * Draws text using the currently selected font, background color, and text color.
1863 * x,y [I] coordinates of string
1865 * ETO_GRAYED - undocumented on MSDN
1866 * ETO_OPAQUE - use background color for fill the rectangle
1867 * ETO_CLIPPED - clipping text to the rectangle
1868 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1869 * than encoded characters. Implies ETO_IGNORELANGUAGE
1870 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1871 * Affects BiDi ordering
1872 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1873 * ETO_PDY - unimplemented
1874 * ETO_NUMERICSLATIN - unimplemented always assumed -
1875 * do not translate numbers into locale representations
1876 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1877 * lprect [I] dimensions for clipping or/and opaquing
1878 * str [I] text string
1879 * count [I] number of symbols in string
1880 * lpDx [I] optional parameter with distance between drawing characters
1886 BOOL WINAPI
ExtTextOutW( HDC hdc
, INT x
, INT y
, UINT flags
,
1887 const RECT
*lprect
, LPCWSTR str
, UINT count
, const INT
*lpDx
)
1890 LPWSTR reordered_str
= (LPWSTR
)str
;
1891 WORD
*glyphs
= NULL
;
1892 UINT align
= GetTextAlign( hdc
);
1896 double cosEsc
, sinEsc
;
1897 INT
*deltas
= NULL
, char_extra
;
1900 BOOL done_extents
= FALSE
;
1901 INT width
= 0, xwidth
= 0, ywidth
= 0;
1903 DC
* dc
= get_dc_ptr( hdc
);
1906 if (!dc
) return FALSE
;
1908 breakRem
= dc
->breakRem
;
1910 if (flags
& (ETO_NUMERICSLOCAL
| ETO_NUMERICSLATIN
| ETO_PDY
))
1911 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY unimplemented\n");
1913 if (!dc
->funcs
->pExtTextOut
&& !PATH_IsPathOpen(dc
->path
))
1915 release_dc_ptr( dc
);
1920 type
= GetObjectType(hdc
);
1921 if(type
== OBJ_METADC
|| type
== OBJ_ENHMETADC
)
1923 ret
= dc
->funcs
->pExtTextOut(dc
->physDev
, x
, y
, flags
, lprect
, str
, count
, lpDx
);
1924 release_dc_ptr( dc
);
1929 flags
&= ~ETO_CLIPPED
;
1931 if( !(flags
& (ETO_GLYPH_INDEX
| ETO_IGNORELANGUAGE
)) && count
> 0 )
1933 reordered_str
= HeapAlloc(GetProcessHeap(), 0, count
*sizeof(WCHAR
));
1935 BIDI_Reorder( str
, count
, GCP_REORDER
,
1936 ((flags
&ETO_RTLREADING
)!=0 || (GetTextAlign(hdc
)&TA_RTLREADING
)!=0)?
1937 WINE_GCPW_FORCE_RTL
:WINE_GCPW_FORCE_LTR
,
1938 reordered_str
, count
, NULL
);
1940 flags
|= ETO_IGNORELANGUAGE
;
1943 TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc
, x
, y
, flags
,
1944 lprect
, debugstr_wn(str
, count
), count
, lpDx
);
1946 if(flags
& ETO_GLYPH_INDEX
)
1947 glyphs
= reordered_str
;
1950 TRACE("rect: %d,%d - %d,%d\n", lprect
->left
, lprect
->top
, lprect
->right
,
1952 TRACE("align = %x bkmode = %x mapmode = %x\n", align
, GetBkMode(hdc
), GetMapMode(hdc
));
1954 if(align
& TA_UPDATECP
)
1956 GetCurrentPositionEx( hdc
, &pt
);
1961 GetTextMetricsW(hdc
, &tm
);
1962 GetObjectW(GetCurrentObject(hdc
, OBJ_FONT
), sizeof(lf
), &lf
);
1964 if(!(tm
.tmPitchAndFamily
& TMPF_VECTOR
)) /* Non-scalable fonts shouldn't be rotated */
1965 lf
.lfEscapement
= 0;
1967 if(lf
.lfEscapement
!= 0)
1969 cosEsc
= cos(lf
.lfEscapement
* M_PI
/ 1800);
1970 sinEsc
= sin(lf
.lfEscapement
* M_PI
/ 1800);
1978 if(flags
& (ETO_CLIPPED
| ETO_OPAQUE
))
1982 if(flags
& ETO_GLYPH_INDEX
)
1983 GetTextExtentPointI(hdc
, glyphs
, count
, &sz
);
1985 GetTextExtentPointW(hdc
, reordered_str
, count
, &sz
);
1987 done_extents
= TRUE
;
1990 rc
.right
= x
+ sz
.cx
;
1991 rc
.bottom
= y
+ sz
.cy
;
1998 LPtoDP(hdc
, (POINT
*)&rc
, 2);
2000 if(rc
.left
> rc
.right
) {INT tmp
= rc
.left
; rc
.left
= rc
.right
; rc
.right
= tmp
;}
2001 if(rc
.top
> rc
.bottom
) {INT tmp
= rc
.top
; rc
.top
= rc
.bottom
; rc
.bottom
= tmp
;}
2004 if ((flags
& ETO_OPAQUE
) && !PATH_IsPathOpen(dc
->path
))
2005 dc
->funcs
->pExtTextOut(dc
->physDev
, 0, 0, ETO_OPAQUE
, &rc
, NULL
, 0, NULL
);
2015 LPtoDP(hdc
, &pt
, 1);
2019 char_extra
= GetTextCharacterExtra(hdc
);
2020 if(char_extra
|| dc
->breakExtra
|| breakRem
|| lpDx
|| lf
.lfEscapement
!= 0)
2024 deltas
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(INT
));
2025 for(i
= 0; i
< count
; i
++)
2027 if(lpDx
&& (flags
& ETO_PDY
))
2028 deltas
[i
] = lpDx
[i
*2] + char_extra
;
2030 deltas
[i
] = lpDx
[i
] + char_extra
;
2033 if(flags
& ETO_GLYPH_INDEX
)
2034 GetTextExtentPointI(hdc
, glyphs
+ i
, 1, &tmpsz
);
2036 GetTextExtentPointW(hdc
, reordered_str
+ i
, 1, &tmpsz
);
2038 deltas
[i
] = tmpsz
.cx
;
2041 if (!(flags
& ETO_GLYPH_INDEX
) && (dc
->breakExtra
|| breakRem
) && reordered_str
[i
] == tm
.tmBreakChar
)
2043 deltas
[i
] = deltas
[i
] + dc
->breakExtra
;
2050 deltas
[i
] = INTERNAL_XWSTODS(dc
, deltas
[i
]);
2058 if(flags
& ETO_GLYPH_INDEX
)
2059 GetTextExtentPointI(hdc
, glyphs
, count
, &sz
);
2061 GetTextExtentPointW(hdc
, reordered_str
, count
, &sz
);
2062 done_extents
= TRUE
;
2064 width
= INTERNAL_XWSTODS(dc
, sz
.cx
);
2066 xwidth
= width
* cosEsc
;
2067 ywidth
= width
* sinEsc
;
2069 tm
.tmAscent
= abs(INTERNAL_YWSTODS(dc
, tm
.tmAscent
));
2070 tm
.tmDescent
= abs(INTERNAL_YWSTODS(dc
, tm
.tmDescent
));
2071 switch( align
& (TA_LEFT
| TA_RIGHT
| TA_CENTER
) )
2074 if (align
& TA_UPDATECP
)
2078 DPtoLP(hdc
, &pt
, 1);
2079 MoveToEx(hdc
, pt
.x
, pt
.y
, NULL
);
2091 if (align
& TA_UPDATECP
)
2095 DPtoLP(hdc
, &pt
, 1);
2096 MoveToEx(hdc
, pt
.x
, pt
.y
, NULL
);
2101 switch( align
& (TA_TOP
| TA_BOTTOM
| TA_BASELINE
) )
2104 y
+= tm
.tmAscent
* cosEsc
;
2105 x
+= tm
.tmAscent
* sinEsc
;
2109 y
-= tm
.tmDescent
* cosEsc
;
2110 x
-= tm
.tmDescent
* sinEsc
;
2117 if (GetBkMode(hdc
) != TRANSPARENT
&& !PATH_IsPathOpen(dc
->path
))
2119 if(!((flags
& ETO_CLIPPED
) && (flags
& ETO_OPAQUE
)))
2121 if(!(flags
& ETO_OPAQUE
) || x
< rc
.left
|| x
+ width
>= rc
.right
||
2122 y
- tm
.tmAscent
< rc
.top
|| y
+ tm
.tmDescent
>= rc
.bottom
)
2126 rc
.right
= x
+ width
;
2127 rc
.top
= y
- tm
.tmAscent
;
2128 rc
.bottom
= y
+ tm
.tmDescent
;
2129 dc
->funcs
->pExtTextOut(dc
->physDev
, 0, 0, ETO_OPAQUE
, &rc
, NULL
, 0, NULL
);
2134 if(FontIsLinked(hdc
) && !(flags
& ETO_GLYPH_INDEX
))
2136 HFONT orig_font
= dc
->hFont
, cur_font
;
2138 INT span
= 0, *offsets
= NULL
;
2141 glyphs
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(WORD
));
2142 for(i
= 0; i
< count
; i
++)
2144 WineEngGetLinkedHFont(dc
, reordered_str
[i
], &cur_font
, &glyph
);
2145 if(cur_font
!= dc
->hFont
)
2150 offsets
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(*deltas
));
2155 for(j
= 1; j
< count
; j
++)
2157 GetTextExtentPointW(hdc
, reordered_str
+ j
- 1, 1, &tmpsz
);
2158 offsets
[j
] = offsets
[j
-1] + INTERNAL_XWSTODS(dc
, tmpsz
.cx
);
2163 for(j
= 1; j
< count
; j
++)
2164 offsets
[j
] = offsets
[j
-1] + deltas
[j
];
2169 if (PATH_IsPathOpen(dc
->path
))
2170 ret
= PATH_ExtTextOut(dc
, x
+ offsets
[i
- span
] * cosEsc
, y
- offsets
[i
- span
] * sinEsc
,
2171 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
,
2172 glyphs
, span
, deltas
? deltas
+ i
- span
: NULL
);
2174 dc
->funcs
->pExtTextOut(dc
->physDev
, x
+ offsets
[i
- span
] * cosEsc
, y
- offsets
[i
- span
] * sinEsc
,
2175 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
,
2176 glyphs
, span
, deltas
? deltas
+ i
- span
: NULL
);
2179 SelectObject(hdc
, cur_font
);
2181 glyphs
[span
++] = glyph
;
2185 if (PATH_IsPathOpen(dc
->path
))
2186 ret
= PATH_ExtTextOut(dc
, x
+ (offsets
? offsets
[count
- span
] * cosEsc
: 0),
2187 y
- (offsets
? offsets
[count
- span
] * sinEsc
: 0),
2188 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
,
2189 glyphs
, span
, deltas
? deltas
+ count
- span
: NULL
);
2191 ret
= dc
->funcs
->pExtTextOut(dc
->physDev
, x
+ (offsets
? offsets
[count
- span
] * cosEsc
: 0),
2192 y
- (offsets
? offsets
[count
- span
] * sinEsc
: 0),
2193 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
,
2194 glyphs
, span
, deltas
? deltas
+ count
- span
: NULL
);
2195 SelectObject(hdc
, orig_font
);
2196 HeapFree(GetProcessHeap(), 0, offsets
);
2202 if(!(flags
& ETO_GLYPH_INDEX
) && dc
->gdiFont
)
2204 glyphs
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(WORD
));
2205 GetGlyphIndicesW(hdc
, reordered_str
, count
, glyphs
, 0);
2206 flags
|= ETO_GLYPH_INDEX
;
2209 if (PATH_IsPathOpen(dc
->path
))
2210 ret
= PATH_ExtTextOut(dc
, x
, y
, (flags
& ~ETO_OPAQUE
), &rc
,
2211 glyphs
? glyphs
: reordered_str
, count
, deltas
);
2213 ret
= dc
->funcs
->pExtTextOut(dc
->physDev
, x
, y
, (flags
& ~ETO_OPAQUE
), &rc
,
2214 glyphs
? glyphs
: reordered_str
, count
, deltas
);
2218 HeapFree(GetProcessHeap(), 0, deltas
);
2219 if(glyphs
!= reordered_str
)
2220 HeapFree(GetProcessHeap(), 0, glyphs
);
2221 if(reordered_str
!= str
)
2222 HeapFree(GetProcessHeap(), 0, reordered_str
);
2224 release_dc_ptr( dc
);
2226 if (ret
&& (lf
.lfUnderline
|| lf
.lfStrikeOut
))
2228 int underlinePos
, strikeoutPos
;
2229 int underlineWidth
, strikeoutWidth
;
2230 UINT size
= GetOutlineTextMetricsW(hdc
, 0, NULL
);
2231 OUTLINETEXTMETRICW
* otm
= NULL
;
2236 underlineWidth
= tm
.tmAscent
/ 20 + 1;
2237 strikeoutPos
= tm
.tmAscent
/ 2;
2238 strikeoutWidth
= underlineWidth
;
2242 otm
= HeapAlloc(GetProcessHeap(), 0, size
);
2243 GetOutlineTextMetricsW(hdc
, size
, otm
);
2244 underlinePos
= otm
->otmsUnderscorePosition
;
2245 underlineWidth
= otm
->otmsUnderscoreSize
;
2246 strikeoutPos
= otm
->otmsStrikeoutPosition
;
2247 strikeoutWidth
= otm
->otmsStrikeoutSize
;
2248 HeapFree(GetProcessHeap(), 0, otm
);
2251 if (PATH_IsPathOpen(dc
->path
))
2255 HBRUSH hbrush
= CreateSolidBrush(GetTextColor(hdc
));
2257 hbrush
= SelectObject(hdc
, hbrush
);
2258 hpen
= SelectObject(hdc
, GetStockObject(NULL_PEN
));
2262 pts
[0].x
= x
- underlinePos
* sinEsc
;
2263 pts
[0].y
= y
- underlinePos
* cosEsc
;
2264 pts
[1].x
= x
+ xwidth
- underlinePos
* sinEsc
;
2265 pts
[1].y
= y
- ywidth
- underlinePos
* cosEsc
;
2266 pts
[2].x
= pts
[1].x
+ underlineWidth
* sinEsc
;
2267 pts
[2].y
= pts
[1].y
+ underlineWidth
* cosEsc
;
2268 pts
[3].x
= pts
[0].x
+ underlineWidth
* sinEsc
;
2269 pts
[3].y
= pts
[0].y
+ underlineWidth
* cosEsc
;
2270 pts
[4].x
= pts
[0].x
;
2271 pts
[4].y
= pts
[0].y
;
2272 DPtoLP(hdc
, pts
, 5);
2273 Polygon(hdc
, pts
, 5);
2278 pts
[0].x
= x
- strikeoutPos
* sinEsc
;
2279 pts
[0].y
= y
- strikeoutPos
* cosEsc
;
2280 pts
[1].x
= x
+ xwidth
- strikeoutPos
* sinEsc
;
2281 pts
[1].y
= y
- ywidth
- strikeoutPos
* cosEsc
;
2282 pts
[2].x
= pts
[1].x
+ strikeoutWidth
* sinEsc
;
2283 pts
[2].y
= pts
[1].y
+ strikeoutWidth
* cosEsc
;
2284 pts
[3].x
= pts
[0].x
+ strikeoutWidth
* sinEsc
;
2285 pts
[3].y
= pts
[0].y
+ strikeoutWidth
* cosEsc
;
2286 pts
[4].x
= pts
[0].x
;
2287 pts
[4].y
= pts
[0].y
;
2288 DPtoLP(hdc
, pts
, 5);
2289 Polygon(hdc
, pts
, 5);
2292 SelectObject(hdc
, hpen
);
2293 hbrush
= SelectObject(hdc
, hbrush
);
2294 DeleteObject(hbrush
);
2298 POINT pts
[2], oldpt
;
2303 hpen
= CreatePen(PS_SOLID
, underlineWidth
, GetTextColor(hdc
));
2304 hpen
= SelectObject(hdc
, hpen
);
2307 pts
[1].x
= x
+ xwidth
;
2308 pts
[1].y
= y
- ywidth
;
2309 DPtoLP(hdc
, pts
, 2);
2310 MoveToEx(hdc
, pts
[0].x
- underlinePos
* sinEsc
, pts
[0].y
- underlinePos
* cosEsc
, &oldpt
);
2311 LineTo(hdc
, pts
[1].x
- underlinePos
* sinEsc
, pts
[1].y
- underlinePos
* cosEsc
);
2312 MoveToEx(hdc
, oldpt
.x
, oldpt
.y
, NULL
);
2313 DeleteObject(SelectObject(hdc
, hpen
));
2318 hpen
= CreatePen(PS_SOLID
, strikeoutWidth
, GetTextColor(hdc
));
2319 hpen
= SelectObject(hdc
, hpen
);
2322 pts
[1].x
= x
+ xwidth
;
2323 pts
[1].y
= y
- ywidth
;
2324 DPtoLP(hdc
, pts
, 2);
2325 MoveToEx(hdc
, pts
[0].x
- strikeoutPos
* sinEsc
, pts
[0].y
- strikeoutPos
* cosEsc
, &oldpt
);
2326 LineTo(hdc
, pts
[1].x
- strikeoutPos
* sinEsc
, pts
[1].y
- strikeoutPos
* cosEsc
);
2327 MoveToEx(hdc
, oldpt
.x
, oldpt
.y
, NULL
);
2328 DeleteObject(SelectObject(hdc
, hpen
));
2337 /***********************************************************************
2338 * TextOutA (GDI32.@)
2340 BOOL WINAPI
TextOutA( HDC hdc
, INT x
, INT y
, LPCSTR str
, INT count
)
2342 return ExtTextOutA( hdc
, x
, y
, 0, NULL
, str
, count
, NULL
);
2346 /***********************************************************************
2347 * TextOutW (GDI32.@)
2349 BOOL WINAPI
TextOutW(HDC hdc
, INT x
, INT y
, LPCWSTR str
, INT count
)
2351 return ExtTextOutW( hdc
, x
, y
, 0, NULL
, str
, count
, NULL
);
2355 /***********************************************************************
2356 * PolyTextOutA (GDI32.@)
2360 BOOL WINAPI
PolyTextOutA( HDC hdc
, const POLYTEXTA
*pptxt
, INT cStrings
)
2362 for (; cStrings
>0; cStrings
--, pptxt
++)
2363 if (!ExtTextOutA( hdc
, pptxt
->x
, pptxt
->y
, pptxt
->uiFlags
, &pptxt
->rcl
, pptxt
->lpstr
, pptxt
->n
, pptxt
->pdx
))
2370 /***********************************************************************
2371 * PolyTextOutW (GDI32.@)
2373 * Draw several Strings
2379 BOOL WINAPI
PolyTextOutW( HDC hdc
, const POLYTEXTW
*pptxt
, INT cStrings
)
2381 for (; cStrings
>0; cStrings
--, pptxt
++)
2382 if (!ExtTextOutW( hdc
, pptxt
->x
, pptxt
->y
, pptxt
->uiFlags
, &pptxt
->rcl
, pptxt
->lpstr
, pptxt
->n
, pptxt
->pdx
))
2388 /* FIXME: all following APIs ******************************************/
2391 /***********************************************************************
2392 * SetMapperFlags (GDI32.@)
2394 DWORD WINAPI
SetMapperFlags( HDC hDC
, DWORD dwFlag
)
2396 DC
*dc
= get_dc_ptr( hDC
);
2399 if(dc
->funcs
->pSetMapperFlags
)
2401 ret
= dc
->funcs
->pSetMapperFlags( dc
->physDev
, dwFlag
);
2402 /* FIXME: ret is just a success flag, we should return a proper value */
2405 FIXME("(%p, 0x%08x): stub - harmless\n", hDC
, dwFlag
);
2406 release_dc_ptr( dc
);
2410 /***********************************************************************
2411 * GetAspectRatioFilterEx (GDI.486)
2413 BOOL16 WINAPI
GetAspectRatioFilterEx16( HDC16 hdc
, LPSIZE16 pAspectRatio
)
2415 FIXME("(%04x, %p): -- Empty Stub !\n", hdc
, pAspectRatio
);
2419 /***********************************************************************
2420 * GetAspectRatioFilterEx (GDI32.@)
2422 BOOL WINAPI
GetAspectRatioFilterEx( HDC hdc
, LPSIZE pAspectRatio
)
2424 FIXME("(%p, %p): -- Empty Stub !\n", hdc
, pAspectRatio
);
2429 /***********************************************************************
2430 * GetCharABCWidthsA (GDI32.@)
2432 * See GetCharABCWidthsW.
2434 BOOL WINAPI
GetCharABCWidthsA(HDC hdc
, UINT firstChar
, UINT lastChar
,
2437 INT i
, wlen
, count
= (INT
)(lastChar
- firstChar
+ 1);
2442 if(count
<= 0) return FALSE
;
2444 str
= HeapAlloc(GetProcessHeap(), 0, count
);
2445 for(i
= 0; i
< count
; i
++)
2446 str
[i
] = (BYTE
)(firstChar
+ i
);
2448 wstr
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
2450 for(i
= 0; i
< wlen
; i
++)
2452 if(!GetCharABCWidthsW(hdc
, wstr
[i
], wstr
[i
], abc
))
2460 HeapFree(GetProcessHeap(), 0, str
);
2461 HeapFree(GetProcessHeap(), 0, wstr
);
2467 /******************************************************************************
2468 * GetCharABCWidthsW [GDI32.@]
2470 * Retrieves widths of characters in range.
2473 * hdc [I] Handle of device context
2474 * firstChar [I] First character in range to query
2475 * lastChar [I] Last character in range to query
2476 * abc [O] Address of character-width structure
2479 * Only works with TrueType fonts
2485 BOOL WINAPI
GetCharABCWidthsW( HDC hdc
, UINT firstChar
, UINT lastChar
,
2488 DC
*dc
= get_dc_ptr(hdc
);
2492 if (!dc
) return FALSE
;
2496 release_dc_ptr( dc
);
2501 ret
= WineEngGetCharABCWidths( dc
->gdiFont
, firstChar
, lastChar
, abc
);
2507 /* convert device units to logical */
2508 for( i
= firstChar
; i
<= lastChar
; i
++, abc
++ ) {
2509 abc
->abcA
= INTERNAL_XDSTOWS(dc
, abc
->abcA
);
2510 abc
->abcB
= INTERNAL_XDSTOWS(dc
, abc
->abcB
);
2511 abc
->abcC
= INTERNAL_XDSTOWS(dc
, abc
->abcC
);
2516 release_dc_ptr( dc
);
2521 /******************************************************************************
2522 * GetCharABCWidthsI [GDI32.@]
2524 * Retrieves widths of characters in range.
2527 * hdc [I] Handle of device context
2528 * firstChar [I] First glyphs in range to query
2529 * count [I] Last glyphs in range to query
2530 * pgi [i] Array of glyphs to query
2531 * abc [O] Address of character-width structure
2534 * Only works with TrueType fonts
2540 BOOL WINAPI
GetCharABCWidthsI( HDC hdc
, UINT firstChar
, UINT count
,
2541 LPWORD pgi
, LPABC abc
)
2543 DC
*dc
= get_dc_ptr(hdc
);
2547 if (!dc
) return FALSE
;
2551 release_dc_ptr( dc
);
2556 ret
= WineEngGetCharABCWidthsI( dc
->gdiFont
, firstChar
, count
, pgi
, abc
);
2562 /* convert device units to logical */
2563 for( i
= 0; i
< count
; i
++, abc
++ ) {
2564 abc
->abcA
= INTERNAL_XDSTOWS(dc
, abc
->abcA
);
2565 abc
->abcB
= INTERNAL_XDSTOWS(dc
, abc
->abcB
);
2566 abc
->abcC
= INTERNAL_XDSTOWS(dc
, abc
->abcC
);
2571 release_dc_ptr( dc
);
2576 /***********************************************************************
2577 * GetGlyphOutlineA (GDI32.@)
2579 DWORD WINAPI
GetGlyphOutlineA( HDC hdc
, UINT uChar
, UINT fuFormat
,
2580 LPGLYPHMETRICS lpgm
, DWORD cbBuffer
,
2581 LPVOID lpBuffer
, const MAT2
*lpmat2
)
2587 if(!(fuFormat
& GGO_GLYPH_INDEX
)) {
2590 if(uChar
> 0xff) { /* but, 2 bytes character only */
2592 mbchs
[0] = (uChar
& 0xff00) >> 8;
2593 mbchs
[1] = (uChar
& 0xff);
2596 mbchs
[0] = (uChar
& 0xff);
2598 p
= FONT_mbtowc(hdc
, mbchs
, len
, NULL
, NULL
);
2602 ret
= GetGlyphOutlineW(hdc
, c
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
,
2604 HeapFree(GetProcessHeap(), 0, p
);
2608 /***********************************************************************
2609 * GetGlyphOutlineW (GDI32.@)
2611 DWORD WINAPI
GetGlyphOutlineW( HDC hdc
, UINT uChar
, UINT fuFormat
,
2612 LPGLYPHMETRICS lpgm
, DWORD cbBuffer
,
2613 LPVOID lpBuffer
, const MAT2
*lpmat2
)
2615 DC
*dc
= get_dc_ptr(hdc
);
2618 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2619 hdc
, uChar
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
, lpmat2
);
2621 if(!dc
) return GDI_ERROR
;
2624 ret
= WineEngGetGlyphOutline(dc
->gdiFont
, uChar
, fuFormat
, lpgm
,
2625 cbBuffer
, lpBuffer
, lpmat2
);
2629 release_dc_ptr( dc
);
2634 /***********************************************************************
2635 * CreateScalableFontResourceA (GDI32.@)
2637 BOOL WINAPI
CreateScalableFontResourceA( DWORD fHidden
,
2638 LPCSTR lpszResourceFile
,
2639 LPCSTR lpszFontFile
,
2640 LPCSTR lpszCurrentPath
)
2644 /* fHidden=1 - only visible for the calling app, read-only, not
2645 * enumbered with EnumFonts/EnumFontFamilies
2646 * lpszCurrentPath can be NULL
2648 FIXME("(%d,%s,%s,%s): stub\n",
2649 fHidden
, debugstr_a(lpszResourceFile
), debugstr_a(lpszFontFile
),
2650 debugstr_a(lpszCurrentPath
) );
2652 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2653 if ((f
= CreateFileA(lpszResourceFile
, 0, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, 0)) != INVALID_HANDLE_VALUE
) {
2655 SetLastError(ERROR_FILE_EXISTS
);
2658 return FALSE
; /* create failed */
2661 /***********************************************************************
2662 * CreateScalableFontResourceW (GDI32.@)
2664 BOOL WINAPI
CreateScalableFontResourceW( DWORD fHidden
,
2665 LPCWSTR lpszResourceFile
,
2666 LPCWSTR lpszFontFile
,
2667 LPCWSTR lpszCurrentPath
)
2669 FIXME("(%d,%p,%p,%p): stub\n",
2670 fHidden
, lpszResourceFile
, lpszFontFile
, lpszCurrentPath
);
2671 return FALSE
; /* create failed */
2674 /*************************************************************************
2675 * GetKerningPairsA (GDI32.@)
2677 DWORD WINAPI
GetKerningPairsA( HDC hDC
, DWORD cPairs
,
2678 LPKERNINGPAIR kern_pairA
)
2683 DWORD i
, total_kern_pairs
, kern_pairs_copied
= 0;
2684 KERNINGPAIR
*kern_pairW
;
2686 if (!cPairs
&& kern_pairA
)
2688 SetLastError(ERROR_INVALID_PARAMETER
);
2692 charset
= GetTextCharset(hDC
);
2693 if (!TranslateCharsetInfo(ULongToPtr(charset
), &csi
, TCI_SRCCHARSET
))
2695 FIXME("Can't find codepage for charset %d\n", charset
);
2698 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2699 * to fail on an invalid character for CP_SYMBOL.
2701 cpi
.DefaultChar
[0] = 0;
2702 if (csi
.ciACP
!= CP_SYMBOL
&& !GetCPInfo(csi
.ciACP
, &cpi
))
2704 FIXME("Can't find codepage %u info\n", csi
.ciACP
);
2707 TRACE("charset %d => codepage %u\n", charset
, csi
.ciACP
);
2709 total_kern_pairs
= GetKerningPairsW(hDC
, 0, NULL
);
2710 if (!total_kern_pairs
) return 0;
2712 kern_pairW
= HeapAlloc(GetProcessHeap(), 0, total_kern_pairs
* sizeof(*kern_pairW
));
2713 GetKerningPairsW(hDC
, total_kern_pairs
, kern_pairW
);
2715 for (i
= 0; i
< total_kern_pairs
; i
++)
2719 if (!WideCharToMultiByte(csi
.ciACP
, 0, &kern_pairW
[i
].wFirst
, 1, &first
, 1, NULL
, NULL
))
2722 if (!WideCharToMultiByte(csi
.ciACP
, 0, &kern_pairW
[i
].wSecond
, 1, &second
, 1, NULL
, NULL
))
2725 if (first
== cpi
.DefaultChar
[0] || second
== cpi
.DefaultChar
[0])
2730 if (kern_pairs_copied
>= cPairs
) break;
2732 kern_pairA
->wFirst
= (BYTE
)first
;
2733 kern_pairA
->wSecond
= (BYTE
)second
;
2734 kern_pairA
->iKernAmount
= kern_pairW
[i
].iKernAmount
;
2737 kern_pairs_copied
++;
2740 HeapFree(GetProcessHeap(), 0, kern_pairW
);
2742 return kern_pairs_copied
;
2745 /*************************************************************************
2746 * GetKerningPairsW (GDI32.@)
2748 DWORD WINAPI
GetKerningPairsW( HDC hDC
, DWORD cPairs
,
2749 LPKERNINGPAIR lpKerningPairs
)
2754 TRACE("(%p,%d,%p)\n", hDC
, cPairs
, lpKerningPairs
);
2756 if (!cPairs
&& lpKerningPairs
)
2758 SetLastError(ERROR_INVALID_PARAMETER
);
2762 dc
= get_dc_ptr(hDC
);
2766 ret
= WineEngGetKerningPairs(dc
->gdiFont
, cPairs
, lpKerningPairs
);
2768 release_dc_ptr( dc
);
2772 /*************************************************************************
2773 * TranslateCharsetInfo [GDI32.@]
2775 * Fills a CHARSETINFO structure for a character set, code page, or
2776 * font. This allows making the correspondence between different labels
2777 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2778 * of the same encoding.
2780 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2781 * only one codepage should be set in *lpSrc.
2784 * TRUE on success, FALSE on failure.
2787 BOOL WINAPI
TranslateCharsetInfo(
2788 LPDWORD lpSrc
, /* [in]
2789 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2790 if flags == TCI_SRCCHARSET: a character set value
2791 if flags == TCI_SRCCODEPAGE: a code page value
2793 LPCHARSETINFO lpCs
, /* [out] structure to receive charset information */
2794 DWORD flags
/* [in] determines interpretation of lpSrc */)
2798 case TCI_SRCFONTSIG
:
2799 while (!(*lpSrc
>>index
& 0x0001) && index
<MAXTCIINDEX
) index
++;
2801 case TCI_SRCCODEPAGE
:
2802 while (PtrToUlong(lpSrc
) != FONT_tci
[index
].ciACP
&& index
< MAXTCIINDEX
) index
++;
2804 case TCI_SRCCHARSET
:
2805 while (PtrToUlong(lpSrc
) != FONT_tci
[index
].ciCharset
&& index
< MAXTCIINDEX
) index
++;
2810 if (index
>= MAXTCIINDEX
|| FONT_tci
[index
].ciCharset
== DEFAULT_CHARSET
) return FALSE
;
2811 memcpy(lpCs
, &FONT_tci
[index
], sizeof(CHARSETINFO
));
2815 /*************************************************************************
2816 * GetFontLanguageInfo (GDI32.@)
2818 DWORD WINAPI
GetFontLanguageInfo(HDC hdc
)
2820 FONTSIGNATURE fontsig
;
2821 static const DWORD GCP_DBCS_MASK
=0x003F0000,
2822 GCP_DIACRITIC_MASK
=0x00000000,
2823 FLI_GLYPHS_MASK
=0x00000000,
2824 GCP_GLYPHSHAPE_MASK
=0x00000040,
2825 GCP_KASHIDA_MASK
=0x00000000,
2826 GCP_LIGATE_MASK
=0x00000000,
2827 GCP_USEKERNING_MASK
=0x00000000,
2828 GCP_REORDER_MASK
=0x00000060;
2832 GetTextCharsetInfo( hdc
, &fontsig
, 0 );
2833 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2835 if( (fontsig
.fsCsb
[0]&GCP_DBCS_MASK
)!=0 )
2838 if( (fontsig
.fsCsb
[0]&GCP_DIACRITIC_MASK
)!=0 )
2839 result
|=GCP_DIACRITIC
;
2841 if( (fontsig
.fsCsb
[0]&FLI_GLYPHS_MASK
)!=0 )
2844 if( (fontsig
.fsCsb
[0]&GCP_GLYPHSHAPE_MASK
)!=0 )
2845 result
|=GCP_GLYPHSHAPE
;
2847 if( (fontsig
.fsCsb
[0]&GCP_KASHIDA_MASK
)!=0 )
2848 result
|=GCP_KASHIDA
;
2850 if( (fontsig
.fsCsb
[0]&GCP_LIGATE_MASK
)!=0 )
2853 if( (fontsig
.fsCsb
[0]&GCP_USEKERNING_MASK
)!=0 )
2854 result
|=GCP_USEKERNING
;
2856 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2857 if( GetTextAlign( hdc
) & TA_RTLREADING
)
2858 if( (fontsig
.fsCsb
[0]&GCP_REORDER_MASK
)!=0 )
2859 result
|=GCP_REORDER
;
2865 /*************************************************************************
2866 * GetFontData [GDI32.@]
2868 * Retrieve data for TrueType font.
2872 * success: Number of bytes returned
2873 * failure: GDI_ERROR
2877 * Calls SetLastError()
2880 DWORD WINAPI
GetFontData(HDC hdc
, DWORD table
, DWORD offset
,
2881 LPVOID buffer
, DWORD length
)
2883 DC
*dc
= get_dc_ptr(hdc
);
2884 DWORD ret
= GDI_ERROR
;
2886 if(!dc
) return GDI_ERROR
;
2889 ret
= WineEngGetFontData(dc
->gdiFont
, table
, offset
, buffer
, length
);
2891 release_dc_ptr( dc
);
2895 /*************************************************************************
2896 * GetGlyphIndicesA [GDI32.@]
2898 DWORD WINAPI
GetGlyphIndicesA(HDC hdc
, LPCSTR lpstr
, INT count
,
2899 LPWORD pgi
, DWORD flags
)
2905 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2906 hdc
, debugstr_an(lpstr
, count
), count
, pgi
, flags
);
2908 lpstrW
= FONT_mbtowc(hdc
, lpstr
, count
, &countW
, NULL
);
2909 ret
= GetGlyphIndicesW(hdc
, lpstrW
, countW
, pgi
, flags
);
2910 HeapFree(GetProcessHeap(), 0, lpstrW
);
2915 /*************************************************************************
2916 * GetGlyphIndicesW [GDI32.@]
2918 DWORD WINAPI
GetGlyphIndicesW(HDC hdc
, LPCWSTR lpstr
, INT count
,
2919 LPWORD pgi
, DWORD flags
)
2921 DC
*dc
= get_dc_ptr(hdc
);
2922 DWORD ret
= GDI_ERROR
;
2924 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2925 hdc
, debugstr_wn(lpstr
, count
), count
, pgi
, flags
);
2927 if(!dc
) return GDI_ERROR
;
2930 ret
= WineEngGetGlyphIndices(dc
->gdiFont
, lpstr
, count
, pgi
, flags
);
2932 release_dc_ptr( dc
);
2936 /*************************************************************************
2937 * GetCharacterPlacementA [GDI32.@]
2939 * See GetCharacterPlacementW.
2942 * the web browser control of ie4 calls this with dwFlags=0
2945 GetCharacterPlacementA(HDC hdc
, LPCSTR lpString
, INT uCount
,
2946 INT nMaxExtent
, GCP_RESULTSA
*lpResults
,
2951 GCP_RESULTSW resultsW
;
2955 TRACE("%s, %d, %d, 0x%08x\n",
2956 debugstr_an(lpString
, uCount
), uCount
, nMaxExtent
, dwFlags
);
2958 /* both structs are equal in size */
2959 memcpy(&resultsW
, lpResults
, sizeof(resultsW
));
2961 lpStringW
= FONT_mbtowc(hdc
, lpString
, uCount
, &uCountW
, &font_cp
);
2962 if(lpResults
->lpOutString
)
2963 resultsW
.lpOutString
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*uCountW
);
2965 ret
= GetCharacterPlacementW(hdc
, lpStringW
, uCountW
, nMaxExtent
, &resultsW
, dwFlags
);
2967 lpResults
->nGlyphs
= resultsW
.nGlyphs
;
2968 lpResults
->nMaxFit
= resultsW
.nMaxFit
;
2970 if(lpResults
->lpOutString
) {
2971 WideCharToMultiByte(font_cp
, 0, resultsW
.lpOutString
, uCountW
,
2972 lpResults
->lpOutString
, uCount
, NULL
, NULL
);
2975 HeapFree(GetProcessHeap(), 0, lpStringW
);
2976 HeapFree(GetProcessHeap(), 0, resultsW
.lpOutString
);
2981 /*************************************************************************
2982 * GetCharacterPlacementW [GDI32.@]
2984 * Retrieve information about a string. This includes the width, reordering,
2985 * Glyphing and so on.
2989 * The width and height of the string if successful, 0 if failed.
2993 * All flags except GCP_REORDER are not yet implemented.
2994 * Reordering is not 100% complient to the Windows BiDi method.
2995 * Caret positioning is not yet implemented for BiDi.
2996 * Classes are not yet implemented.
3000 GetCharacterPlacementW(
3001 HDC hdc
, /* [in] Device context for which the rendering is to be done */
3002 LPCWSTR lpString
, /* [in] The string for which information is to be returned */
3003 INT uCount
, /* [in] Number of WORDS in string. */
3004 INT nMaxExtent
, /* [in] Maximum extent the string is to take (in HDC logical units) */
3005 GCP_RESULTSW
*lpResults
,/* [in/out] A pointer to a GCP_RESULTSW struct */
3006 DWORD dwFlags
/* [in] Flags specifying how to process the string */
3013 TRACE("%s, %d, %d, 0x%08x\n",
3014 debugstr_wn(lpString
, uCount
), uCount
, nMaxExtent
, dwFlags
);
3016 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
3017 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
3018 lpResults
->lStructSize
, lpResults
->lpOutString
, lpResults
->lpOrder
,
3019 lpResults
->lpDx
, lpResults
->lpCaretPos
, lpResults
->lpClass
,
3020 lpResults
->lpGlyphs
, lpResults
->nGlyphs
, lpResults
->nMaxFit
);
3022 if(dwFlags
&(~GCP_REORDER
)) FIXME("flags 0x%08x ignored\n", dwFlags
);
3023 if(lpResults
->lpClass
) FIXME("classes not implemented\n");
3024 if (lpResults
->lpCaretPos
&& (dwFlags
& GCP_REORDER
))
3025 FIXME("Caret positions for complex scripts not implemented\n");
3027 nSet
= (UINT
)uCount
;
3028 if(nSet
> lpResults
->nGlyphs
)
3029 nSet
= lpResults
->nGlyphs
;
3031 /* return number of initialized fields */
3032 lpResults
->nGlyphs
= nSet
;
3034 if((dwFlags
&GCP_REORDER
)==0 )
3036 /* Treat the case where no special handling was requested in a fastpath way */
3037 /* copy will do if the GCP_REORDER flag is not set */
3038 if(lpResults
->lpOutString
)
3039 memcpy( lpResults
->lpOutString
, lpString
, nSet
* sizeof(WCHAR
));
3041 if(lpResults
->lpOrder
)
3043 for(i
= 0; i
< nSet
; i
++)
3044 lpResults
->lpOrder
[i
] = i
;
3048 BIDI_Reorder( lpString
, uCount
, dwFlags
, WINE_GCPW_FORCE_LTR
, lpResults
->lpOutString
,
3049 nSet
, lpResults
->lpOrder
);
3052 /* FIXME: Will use the placement chars */
3053 if (lpResults
->lpDx
)
3056 for (i
= 0; i
< nSet
; i
++)
3058 if (GetCharWidth32W(hdc
, lpString
[i
], lpString
[i
], &c
))
3059 lpResults
->lpDx
[i
]= c
;
3063 if (lpResults
->lpCaretPos
&& !(dwFlags
& GCP_REORDER
))
3067 lpResults
->lpCaretPos
[0] = 0;
3068 for (i
= 1; i
< nSet
; i
++)
3069 if (GetTextExtentPoint32W(hdc
, &(lpString
[i
- 1]), 1, &size
))
3070 lpResults
->lpCaretPos
[i
] = (pos
+= size
.cx
);
3073 if(lpResults
->lpGlyphs
)
3074 GetGlyphIndicesW(hdc
, lpString
, nSet
, lpResults
->lpGlyphs
, 0);
3076 if (GetTextExtentPoint32W(hdc
, lpString
, uCount
, &size
))
3077 ret
= MAKELONG(size
.cx
, size
.cy
);
3082 /*************************************************************************
3083 * GetCharABCWidthsFloatA [GDI32.@]
3085 * See GetCharABCWidthsFloatW.
3087 BOOL WINAPI
GetCharABCWidthsFloatA( HDC hdc
, UINT first
, UINT last
, LPABCFLOAT abcf
)
3089 INT i
, wlen
, count
= (INT
)(last
- first
+ 1);
3094 if (count
<= 0) return FALSE
;
3096 str
= HeapAlloc(GetProcessHeap(), 0, count
);
3098 for(i
= 0; i
< count
; i
++)
3099 str
[i
] = (BYTE
)(first
+ i
);
3101 wstr
= FONT_mbtowc( hdc
, str
, count
, &wlen
, NULL
);
3103 for (i
= 0; i
< wlen
; i
++)
3105 if (!GetCharABCWidthsFloatW( hdc
, wstr
[i
], wstr
[i
], abcf
))
3113 HeapFree( GetProcessHeap(), 0, str
);
3114 HeapFree( GetProcessHeap(), 0, wstr
);
3119 /*************************************************************************
3120 * GetCharABCWidthsFloatW [GDI32.@]
3122 * Retrieves widths of a range of characters.
3125 * hdc [I] Handle to device context.
3126 * first [I] First character in range to query.
3127 * last [I] Last character in range to query.
3128 * abcf [O] Array of LPABCFLOAT structures.
3135 * Only works with TrueType fonts. It also doesn't return real
3136 * floats but converted integers because it's implemented on
3137 * top of GetCharABCWidthsW.
3139 BOOL WINAPI
GetCharABCWidthsFloatW( HDC hdc
, UINT first
, UINT last
, LPABCFLOAT abcf
)
3142 unsigned int i
, size
= sizeof(ABC
) * (last
- first
+ 1);
3145 TRACE("%p, %d, %d, %p - partial stub\n", hdc
, first
, last
, abcf
);
3147 abc
= HeapAlloc( GetProcessHeap(), 0, size
);
3148 if (!abc
) return FALSE
;
3150 ret
= GetCharABCWidthsW( hdc
, first
, last
, abc
);
3153 for (i
= first
; i
<= last
; i
++, abc
++, abcf
++)
3155 abcf
->abcfA
= abc
->abcA
;
3156 abcf
->abcfB
= abc
->abcB
;
3157 abcf
->abcfC
= abc
->abcC
;
3160 HeapFree( GetProcessHeap(), 0, abc
);
3164 /*************************************************************************
3165 * GetCharWidthFloatA [GDI32.@]
3167 BOOL WINAPI
GetCharWidthFloatA(HDC hdc
, UINT iFirstChar
,
3168 UINT iLastChar
, PFLOAT pxBuffer
)
3170 FIXME("%p, %u, %u, %p: stub!\n", hdc
, iFirstChar
, iLastChar
, pxBuffer
);
3174 /*************************************************************************
3175 * GetCharWidthFloatW [GDI32.@]
3177 BOOL WINAPI
GetCharWidthFloatW(HDC hdc
, UINT iFirstChar
,
3178 UINT iLastChar
, PFLOAT pxBuffer
)
3180 FIXME("%p, %u, %u, %p: stub!\n", hdc
, iFirstChar
, iLastChar
, pxBuffer
);
3185 /***********************************************************************
3187 * Font Resource API *
3189 ***********************************************************************/
3191 /***********************************************************************
3192 * AddFontResourceA (GDI32.@)
3194 INT WINAPI
AddFontResourceA( LPCSTR str
)
3196 return AddFontResourceExA( str
, 0, NULL
);
3199 /***********************************************************************
3200 * AddFontResourceW (GDI32.@)
3202 INT WINAPI
AddFontResourceW( LPCWSTR str
)
3204 return AddFontResourceExW(str
, 0, NULL
);
3208 /***********************************************************************
3209 * AddFontResourceExA (GDI32.@)
3211 INT WINAPI
AddFontResourceExA( LPCSTR str
, DWORD fl
, PVOID pdv
)
3213 DWORD len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
3214 LPWSTR strW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3217 MultiByteToWideChar(CP_ACP
, 0, str
, -1, strW
, len
);
3218 ret
= AddFontResourceExW(strW
, fl
, pdv
);
3219 HeapFree(GetProcessHeap(), 0, strW
);
3223 static BOOL CALLBACK
load_enumed_resource(HMODULE hModule
, LPCWSTR type
, LPWSTR name
, LONG_PTR lParam
)
3225 HRSRC rsrc
= FindResourceW(hModule
, name
, type
);
3226 HGLOBAL hMem
= LoadResource(hModule
, rsrc
);
3227 LPVOID
*pMem
= LockResource(hMem
);
3228 int *num_total
= (int *)lParam
;
3231 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type
));
3232 if (!AddFontMemResourceEx(pMem
, SizeofResource(hModule
, rsrc
), NULL
, &num_in_res
))
3234 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule
, hMem
);
3238 *num_total
+= num_in_res
;
3242 /***********************************************************************
3243 * AddFontResourceExW (GDI32.@)
3245 INT WINAPI
AddFontResourceExW( LPCWSTR str
, DWORD fl
, PVOID pdv
)
3247 int ret
= WineEngAddFontResourceEx(str
, fl
, pdv
);
3250 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3251 HMODULE hModule
= LoadLibraryExW(str
, NULL
, LOAD_LIBRARY_AS_DATAFILE
);
3252 if (hModule
!= NULL
)
3254 int num_resources
= 0;
3255 LPWSTR rt_font
= (LPWSTR
)((ULONG_PTR
)8); /* we don't want to include winuser.h */
3257 TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3258 wine_dbgstr_w(str
));
3259 if (EnumResourceNamesW(hModule
, rt_font
, load_enumed_resource
, (LONG_PTR
)&num_resources
))
3260 ret
= num_resources
;
3261 FreeLibrary(hModule
);
3267 /***********************************************************************
3268 * RemoveFontResourceA (GDI32.@)
3270 BOOL WINAPI
RemoveFontResourceA( LPCSTR str
)
3272 return RemoveFontResourceExA(str
, 0, 0);
3275 /***********************************************************************
3276 * RemoveFontResourceW (GDI32.@)
3278 BOOL WINAPI
RemoveFontResourceW( LPCWSTR str
)
3280 return RemoveFontResourceExW(str
, 0, 0);
3283 /***********************************************************************
3284 * AddFontMemResourceEx (GDI32.@)
3286 HANDLE WINAPI
AddFontMemResourceEx( PVOID pbFont
, DWORD cbFont
, PVOID pdv
, DWORD
*pcFonts
)
3288 return WineEngAddFontMemResourceEx(pbFont
, cbFont
, pdv
, pcFonts
);
3291 /***********************************************************************
3292 * RemoveFontMemResourceEx (GDI32.@)
3294 BOOL WINAPI
RemoveFontMemResourceEx( HANDLE fh
)
3296 FIXME("(%p) stub\n", fh
);
3300 /***********************************************************************
3301 * RemoveFontResourceExA (GDI32.@)
3303 BOOL WINAPI
RemoveFontResourceExA( LPCSTR str
, DWORD fl
, PVOID pdv
)
3305 DWORD len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
3306 LPWSTR strW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3309 MultiByteToWideChar(CP_ACP
, 0, str
, -1, strW
, len
);
3310 ret
= RemoveFontResourceExW(strW
, fl
, pdv
);
3311 HeapFree(GetProcessHeap(), 0, strW
);
3315 /***********************************************************************
3316 * RemoveFontResourceExW (GDI32.@)
3318 BOOL WINAPI
RemoveFontResourceExW( LPCWSTR str
, DWORD fl
, PVOID pdv
)
3320 return WineEngRemoveFontResourceEx(str
, fl
, pdv
);
3323 /***********************************************************************
3324 * GetTextCharset (GDI32.@)
3326 UINT WINAPI
GetTextCharset(HDC hdc
)
3328 /* MSDN docs say this is equivalent */
3329 return GetTextCharsetInfo(hdc
, NULL
, 0);
3332 /***********************************************************************
3333 * GetTextCharsetInfo (GDI32.@)
3335 UINT WINAPI
GetTextCharsetInfo(HDC hdc
, LPFONTSIGNATURE fs
, DWORD flags
)
3337 UINT ret
= DEFAULT_CHARSET
;
3338 DC
*dc
= get_dc_ptr(hdc
);
3343 ret
= WineEngGetTextCharsetInfo(dc
->gdiFont
, fs
, flags
);
3345 release_dc_ptr( dc
);
3348 if (ret
== DEFAULT_CHARSET
&& fs
)
3349 memset(fs
, 0, sizeof(FONTSIGNATURE
));
3353 /***********************************************************************
3354 * GdiGetCharDimensions (GDI32.@)
3356 * Gets the average width of the characters in the English alphabet.
3359 * hdc [I] Handle to the device context to measure on.
3360 * lptm [O] Pointer to memory to store the text metrics into.
3361 * height [O] On exit, the maximum height of characters in the English alphabet.
3364 * The average width of characters in the English alphabet.
3367 * This function is used by the dialog manager to get the size of a dialog
3368 * unit. It should also be used by other pieces of code that need to know
3369 * the size of a dialog unit in logical units without having access to the
3370 * window handle of the dialog.
3371 * Windows caches the font metrics from this function, but we don't and
3372 * there doesn't appear to be an immediate advantage to do so.
3375 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3377 LONG WINAPI
GdiGetCharDimensions(HDC hdc
, LPTEXTMETRICW lptm
, LONG
*height
)
3380 static const WCHAR alphabet
[] = {
3381 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3382 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3383 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3385 if(lptm
&& !GetTextMetricsW(hdc
, lptm
)) return 0;
3387 if(!GetTextExtentPointW(hdc
, alphabet
, 52, &sz
)) return 0;
3389 if (height
) *height
= sz
.cy
;
3390 return (sz
.cx
/ 26 + 1) / 2;
3393 BOOL WINAPI
EnableEUDC(BOOL fEnableEUDC
)
3395 FIXME("(%d): stub\n", fEnableEUDC
);
3399 /***********************************************************************
3400 * GetCharWidthI (GDI32.@)
3402 * Retrieve widths of characters.
3405 * hdc [I] Handle to a device context.
3406 * first [I] First glyph in range to query.
3407 * count [I] Number of glyph indices to query.
3408 * glyphs [I] Array of glyphs to query.
3409 * buffer [O] Buffer to receive character widths.
3412 * Only works with TrueType fonts.
3418 BOOL WINAPI
GetCharWidthI(HDC hdc
, UINT first
, UINT count
, LPWORD glyphs
, LPINT buffer
)
3423 TRACE("(%p, %d, %d, %p, %p)\n", hdc
, first
, count
, glyphs
, buffer
);
3425 if (!(abc
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(ABC
))))
3428 if (!GetCharABCWidthsI(hdc
, first
, count
, glyphs
, abc
))
3430 HeapFree(GetProcessHeap(), 0, abc
);
3434 for (i
= 0; i
< count
; i
++)
3435 buffer
[i
] = abc
->abcA
+ abc
->abcB
+ abc
->abcC
;
3437 HeapFree(GetProcessHeap(), 0, abc
);
3441 /***********************************************************************
3442 * GetFontUnicodeRanges (GDI32.@)
3444 * Retrieve a list of supported Unicode characters in a font.
3447 * hdc [I] Handle to a device context.
3448 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3451 * Success: Number of bytes written to the buffer pointed to by lpgs.
3455 DWORD WINAPI
GetFontUnicodeRanges(HDC hdc
, LPGLYPHSET lpgs
)
3458 DC
*dc
= get_dc_ptr(hdc
);
3460 TRACE("(%p, %p)\n", hdc
, lpgs
);
3464 if (dc
->gdiFont
) ret
= WineEngGetFontUnicodeRanges(dc
->gdiFont
, lpgs
);
3470 /*************************************************************
3471 * FontIsLinked (GDI32.@)
3473 BOOL WINAPI
FontIsLinked(HDC hdc
)
3475 DC
*dc
= get_dc_ptr(hdc
);
3478 if (!dc
) return FALSE
;
3479 if (dc
->gdiFont
) ret
= WineEngFontIsLinked(dc
->gdiFont
);
3481 TRACE("returning %d\n", ret
);