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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include "wine/port.h"
36 #include "gdi_private.h"
37 #include "wine/unicode.h"
38 #include "wine/debug.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(font
);
41 WINE_DECLARE_DEBUG_CHANNEL(gdi
);
43 /* Device -> World size conversion */
45 /* Performs a device to world transformation on the specified width (which
46 * is in integer format).
48 static inline INT
INTERNAL_XDSTOWS(DC
*dc
, INT width
)
52 /* Perform operation with floating point */
53 floatWidth
= (FLOAT
)width
* dc
->xformVport2World
.eM11
;
54 /* Round to integers */
55 return GDI_ROUND(floatWidth
);
58 /* Performs a device to world transformation on the specified size (which
59 * is in integer format).
61 static inline INT
INTERNAL_YDSTOWS(DC
*dc
, INT height
)
65 /* Perform operation with floating point */
66 floatHeight
= (FLOAT
)height
* dc
->xformVport2World
.eM22
;
67 /* Round to integers */
68 return GDI_ROUND(floatHeight
);
71 static inline INT
INTERNAL_XWSTODS(DC
*dc
, INT width
)
74 pt
[0].x
= pt
[0].y
= 0;
77 LPtoDP(dc
->hSelf
, pt
, 2);
78 return pt
[1].x
- pt
[0].x
;
81 static inline INT
INTERNAL_YWSTODS(DC
*dc
, INT height
)
84 pt
[0].x
= pt
[0].y
= 0;
87 LPtoDP(dc
->hSelf
, pt
, 2);
88 return pt
[1].y
- pt
[0].y
;
91 static HGDIOBJ
FONT_SelectObject( HGDIOBJ handle
, void *obj
, HDC hdc
);
92 static INT
FONT_GetObject16( HGDIOBJ handle
, void *obj
, INT count
, LPVOID buffer
);
93 static INT
FONT_GetObjectA( HGDIOBJ handle
, void *obj
, INT count
, LPVOID buffer
);
94 static INT
FONT_GetObjectW( HGDIOBJ handle
, void *obj
, INT count
, LPVOID buffer
);
95 static BOOL
FONT_DeleteObject( HGDIOBJ handle
, void *obj
);
97 static const struct gdi_obj_funcs font_funcs
=
99 FONT_SelectObject
, /* pSelectObject */
100 FONT_GetObject16
, /* pGetObject16 */
101 FONT_GetObjectA
, /* pGetObjectA */
102 FONT_GetObjectW
, /* pGetObjectW */
103 NULL
, /* pUnrealizeObject */
104 FONT_DeleteObject
/* pDeleteObject */
107 #define ENUM_UNICODE 0x00000001
108 #define ENUM_CALLED 0x00000002
118 LPLOGFONT16 lpLogFontParam
;
119 FONTENUMPROC16 lpEnumFunc
;
122 LPNEWTEXTMETRICEX16 lpTextMetric
;
123 LPENUMLOGFONTEX16 lpLogFont
;
124 SEGPTR segTextMetric
;
134 LPLOGFONTW lpLogFontParam
;
135 FONTENUMPROCW lpEnumFunc
;
144 * For TranslateCharsetInfo
146 #define FS(x) {{0,0,0,0},{0x1<<(x),0}}
147 #define MAXTCIINDEX 32
148 static const CHARSETINFO FONT_tci
[MAXTCIINDEX
] = {
150 { ANSI_CHARSET
, 1252, FS(0)},
151 { EASTEUROPE_CHARSET
, 1250, FS(1)},
152 { RUSSIAN_CHARSET
, 1251, FS(2)},
153 { GREEK_CHARSET
, 1253, FS(3)},
154 { TURKISH_CHARSET
, 1254, FS(4)},
155 { HEBREW_CHARSET
, 1255, FS(5)},
156 { ARABIC_CHARSET
, 1256, FS(6)},
157 { BALTIC_CHARSET
, 1257, FS(7)},
158 { VIETNAMESE_CHARSET
, 1258, FS(8)},
159 /* reserved by ANSI */
160 { DEFAULT_CHARSET
, 0, FS(0)},
161 { DEFAULT_CHARSET
, 0, FS(0)},
162 { DEFAULT_CHARSET
, 0, FS(0)},
163 { DEFAULT_CHARSET
, 0, FS(0)},
164 { DEFAULT_CHARSET
, 0, FS(0)},
165 { DEFAULT_CHARSET
, 0, FS(0)},
166 { DEFAULT_CHARSET
, 0, FS(0)},
168 { THAI_CHARSET
, 874, FS(16)},
169 { SHIFTJIS_CHARSET
, 932, FS(17)},
170 { GB2312_CHARSET
, 936, FS(18)},
171 { HANGEUL_CHARSET
, 949, FS(19)},
172 { CHINESEBIG5_CHARSET
, 950, FS(20)},
173 { JOHAB_CHARSET
, 1361, FS(21)},
174 /* reserved for alternate ANSI and OEM */
175 { DEFAULT_CHARSET
, 0, FS(0)},
176 { DEFAULT_CHARSET
, 0, FS(0)},
177 { DEFAULT_CHARSET
, 0, FS(0)},
178 { DEFAULT_CHARSET
, 0, FS(0)},
179 { DEFAULT_CHARSET
, 0, FS(0)},
180 { DEFAULT_CHARSET
, 0, FS(0)},
181 { DEFAULT_CHARSET
, 0, FS(0)},
182 { DEFAULT_CHARSET
, 0, FS(0)},
183 /* reserved for system */
184 { DEFAULT_CHARSET
, 0, FS(0)},
185 { SYMBOL_CHARSET
, CP_SYMBOL
, FS(31)},
188 /***********************************************************************
189 * LOGFONT conversion functions.
191 static void FONT_LogFontWTo16( const LOGFONTW
* font32
, LPLOGFONT16 font16
)
193 font16
->lfHeight
= font32
->lfHeight
;
194 font16
->lfWidth
= font32
->lfWidth
;
195 font16
->lfEscapement
= font32
->lfEscapement
;
196 font16
->lfOrientation
= font32
->lfOrientation
;
197 font16
->lfWeight
= font32
->lfWeight
;
198 font16
->lfItalic
= font32
->lfItalic
;
199 font16
->lfUnderline
= font32
->lfUnderline
;
200 font16
->lfStrikeOut
= font32
->lfStrikeOut
;
201 font16
->lfCharSet
= font32
->lfCharSet
;
202 font16
->lfOutPrecision
= font32
->lfOutPrecision
;
203 font16
->lfClipPrecision
= font32
->lfClipPrecision
;
204 font16
->lfQuality
= font32
->lfQuality
;
205 font16
->lfPitchAndFamily
= font32
->lfPitchAndFamily
;
206 WideCharToMultiByte( CP_ACP
, 0, font32
->lfFaceName
, -1,
207 font16
->lfFaceName
, LF_FACESIZE
, NULL
, NULL
);
208 font16
->lfFaceName
[LF_FACESIZE
-1] = 0;
211 static void FONT_LogFont16ToW( const LOGFONT16
*font16
, LPLOGFONTW font32
)
213 font32
->lfHeight
= font16
->lfHeight
;
214 font32
->lfWidth
= font16
->lfWidth
;
215 font32
->lfEscapement
= font16
->lfEscapement
;
216 font32
->lfOrientation
= font16
->lfOrientation
;
217 font32
->lfWeight
= font16
->lfWeight
;
218 font32
->lfItalic
= font16
->lfItalic
;
219 font32
->lfUnderline
= font16
->lfUnderline
;
220 font32
->lfStrikeOut
= font16
->lfStrikeOut
;
221 font32
->lfCharSet
= font16
->lfCharSet
;
222 font32
->lfOutPrecision
= font16
->lfOutPrecision
;
223 font32
->lfClipPrecision
= font16
->lfClipPrecision
;
224 font32
->lfQuality
= font16
->lfQuality
;
225 font32
->lfPitchAndFamily
= font16
->lfPitchAndFamily
;
226 MultiByteToWideChar( CP_ACP
, 0, font16
->lfFaceName
, -1, font32
->lfFaceName
, LF_FACESIZE
);
227 font32
->lfFaceName
[LF_FACESIZE
-1] = 0;
230 static void FONT_LogFontAToW( const LOGFONTA
*fontA
, LPLOGFONTW fontW
)
232 memcpy(fontW
, fontA
, sizeof(LOGFONTA
) - LF_FACESIZE
);
233 MultiByteToWideChar(CP_ACP
, 0, fontA
->lfFaceName
, -1, fontW
->lfFaceName
,
235 fontW
->lfFaceName
[LF_FACESIZE
-1] = 0;
238 static void FONT_LogFontWToA( const LOGFONTW
*fontW
, LPLOGFONTA fontA
)
240 memcpy(fontA
, fontW
, sizeof(LOGFONTA
) - LF_FACESIZE
);
241 WideCharToMultiByte(CP_ACP
, 0, fontW
->lfFaceName
, -1, fontA
->lfFaceName
,
242 LF_FACESIZE
, NULL
, NULL
);
243 fontA
->lfFaceName
[LF_FACESIZE
-1] = 0;
246 static void FONT_EnumLogFontExWTo16( const ENUMLOGFONTEXW
*fontW
, LPENUMLOGFONTEX16 font16
)
248 FONT_LogFontWTo16( (LPLOGFONTW
)fontW
, (LPLOGFONT16
)font16
);
250 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfFullName
, -1,
251 (LPSTR
) font16
->elfFullName
, LF_FULLFACESIZE
, NULL
, NULL
);
252 font16
->elfFullName
[LF_FULLFACESIZE
-1] = '\0';
253 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfStyle
, -1,
254 (LPSTR
) font16
->elfStyle
, LF_FACESIZE
, NULL
, NULL
);
255 font16
->elfStyle
[LF_FACESIZE
-1] = '\0';
256 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfScript
, -1,
257 (LPSTR
) font16
->elfScript
, LF_FACESIZE
, NULL
, NULL
);
258 font16
->elfScript
[LF_FACESIZE
-1] = '\0';
261 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW
*fontW
, LPENUMLOGFONTEXA fontA
)
263 FONT_LogFontWToA( (LPLOGFONTW
)fontW
, (LPLOGFONTA
)fontA
);
265 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfFullName
, -1,
266 (LPSTR
) fontA
->elfFullName
, LF_FULLFACESIZE
, NULL
, NULL
);
267 fontA
->elfFullName
[LF_FULLFACESIZE
-1] = '\0';
268 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfStyle
, -1,
269 (LPSTR
) fontA
->elfStyle
, LF_FACESIZE
, NULL
, NULL
);
270 fontA
->elfStyle
[LF_FACESIZE
-1] = '\0';
271 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfScript
, -1,
272 (LPSTR
) fontA
->elfScript
, LF_FACESIZE
, NULL
, NULL
);
273 fontA
->elfScript
[LF_FACESIZE
-1] = '\0';
276 /***********************************************************************
277 * TEXTMETRIC conversion functions.
279 static void FONT_TextMetricWToA(const TEXTMETRICW
*ptmW
, LPTEXTMETRICA ptmA
)
281 ptmA
->tmHeight
= ptmW
->tmHeight
;
282 ptmA
->tmAscent
= ptmW
->tmAscent
;
283 ptmA
->tmDescent
= ptmW
->tmDescent
;
284 ptmA
->tmInternalLeading
= ptmW
->tmInternalLeading
;
285 ptmA
->tmExternalLeading
= ptmW
->tmExternalLeading
;
286 ptmA
->tmAveCharWidth
= ptmW
->tmAveCharWidth
;
287 ptmA
->tmMaxCharWidth
= ptmW
->tmMaxCharWidth
;
288 ptmA
->tmWeight
= ptmW
->tmWeight
;
289 ptmA
->tmOverhang
= ptmW
->tmOverhang
;
290 ptmA
->tmDigitizedAspectX
= ptmW
->tmDigitizedAspectX
;
291 ptmA
->tmDigitizedAspectY
= ptmW
->tmDigitizedAspectY
;
292 ptmA
->tmFirstChar
= ptmW
->tmFirstChar
> 255 ? 255 : ptmW
->tmFirstChar
;
293 ptmA
->tmLastChar
= ptmW
->tmLastChar
> 255 ? 255 : ptmW
->tmLastChar
;
294 ptmA
->tmDefaultChar
= ptmW
->tmDefaultChar
> 255 ? 255 : ptmW
->tmDefaultChar
;
295 ptmA
->tmBreakChar
= ptmW
->tmBreakChar
> 255 ? 255 : ptmW
->tmBreakChar
;
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((LPTEXTMETRICW
)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 /***********************************************************************
347 * Returns a Unicode translation of str. If count is -1 then str is
348 * assumed to be '\0' terminated, otherwise it contains the number of
349 * bytes to convert. If plenW is non-NULL, on return it will point to
350 * the number of WCHARs that have been written. The caller should free
351 * the returned LPWSTR from the process heap itself.
353 static LPWSTR
FONT_mbtowc(LPCSTR str
, INT count
, INT
*plenW
)
359 if(count
== -1) count
= strlen(str
);
360 lenW
= MultiByteToWideChar(cp
, 0, str
, count
, NULL
, 0);
361 strW
= HeapAlloc(GetProcessHeap(), 0, lenW
*sizeof(WCHAR
));
362 MultiByteToWideChar(cp
, 0, str
, count
, strW
, lenW
);
363 TRACE("mapped %s -> %s\n", debugstr_an(str
, count
), debugstr_wn(strW
, lenW
));
364 if(plenW
) *plenW
= lenW
;
369 /***********************************************************************
370 * CreateFontIndirectA (GDI32.@)
372 HFONT WINAPI
CreateFontIndirectA( const LOGFONTA
*plfA
)
377 FONT_LogFontAToW( plfA
, &lfW
);
378 return CreateFontIndirectW( &lfW
);
380 return CreateFontIndirectW( NULL
);
384 /***********************************************************************
385 * CreateFontIndirectW (GDI32.@)
387 HFONT WINAPI
CreateFontIndirectW( const LOGFONTW
*plf
)
394 if ((fontPtr
= GDI_AllocObject( sizeof(FONTOBJ
), FONT_MAGIC
,
395 (HGDIOBJ
*)&hFont
, &font_funcs
)))
397 static const WCHAR ItalicW
[] = {' ','I','t','a','l','i','c','\0'};
398 static const WCHAR BoldW
[] = {' ','B','o','l','d','\0'};
399 WCHAR
*pFaceNameItalicSuffix
, *pFaceNameBoldSuffix
;
400 WCHAR
* pFaceNameSuffix
= NULL
;
402 memcpy( &fontPtr
->logfont
, plf
, sizeof(LOGFONTW
) );
404 TRACE("(%ld %ld %ld %ld %x %d %x %d %d) %s %s %s %s => %p\n",
405 plf
->lfHeight
, plf
->lfWidth
,
406 plf
->lfEscapement
, plf
->lfOrientation
,
407 plf
->lfPitchAndFamily
,
408 plf
->lfOutPrecision
, plf
->lfClipPrecision
,
409 plf
->lfQuality
, plf
->lfCharSet
,
410 debugstr_w(plf
->lfFaceName
),
411 plf
->lfWeight
> 400 ? "Bold" : "",
412 plf
->lfItalic
? "Italic" : "",
413 plf
->lfUnderline
? "Underline" : "", hFont
);
415 if (plf
->lfEscapement
!= plf
->lfOrientation
) {
416 /* this should really depend on whether GM_ADVANCED is set */
417 fontPtr
->logfont
.lfOrientation
= fontPtr
->logfont
.lfEscapement
;
418 WARN("orientation angle %f set to "
419 "escapement angle %f for new font %p\n",
420 plf
->lfOrientation
/10., plf
->lfEscapement
/10., hFont
);
423 pFaceNameItalicSuffix
= strstrW(fontPtr
->logfont
.lfFaceName
, ItalicW
);
424 if (pFaceNameItalicSuffix
) {
425 fontPtr
->logfont
.lfItalic
= TRUE
;
426 pFaceNameSuffix
= pFaceNameItalicSuffix
;
429 pFaceNameBoldSuffix
= strstrW(fontPtr
->logfont
.lfFaceName
, BoldW
);
430 if (pFaceNameBoldSuffix
) {
431 if (fontPtr
->logfont
.lfWeight
< FW_BOLD
) {
432 fontPtr
->logfont
.lfWeight
= FW_BOLD
;
434 if (!pFaceNameSuffix
||
435 (pFaceNameBoldSuffix
< pFaceNameSuffix
)) {
436 pFaceNameSuffix
= pFaceNameBoldSuffix
;
440 if (pFaceNameSuffix
) *pFaceNameSuffix
= 0;
442 GDI_ReleaseObj( hFont
);
445 else WARN("(NULL) => NULL\n");
450 /*************************************************************************
451 * CreateFontA (GDI32.@)
453 HFONT WINAPI
CreateFontA( INT height
, INT width
, INT esc
,
454 INT orient
, INT weight
, DWORD italic
,
455 DWORD underline
, DWORD strikeout
, DWORD charset
,
456 DWORD outpres
, DWORD clippres
, DWORD quality
,
457 DWORD pitch
, LPCSTR name
)
461 logfont
.lfHeight
= height
;
462 logfont
.lfWidth
= width
;
463 logfont
.lfEscapement
= esc
;
464 logfont
.lfOrientation
= orient
;
465 logfont
.lfWeight
= weight
;
466 logfont
.lfItalic
= italic
;
467 logfont
.lfUnderline
= underline
;
468 logfont
.lfStrikeOut
= strikeout
;
469 logfont
.lfCharSet
= charset
;
470 logfont
.lfOutPrecision
= outpres
;
471 logfont
.lfClipPrecision
= clippres
;
472 logfont
.lfQuality
= quality
;
473 logfont
.lfPitchAndFamily
= pitch
;
476 lstrcpynA(logfont
.lfFaceName
,name
,sizeof(logfont
.lfFaceName
));
478 logfont
.lfFaceName
[0] = '\0';
480 return CreateFontIndirectA( &logfont
);
483 /*************************************************************************
484 * CreateFontW (GDI32.@)
486 HFONT WINAPI
CreateFontW( INT height
, INT width
, INT esc
,
487 INT orient
, INT weight
, DWORD italic
,
488 DWORD underline
, DWORD strikeout
, DWORD charset
,
489 DWORD outpres
, DWORD clippres
, DWORD quality
,
490 DWORD pitch
, LPCWSTR name
)
494 logfont
.lfHeight
= height
;
495 logfont
.lfWidth
= width
;
496 logfont
.lfEscapement
= esc
;
497 logfont
.lfOrientation
= orient
;
498 logfont
.lfWeight
= weight
;
499 logfont
.lfItalic
= italic
;
500 logfont
.lfUnderline
= underline
;
501 logfont
.lfStrikeOut
= strikeout
;
502 logfont
.lfCharSet
= charset
;
503 logfont
.lfOutPrecision
= outpres
;
504 logfont
.lfClipPrecision
= clippres
;
505 logfont
.lfQuality
= quality
;
506 logfont
.lfPitchAndFamily
= pitch
;
509 lstrcpynW(logfont
.lfFaceName
, name
,
510 sizeof(logfont
.lfFaceName
) / sizeof(WCHAR
));
512 logfont
.lfFaceName
[0] = '\0';
514 return CreateFontIndirectW( &logfont
);
518 /***********************************************************************
521 * If the driver supports vector fonts we create a gdi font first and
522 * then call the driver to give it a chance to supply its own device
523 * font. If the driver wants to do this it returns TRUE and we can
524 * delete the gdi font, if the driver wants to use the gdi font it
525 * should return FALSE, to signal an error return GDI_ERROR. For
526 * drivers that don't support vector fonts they must supply their own
529 static HGDIOBJ
FONT_SelectObject( HGDIOBJ handle
, void *obj
, HDC hdc
)
532 DC
*dc
= DC_GetDCPtr( hdc
);
536 if (dc
->hFont
!= handle
|| dc
->gdiFont
== NULL
)
538 if(GetDeviceCaps(dc
->hSelf
, TEXTCAPS
) & TC_VA_ABLE
)
539 dc
->gdiFont
= WineEngCreateFontInstance(dc
, handle
);
542 if (dc
->funcs
->pSelectFont
) ret
= dc
->funcs
->pSelectFont( dc
->physDev
, handle
, dc
->gdiFont
);
544 if (ret
&& dc
->gdiFont
) dc
->gdiFont
= 0;
546 if (ret
== HGDI_ERROR
)
547 ret
= 0; /* SelectObject returns 0 on error */
553 GDI_ReleaseObj( hdc
);
558 /***********************************************************************
561 static INT
FONT_GetObject16( HGDIOBJ handle
, void *obj
, INT count
, LPVOID buffer
)
566 FONT_LogFontWTo16( &font
->logfont
, &lf16
);
568 if (count
> sizeof(LOGFONT16
)) count
= sizeof(LOGFONT16
);
569 memcpy( buffer
, &lf16
, count
);
573 /***********************************************************************
576 static INT
FONT_GetObjectA( HGDIOBJ handle
, void *obj
, INT count
, LPVOID buffer
)
583 FONT_LogFontWToA( &font
->logfont
, &lfA
);
585 if (count
> sizeof(lfA
)) count
= sizeof(lfA
);
586 memcpy( buffer
, &lfA
, count
);
590 /***********************************************************************
593 static INT
FONT_GetObjectW( HGDIOBJ handle
, void *obj
, INT count
, LPVOID buffer
)
597 return sizeof(LOGFONTW
);
598 if (count
> sizeof(LOGFONTW
)) count
= sizeof(LOGFONTW
);
599 memcpy( buffer
, &font
->logfont
, count
);
604 /***********************************************************************
607 static BOOL
FONT_DeleteObject( HGDIOBJ handle
, void *obj
)
609 WineEngDestroyFontInstance( handle
);
610 return GDI_FreeObject( handle
, obj
);
614 /***********************************************************************
615 * FONT_EnumInstance16
617 * Called by the device driver layer to pass font info
618 * down to the application.
620 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
621 * We have to use other types because of the FONTENUMPROCW definition.
623 static INT CALLBACK
FONT_EnumInstance16( const LOGFONTW
*plf
, const TEXTMETRICW
*ptm
,
624 DWORD fType
, LPARAM lp
)
626 fontEnum16
*pfe
= (fontEnum16
*)lp
;
630 if( pfe
->lpLogFontParam
->lfCharSet
== DEFAULT_CHARSET
||
631 pfe
->lpLogFontParam
->lfCharSet
== plf
->lfCharSet
)
636 FONT_EnumLogFontExWTo16((const ENUMLOGFONTEXW
*)plf
, pfe
->lpLogFont
);
637 FONT_NewTextMetricExWTo16((const NEWTEXTMETRICEXW
*)ptm
, pfe
->lpTextMetric
);
638 pfe
->dwFlags
|= ENUM_CALLED
;
639 GDI_ReleaseObj( pfe
->hdc
); /* release the GDI lock */
641 args
[6] = SELECTOROF(pfe
->segLogFont
);
642 args
[5] = OFFSETOF(pfe
->segLogFont
);
643 args
[4] = SELECTOROF(pfe
->segTextMetric
);
644 args
[3] = OFFSETOF(pfe
->segTextMetric
);
646 args
[1] = HIWORD(pfe
->lpData
);
647 args
[0] = LOWORD(pfe
->lpData
);
648 WOWCallback16Ex( (DWORD
)pfe
->lpEnumFunc
, WCB16_PASCAL
, sizeof(args
), args
, &result
);
649 ret
= LOWORD(result
);
651 /* get the lock again and make sure the DC is still valid */
652 dc
= DC_GetDCPtr( pfe
->hdc
);
653 if (!dc
|| dc
!= pfe
->dc
|| dc
->physDev
!= pfe
->physDev
)
655 if (dc
) GDI_ReleaseObj( pfe
->hdc
);
656 pfe
->hdc
= 0; /* make sure we don't try to release it later on */
663 /***********************************************************************
666 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
667 * We have to use other types because of the FONTENUMPROCW definition.
669 static INT CALLBACK
FONT_EnumInstance( const LOGFONTW
*plf
, const TEXTMETRICW
*ptm
,
670 DWORD fType
, LPARAM lp
)
672 fontEnum32
*pfe
= (fontEnum32
*)lp
;
676 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
677 if((pfe
->lpLogFontParam
->lfCharSet
== DEFAULT_CHARSET
||
678 pfe
->lpLogFontParam
->lfCharSet
== plf
->lfCharSet
) &&
679 (!(fType
& RASTER_FONTTYPE
) || GetDeviceCaps(pfe
->hdc
, TEXTCAPS
) & TC_RA_ABLE
) )
681 /* convert font metrics */
682 ENUMLOGFONTEXA logfont
;
683 NEWTEXTMETRICEXA tmA
;
685 pfe
->dwFlags
|= ENUM_CALLED
;
686 if (!(pfe
->dwFlags
& ENUM_UNICODE
))
688 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW
*)plf
, &logfont
);
689 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW
*)ptm
, &tmA
);
690 plf
= (LOGFONTW
*)&logfont
.elfLogFont
;
691 ptm
= (TEXTMETRICW
*)&tmA
;
693 GDI_ReleaseObj( pfe
->hdc
); /* release the GDI lock */
695 ret
= pfe
->lpEnumFunc( plf
, ptm
, fType
, pfe
->lpData
);
697 /* get the lock again and make sure the DC is still valid */
698 dc
= DC_GetDCPtr( pfe
->hdc
);
699 if (!dc
|| dc
!= pfe
->dc
|| dc
->physDev
!= pfe
->physDev
)
701 if (dc
) GDI_ReleaseObj( pfe
->hdc
);
702 pfe
->hdc
= 0; /* make sure we don't try to release it later on */
709 /***********************************************************************
710 * EnumFontFamiliesEx (GDI.613)
712 INT16 WINAPI
EnumFontFamiliesEx16( HDC16 hDC
, LPLOGFONT16 plf
,
713 FONTENUMPROC16 efproc
, LPARAM lParam
,
718 DC
* dc
= DC_GetDCPtr( HDC_32(hDC
) );
719 NEWTEXTMETRICEX16 tm16
;
720 ENUMLOGFONTEX16 lf16
;
725 FONT_LogFont16ToW(plf
, &lfW
);
727 fe16
.hdc
= HDC_32(hDC
);
729 fe16
.physDev
= dc
->physDev
;
730 fe16
.lpLogFontParam
= plf
;
731 fe16
.lpEnumFunc
= efproc
;
732 fe16
.lpData
= lParam
;
733 fe16
.lpTextMetric
= &tm16
;
734 fe16
.lpLogFont
= &lf16
;
735 fe16
.segTextMetric
= MapLS( &tm16
);
736 fe16
.segLogFont
= MapLS( &lf16
);
739 enum_gdi_fonts
= GetDeviceCaps(fe16
.hdc
, TEXTCAPS
) & TC_VA_ABLE
;
741 if (!dc
->funcs
->pEnumDeviceFonts
&& !enum_gdi_fonts
)
748 ret
= WineEngEnumFonts( &lfW
, FONT_EnumInstance16
, (LPARAM
)&fe16
);
749 fe16
.dwFlags
&= ~ENUM_CALLED
;
750 if (ret
&& dc
->funcs
->pEnumDeviceFonts
) {
751 ret2
= dc
->funcs
->pEnumDeviceFonts( dc
->physDev
, &lfW
, FONT_EnumInstance16
, (LPARAM
)&fe16
);
752 if(fe16
.dwFlags
& ENUM_CALLED
) /* update ret iff a font gets enumed */
756 UnMapLS( fe16
.segTextMetric
);
757 UnMapLS( fe16
.segLogFont
);
758 if (fe16
.hdc
) GDI_ReleaseObj( fe16
.hdc
);
762 /***********************************************************************
763 * FONT_EnumFontFamiliesEx
765 static INT
FONT_EnumFontFamiliesEx( HDC hDC
, LPLOGFONTW plf
,
766 FONTENUMPROCW efproc
,
767 LPARAM lParam
, DWORD dwUnicode
)
770 DC
*dc
= DC_GetDCPtr( hDC
);
776 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf
->lfFaceName
),
778 fe32
.lpLogFontParam
= plf
;
779 fe32
.lpEnumFunc
= efproc
;
780 fe32
.lpData
= lParam
;
781 fe32
.dwFlags
= dwUnicode
;
784 fe32
.physDev
= dc
->physDev
;
786 enum_gdi_fonts
= GetDeviceCaps(hDC
, TEXTCAPS
) & TC_VA_ABLE
;
788 if (!dc
->funcs
->pEnumDeviceFonts
&& !enum_gdi_fonts
)
795 ret
= WineEngEnumFonts( plf
, FONT_EnumInstance
, (LPARAM
)&fe32
);
796 fe32
.dwFlags
&= ~ENUM_CALLED
;
797 if (ret
&& dc
->funcs
->pEnumDeviceFonts
) {
798 ret2
= dc
->funcs
->pEnumDeviceFonts( dc
->physDev
, plf
, FONT_EnumInstance
, (LPARAM
)&fe32
);
799 if(fe32
.dwFlags
& ENUM_CALLED
) /* update ret iff a font gets enumed */
803 if (fe32
.hdc
) GDI_ReleaseObj( fe32
.hdc
);
807 /***********************************************************************
808 * EnumFontFamiliesExW (GDI32.@)
810 INT WINAPI
EnumFontFamiliesExW( HDC hDC
, LPLOGFONTW plf
,
811 FONTENUMPROCW efproc
,
812 LPARAM lParam
, DWORD dwFlags
)
814 return FONT_EnumFontFamiliesEx( hDC
, plf
, efproc
, lParam
, ENUM_UNICODE
);
817 /***********************************************************************
818 * EnumFontFamiliesExA (GDI32.@)
820 INT WINAPI
EnumFontFamiliesExA( HDC hDC
, LPLOGFONTA plf
,
821 FONTENUMPROCA efproc
,
822 LPARAM lParam
, DWORD dwFlags
)
825 FONT_LogFontAToW( plf
, &lfW
);
827 return FONT_EnumFontFamiliesEx( hDC
, &lfW
, (FONTENUMPROCW
)efproc
, lParam
, 0);
830 /***********************************************************************
831 * EnumFontFamilies (GDI.330)
833 INT16 WINAPI
EnumFontFamilies16( HDC16 hDC
, LPCSTR lpFamily
,
834 FONTENUMPROC16 efproc
, LPARAM lpData
)
838 lf
.lfCharSet
= DEFAULT_CHARSET
;
839 if( lpFamily
) lstrcpynA( lf
.lfFaceName
, lpFamily
, LF_FACESIZE
);
840 else lf
.lfFaceName
[0] = '\0';
842 return EnumFontFamiliesEx16( hDC
, &lf
, efproc
, lpData
, 0 );
845 /***********************************************************************
846 * EnumFontFamiliesA (GDI32.@)
848 INT WINAPI
EnumFontFamiliesA( HDC hDC
, LPCSTR lpFamily
,
849 FONTENUMPROCA efproc
, LPARAM lpData
)
853 lf
.lfCharSet
= DEFAULT_CHARSET
;
854 if( lpFamily
) lstrcpynA( lf
.lfFaceName
, lpFamily
, LF_FACESIZE
);
855 else lf
.lfFaceName
[0] = lf
.lfFaceName
[1] = '\0';
857 return EnumFontFamiliesExA( hDC
, &lf
, efproc
, lpData
, 0 );
860 /***********************************************************************
861 * EnumFontFamiliesW (GDI32.@)
863 INT WINAPI
EnumFontFamiliesW( HDC hDC
, LPCWSTR lpFamily
,
864 FONTENUMPROCW efproc
, LPARAM lpData
)
868 lf
.lfCharSet
= DEFAULT_CHARSET
;
869 if( lpFamily
) lstrcpynW( lf
.lfFaceName
, lpFamily
, LF_FACESIZE
);
870 else lf
.lfFaceName
[0] = 0;
872 return EnumFontFamiliesExW( hDC
, &lf
, efproc
, lpData
, 0 );
875 /***********************************************************************
878 INT16 WINAPI
EnumFonts16( HDC16 hDC
, LPCSTR lpName
, FONTENUMPROC16 efproc
,
881 return EnumFontFamilies16( hDC
, lpName
, efproc
, lpData
);
884 /***********************************************************************
885 * EnumFontsA (GDI32.@)
887 INT WINAPI
EnumFontsA( HDC hDC
, LPCSTR lpName
, FONTENUMPROCA efproc
,
890 return EnumFontFamiliesA( hDC
, lpName
, efproc
, lpData
);
893 /***********************************************************************
894 * EnumFontsW (GDI32.@)
896 INT WINAPI
EnumFontsW( HDC hDC
, LPCWSTR lpName
, FONTENUMPROCW efproc
,
899 return EnumFontFamiliesW( hDC
, lpName
, efproc
, lpData
);
903 /***********************************************************************
904 * GetTextCharacterExtra (GDI32.@)
906 INT WINAPI
GetTextCharacterExtra( HDC hdc
)
909 DC
*dc
= DC_GetDCPtr( hdc
);
910 if (!dc
) return 0x80000000;
912 GDI_ReleaseObj( hdc
);
917 /***********************************************************************
918 * SetTextCharacterExtra (GDI32.@)
920 INT WINAPI
SetTextCharacterExtra( HDC hdc
, INT extra
)
923 DC
* dc
= DC_GetDCPtr( hdc
);
924 if (!dc
) return 0x80000000;
925 if (dc
->funcs
->pSetTextCharacterExtra
)
926 prev
= dc
->funcs
->pSetTextCharacterExtra( dc
->physDev
, extra
);
929 prev
= dc
->charExtra
;
930 dc
->charExtra
= extra
;
932 GDI_ReleaseObj( hdc
);
937 /***********************************************************************
938 * SetTextJustification (GDI32.@)
940 BOOL WINAPI
SetTextJustification( HDC hdc
, INT extra
, INT breaks
)
943 DC
* dc
= DC_GetDCPtr( hdc
);
944 if (!dc
) return FALSE
;
945 if (dc
->funcs
->pSetTextJustification
)
946 ret
= dc
->funcs
->pSetTextJustification( dc
->physDev
, extra
, breaks
);
949 extra
= abs((extra
* dc
->vportExtX
+ dc
->wndExtX
/ 2) / dc
->wndExtX
);
950 if (!extra
) breaks
= 0;
953 dc
->breakExtra
= extra
/ breaks
;
954 dc
->breakRem
= extra
- (breaks
* dc
->breakExtra
);
962 GDI_ReleaseObj( hdc
);
967 /***********************************************************************
968 * GetTextFaceA (GDI32.@)
970 INT WINAPI
GetTextFaceA( HDC hdc
, INT count
, LPSTR name
)
972 INT res
= GetTextFaceW(hdc
, 0, NULL
);
973 LPWSTR nameW
= HeapAlloc( GetProcessHeap(), 0, res
* 2 );
974 GetTextFaceW( hdc
, res
, nameW
);
978 if (count
&& !WideCharToMultiByte( CP_ACP
, 0, nameW
, -1, name
, count
, NULL
, NULL
))
983 res
= WideCharToMultiByte( CP_ACP
, 0, nameW
, -1, NULL
, 0, NULL
, NULL
);
984 HeapFree( GetProcessHeap(), 0, nameW
);
988 /***********************************************************************
989 * GetTextFaceW (GDI32.@)
991 INT WINAPI
GetTextFaceW( HDC hdc
, INT count
, LPWSTR name
)
996 DC
* dc
= DC_GetDCPtr( hdc
);
1000 ret
= WineEngGetTextFace(dc
->gdiFont
, count
, name
);
1001 else if ((font
= (FONTOBJ
*) GDI_GetObjPtr( dc
->hFont
, FONT_MAGIC
)))
1005 lstrcpynW( name
, font
->logfont
.lfFaceName
, count
);
1006 ret
= strlenW(name
);
1008 else ret
= strlenW(font
->logfont
.lfFaceName
) + 1;
1009 GDI_ReleaseObj( dc
->hFont
);
1011 GDI_ReleaseObj( hdc
);
1016 /***********************************************************************
1017 * GetTextExtentPoint32A (GDI32.@)
1019 * See GetTextExtentPoint32W.
1021 BOOL WINAPI
GetTextExtentPoint32A( HDC hdc
, LPCSTR str
, INT count
,
1026 LPWSTR p
= FONT_mbtowc(str
, count
, &wlen
);
1029 ret
= GetTextExtentPoint32W( hdc
, p
, wlen
, size
);
1030 HeapFree( GetProcessHeap(), 0, p
);
1033 TRACE("(%p %s %d %p): returning %ld x %ld\n",
1034 hdc
, debugstr_an (str
, count
), count
, size
, size
->cx
, size
->cy
);
1039 /***********************************************************************
1040 * GetTextExtentPoint32W [GDI32.@]
1042 * Computes width/height for a string.
1044 * Computes width and height of the specified string.
1050 BOOL WINAPI
GetTextExtentPoint32W(
1051 HDC hdc
, /* [in] Handle of device context */
1052 LPCWSTR str
, /* [in] Address of text string */
1053 INT count
, /* [in] Number of characters in string */
1054 LPSIZE size
) /* [out] Address of structure for string size */
1057 DC
* dc
= DC_GetDCPtr( hdc
);
1058 if (!dc
) return FALSE
;
1061 ret
= WineEngGetTextExtentPoint(dc
->gdiFont
, str
, count
, size
);
1062 else if(dc
->funcs
->pGetTextExtentPoint
)
1063 ret
= dc
->funcs
->pGetTextExtentPoint( dc
->physDev
, str
, count
, size
);
1067 size
->cx
= abs(INTERNAL_XDSTOWS(dc
, size
->cx
));
1068 size
->cy
= abs(INTERNAL_YDSTOWS(dc
, size
->cy
));
1069 size
->cx
+= count
* dc
->charExtra
+ dc
->breakRem
;
1072 GDI_ReleaseObj( hdc
);
1074 TRACE("(%p %s %d %p): returning %ld x %ld\n",
1075 hdc
, debugstr_wn (str
, count
), count
, size
, size
->cx
, size
->cy
);
1079 /***********************************************************************
1080 * GetTextExtentPointI [GDI32.@]
1082 * Computes width and height of the array of glyph indices.
1088 BOOL WINAPI
GetTextExtentPointI(
1089 HDC hdc
, /* [in] Handle of device context */
1090 const WORD
*indices
, /* [in] Address of glyph index array */
1091 INT count
, /* [in] Number of glyphs in array */
1092 LPSIZE size
) /* [out] Address of structure for string size */
1095 DC
* dc
= DC_GetDCPtr( hdc
);
1096 if (!dc
) return FALSE
;
1099 ret
= WineEngGetTextExtentPointI(dc
->gdiFont
, indices
, count
, size
);
1100 size
->cx
= abs(INTERNAL_XDSTOWS(dc
, size
->cx
));
1101 size
->cy
= abs(INTERNAL_YDSTOWS(dc
, size
->cy
));
1102 size
->cx
+= count
* dc
->charExtra
;
1104 else if(dc
->funcs
->pGetTextExtentPoint
) {
1105 FIXME("calling GetTextExtentPoint\n");
1106 ret
= dc
->funcs
->pGetTextExtentPoint( dc
->physDev
, (LPCWSTR
)indices
, count
, size
);
1109 GDI_ReleaseObj( hdc
);
1111 TRACE("(%p %p %d %p): returning %ld x %ld\n",
1112 hdc
, indices
, count
, size
, size
->cx
, size
->cy
);
1117 /***********************************************************************
1118 * GetTextExtentPointA (GDI32.@)
1120 BOOL WINAPI
GetTextExtentPointA( HDC hdc
, LPCSTR str
, INT count
,
1123 TRACE("not bug compatible.\n");
1124 return GetTextExtentPoint32A( hdc
, str
, count
, size
);
1127 /***********************************************************************
1128 * GetTextExtentPointW (GDI32.@)
1130 BOOL WINAPI
GetTextExtentPointW( HDC hdc
, LPCWSTR str
, INT count
,
1133 TRACE("not bug compatible.\n");
1134 return GetTextExtentPoint32W( hdc
, str
, count
, size
);
1138 /***********************************************************************
1139 * GetTextExtentExPointA (GDI32.@)
1141 BOOL WINAPI
GetTextExtentExPointA( HDC hdc
, LPCSTR str
, INT count
,
1142 INT maxExt
, LPINT lpnFit
,
1143 LPINT alpDx
, LPSIZE size
)
1151 NULL
== (walpDx
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(INT
))))
1154 p
= FONT_mbtowc(str
, count
, &wlen
);
1155 ret
= GetTextExtentExPointW( hdc
, p
, wlen
, maxExt
, lpnFit
, walpDx
, size
);
1158 INT n
= lpnFit
? *lpnFit
: wlen
;
1160 for(i
= 0, j
= 0; i
< n
; i
++, j
++)
1162 alpDx
[j
] = walpDx
[i
];
1163 if (IsDBCSLeadByte(str
[j
])) alpDx
[++j
] = walpDx
[i
];
1166 if (lpnFit
) *lpnFit
= WideCharToMultiByte(CP_ACP
,0,p
,*lpnFit
,NULL
,0,NULL
,NULL
);
1167 HeapFree( GetProcessHeap(), 0, p
);
1168 HeapFree( GetProcessHeap(), 0, walpDx
);
1173 /***********************************************************************
1174 * GetTextExtentExPointW (GDI32.@)
1176 * Return the size of the string as it would be if it was output properly by
1179 * This should include
1180 * - Intercharacter spacing
1181 * - justification spacing (not yet done)
1182 * - kerning? see below
1184 * Kerning. Since kerning would be carried out by the rendering code it should
1185 * be done by the driver. However they don't support it yet. Also I am not
1186 * yet persuaded that (certainly under Win95) any kerning is actually done.
1188 * str: According to MSDN this should be null-terminated. That is not true; a
1189 * null will not terminate it early.
1190 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1191 * than count. I have seen it be either the size of the full string or
1192 * 1 less than the size of the full string. I have not seen it bear any
1193 * resemblance to the portion that would fit.
1194 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1195 * trailing intercharacter spacing and any trailing justification.
1198 * Currently we do this by measuring each character etc. We should do it by
1199 * passing the request to the driver, perhaps by extending the
1200 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1201 * thinking about kerning issues and rounding issues in the justification.
1204 BOOL WINAPI
GetTextExtentExPointW( HDC hdc
, LPCWSTR str
, INT count
,
1205 INT maxExt
, LPINT lpnFit
,
1206 LPINT alpDx
, LPSIZE size
)
1208 int index
, nFit
, extent
;
1212 TRACE("(%p, %s, %d)\n",hdc
,debugstr_wn(str
,count
),maxExt
);
1214 size
->cx
= size
->cy
= nFit
= extent
= 0;
1215 for(index
= 0; index
< count
; index
++)
1217 if(!GetTextExtentPoint32W( hdc
, str
, index
+ 1, &tSize
)) goto done
;
1218 /* GetTextExtentPoint includes intercharacter spacing. */
1219 /* FIXME - justification needs doing yet. Remember that the base
1220 * data will not be in logical coordinates.
1223 if( !lpnFit
|| extent
<= maxExt
)
1224 /* It is allowed to be equal. */
1227 if( alpDx
) alpDx
[index
] = extent
;
1229 if( tSize
.cy
> size
->cy
) size
->cy
= tSize
.cy
;
1232 if(lpnFit
) *lpnFit
= nFit
;
1235 TRACE("returning %d %ld x %ld\n",nFit
,size
->cx
,size
->cy
);
1241 /***********************************************************************
1242 * GetTextMetricsA (GDI32.@)
1244 BOOL WINAPI
GetTextMetricsA( HDC hdc
, TEXTMETRICA
*metrics
)
1248 if (!GetTextMetricsW( hdc
, &tm32
)) return FALSE
;
1249 FONT_TextMetricWToA( &tm32
, metrics
);
1253 /***********************************************************************
1254 * GetTextMetricsW (GDI32.@)
1256 BOOL WINAPI
GetTextMetricsW( HDC hdc
, TEXTMETRICW
*metrics
)
1259 DC
* dc
= DC_GetDCPtr( hdc
);
1260 if (!dc
) return FALSE
;
1263 ret
= WineEngGetTextMetrics(dc
->gdiFont
, metrics
);
1264 else if (dc
->funcs
->pGetTextMetrics
)
1265 ret
= dc
->funcs
->pGetTextMetrics( dc
->physDev
, metrics
);
1269 /* device layer returns values in device units
1270 * therefore we have to convert them to logical */
1272 #define WDPTOLP(x) ((x<0)? \
1273 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1274 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1275 #define HDPTOLP(y) ((y<0)? \
1276 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1277 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1279 metrics
->tmHeight
= HDPTOLP(metrics
->tmHeight
);
1280 metrics
->tmAscent
= HDPTOLP(metrics
->tmAscent
);
1281 metrics
->tmDescent
= HDPTOLP(metrics
->tmDescent
);
1282 metrics
->tmInternalLeading
= HDPTOLP(metrics
->tmInternalLeading
);
1283 metrics
->tmExternalLeading
= HDPTOLP(metrics
->tmExternalLeading
);
1284 metrics
->tmAveCharWidth
= WDPTOLP(metrics
->tmAveCharWidth
);
1285 metrics
->tmMaxCharWidth
= WDPTOLP(metrics
->tmMaxCharWidth
);
1286 metrics
->tmOverhang
= WDPTOLP(metrics
->tmOverhang
);
1290 TRACE("text metrics:\n"
1291 " Weight = %03li\t FirstChar = %i\t AveCharWidth = %li\n"
1292 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %li\n"
1293 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %li\n"
1294 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1295 " PitchAndFamily = %02x\n"
1296 " --------------------\n"
1297 " InternalLeading = %li\n"
1301 metrics
->tmWeight
, metrics
->tmFirstChar
, metrics
->tmAveCharWidth
,
1302 metrics
->tmItalic
, metrics
->tmLastChar
, metrics
->tmMaxCharWidth
,
1303 metrics
->tmUnderlined
, metrics
->tmDefaultChar
, metrics
->tmOverhang
,
1304 metrics
->tmStruckOut
, metrics
->tmBreakChar
, metrics
->tmCharSet
,
1305 metrics
->tmPitchAndFamily
,
1306 metrics
->tmInternalLeading
,
1309 metrics
->tmHeight
);
1311 GDI_ReleaseObj( hdc
);
1316 /***********************************************************************
1317 * GetOutlineTextMetrics [GDI.308] Gets metrics for TrueType fonts.
1320 * lpOTM should be LPOUTLINETEXTMETRIC
1323 * Success: Non-zero or size of required buffer
1326 UINT16 WINAPI
GetOutlineTextMetrics16(
1327 HDC16 hdc
, /* [in] Handle of device context */
1328 UINT16 cbData
, /* [in] Size of metric data array */
1329 LPOUTLINETEXTMETRIC16 lpOTM
) /* [out] Address of metric data array */
1331 FIXME("(%04x,%04x,%p): stub\n", hdc
,cbData
,lpOTM
);
1336 /***********************************************************************
1337 * GetOutlineTextMetricsA (GDI32.@)
1338 * Gets metrics for TrueType fonts.
1341 * If the supplied buffer isn't big enough Windows partially fills it up to
1342 * its given length and returns that length.
1345 * Success: Non-zero or size of required buffer
1348 UINT WINAPI
GetOutlineTextMetricsA(
1349 HDC hdc
, /* [in] Handle of device context */
1350 UINT cbData
, /* [in] Size of metric data array */
1351 LPOUTLINETEXTMETRICA lpOTM
) /* [out] Address of metric data array */
1353 char buf
[512], *ptr
;
1355 OUTLINETEXTMETRICW
*lpOTMW
= (OUTLINETEXTMETRICW
*)buf
;
1356 OUTLINETEXTMETRICA
*output
= lpOTM
;
1359 if((ret
= GetOutlineTextMetricsW(hdc
, 0, NULL
)) == 0)
1361 if(ret
> sizeof(buf
))
1362 lpOTMW
= HeapAlloc(GetProcessHeap(), 0, ret
);
1363 GetOutlineTextMetricsW(hdc
, ret
, lpOTMW
);
1365 needed
= sizeof(OUTLINETEXTMETRICA
);
1366 if(lpOTMW
->otmpFamilyName
)
1367 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1368 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFamilyName
), -1,
1369 NULL
, 0, NULL
, NULL
);
1370 if(lpOTMW
->otmpFaceName
)
1371 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1372 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFaceName
), -1,
1373 NULL
, 0, NULL
, NULL
);
1374 if(lpOTMW
->otmpStyleName
)
1375 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1376 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpStyleName
), -1,
1377 NULL
, 0, NULL
, NULL
);
1378 if(lpOTMW
->otmpFullName
)
1379 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1380 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFullName
), -1,
1381 NULL
, 0, NULL
, NULL
);
1388 TRACE("needed = %d\n", needed
);
1390 /* Since the supplied buffer isn't big enough, we'll alloc one
1391 that is and memcpy the first cbData bytes into the lpOTM at
1393 output
= HeapAlloc(GetProcessHeap(), 0, needed
);
1395 ret
= output
->otmSize
= min(needed
, cbData
);
1396 FONT_TextMetricWToA( &lpOTMW
->otmTextMetrics
, &output
->otmTextMetrics
);
1397 output
->otmFiller
= 0;
1398 output
->otmPanoseNumber
= lpOTMW
->otmPanoseNumber
;
1399 output
->otmfsSelection
= lpOTMW
->otmfsSelection
;
1400 output
->otmfsType
= lpOTMW
->otmfsType
;
1401 output
->otmsCharSlopeRise
= lpOTMW
->otmsCharSlopeRise
;
1402 output
->otmsCharSlopeRun
= lpOTMW
->otmsCharSlopeRun
;
1403 output
->otmItalicAngle
= lpOTMW
->otmItalicAngle
;
1404 output
->otmEMSquare
= lpOTMW
->otmEMSquare
;
1405 output
->otmAscent
= lpOTMW
->otmAscent
;
1406 output
->otmDescent
= lpOTMW
->otmDescent
;
1407 output
->otmLineGap
= lpOTMW
->otmLineGap
;
1408 output
->otmsCapEmHeight
= lpOTMW
->otmsCapEmHeight
;
1409 output
->otmsXHeight
= lpOTMW
->otmsXHeight
;
1410 output
->otmrcFontBox
= lpOTMW
->otmrcFontBox
;
1411 output
->otmMacAscent
= lpOTMW
->otmMacAscent
;
1412 output
->otmMacDescent
= lpOTMW
->otmMacDescent
;
1413 output
->otmMacLineGap
= lpOTMW
->otmMacLineGap
;
1414 output
->otmusMinimumPPEM
= lpOTMW
->otmusMinimumPPEM
;
1415 output
->otmptSubscriptSize
= lpOTMW
->otmptSubscriptSize
;
1416 output
->otmptSubscriptOffset
= lpOTMW
->otmptSubscriptOffset
;
1417 output
->otmptSuperscriptSize
= lpOTMW
->otmptSuperscriptSize
;
1418 output
->otmptSuperscriptOffset
= lpOTMW
->otmptSuperscriptOffset
;
1419 output
->otmsStrikeoutSize
= lpOTMW
->otmsStrikeoutSize
;
1420 output
->otmsStrikeoutPosition
= lpOTMW
->otmsStrikeoutPosition
;
1421 output
->otmsUnderscoreSize
= lpOTMW
->otmsUnderscoreSize
;
1422 output
->otmsUnderscorePosition
= lpOTMW
->otmsUnderscorePosition
;
1425 ptr
= (char*)(output
+ 1);
1426 left
= needed
- sizeof(*output
);
1428 if(lpOTMW
->otmpFamilyName
) {
1429 output
->otmpFamilyName
= (LPSTR
)(ptr
- (char*)output
);
1430 len
= WideCharToMultiByte(CP_ACP
, 0,
1431 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFamilyName
), -1,
1432 ptr
, left
, NULL
, NULL
);
1436 output
->otmpFamilyName
= 0;
1438 if(lpOTMW
->otmpFaceName
) {
1439 output
->otmpFaceName
= (LPSTR
)(ptr
- (char*)output
);
1440 len
= WideCharToMultiByte(CP_ACP
, 0,
1441 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFaceName
), -1,
1442 ptr
, left
, NULL
, NULL
);
1446 output
->otmpFaceName
= 0;
1448 if(lpOTMW
->otmpStyleName
) {
1449 output
->otmpStyleName
= (LPSTR
)(ptr
- (char*)output
);
1450 len
= WideCharToMultiByte(CP_ACP
, 0,
1451 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpStyleName
), -1,
1452 ptr
, left
, NULL
, NULL
);
1456 output
->otmpStyleName
= 0;
1458 if(lpOTMW
->otmpFullName
) {
1459 output
->otmpFullName
= (LPSTR
)(ptr
- (char*)output
);
1460 len
= WideCharToMultiByte(CP_ACP
, 0,
1461 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFullName
), -1,
1462 ptr
, left
, NULL
, NULL
);
1465 output
->otmpFullName
= 0;
1469 if(output
!= lpOTM
) {
1470 memcpy(lpOTM
, output
, cbData
);
1471 HeapFree(GetProcessHeap(), 0, output
);
1475 if(lpOTMW
!= (OUTLINETEXTMETRICW
*)buf
)
1476 HeapFree(GetProcessHeap(), 0, lpOTMW
);
1482 /***********************************************************************
1483 * GetOutlineTextMetricsW [GDI32.@]
1485 UINT WINAPI
GetOutlineTextMetricsW(
1486 HDC hdc
, /* [in] Handle of device context */
1487 UINT cbData
, /* [in] Size of metric data array */
1488 LPOUTLINETEXTMETRICW lpOTM
) /* [out] Address of metric data array */
1490 DC
*dc
= DC_GetDCPtr( hdc
);
1491 OUTLINETEXTMETRICW
*output
= lpOTM
;
1494 TRACE("(%p,%d,%p)\n", hdc
, cbData
, lpOTM
);
1498 ret
= WineEngGetOutlineTextMetrics(dc
->gdiFont
, cbData
, output
);
1501 output
= HeapAlloc(GetProcessHeap(), 0, ret
);
1502 WineEngGetOutlineTextMetrics(dc
->gdiFont
, ret
, output
);
1505 #define WDPTOLP(x) ((x<0)? \
1506 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1507 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1508 #define HDPTOLP(y) ((y<0)? \
1509 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1510 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1512 output
->otmTextMetrics
.tmHeight
= HDPTOLP(output
->otmTextMetrics
.tmHeight
);
1513 output
->otmTextMetrics
.tmAscent
= HDPTOLP(output
->otmTextMetrics
.tmAscent
);
1514 output
->otmTextMetrics
.tmDescent
= HDPTOLP(output
->otmTextMetrics
.tmDescent
);
1515 output
->otmTextMetrics
.tmInternalLeading
= HDPTOLP(output
->otmTextMetrics
.tmInternalLeading
);
1516 output
->otmTextMetrics
.tmExternalLeading
= HDPTOLP(output
->otmTextMetrics
.tmExternalLeading
);
1517 output
->otmTextMetrics
.tmAveCharWidth
= WDPTOLP(output
->otmTextMetrics
.tmAveCharWidth
);
1518 output
->otmTextMetrics
.tmMaxCharWidth
= WDPTOLP(output
->otmTextMetrics
.tmMaxCharWidth
);
1519 output
->otmTextMetrics
.tmOverhang
= WDPTOLP(output
->otmTextMetrics
.tmOverhang
);
1520 output
->otmAscent
= HDPTOLP(output
->otmAscent
);
1521 output
->otmDescent
= HDPTOLP(output
->otmDescent
);
1522 output
->otmLineGap
= HDPTOLP(output
->otmLineGap
);
1523 output
->otmsCapEmHeight
= HDPTOLP(output
->otmsCapEmHeight
);
1524 output
->otmsXHeight
= HDPTOLP(output
->otmsXHeight
);
1525 output
->otmrcFontBox
.top
= HDPTOLP(output
->otmrcFontBox
.top
);
1526 output
->otmrcFontBox
.bottom
= HDPTOLP(output
->otmrcFontBox
.bottom
);
1527 output
->otmrcFontBox
.left
= WDPTOLP(output
->otmrcFontBox
.left
);
1528 output
->otmrcFontBox
.right
= WDPTOLP(output
->otmrcFontBox
.right
);
1529 output
->otmMacAscent
= HDPTOLP(output
->otmMacAscent
);
1530 output
->otmMacDescent
= HDPTOLP(output
->otmMacDescent
);
1531 output
->otmMacLineGap
= HDPTOLP(output
->otmMacLineGap
);
1532 output
->otmptSubscriptSize
.x
= WDPTOLP(output
->otmptSubscriptSize
.x
);
1533 output
->otmptSubscriptSize
.y
= HDPTOLP(output
->otmptSubscriptSize
.y
);
1534 output
->otmptSubscriptOffset
.x
= WDPTOLP(output
->otmptSubscriptOffset
.x
);
1535 output
->otmptSubscriptOffset
.y
= HDPTOLP(output
->otmptSubscriptOffset
.y
);
1536 output
->otmptSuperscriptSize
.x
= WDPTOLP(output
->otmptSuperscriptSize
.x
);
1537 output
->otmptSuperscriptSize
.y
= HDPTOLP(output
->otmptSuperscriptSize
.y
);
1538 output
->otmptSuperscriptOffset
.x
= WDPTOLP(output
->otmptSuperscriptOffset
.x
);
1539 output
->otmptSuperscriptOffset
.y
= HDPTOLP(output
->otmptSuperscriptOffset
.y
);
1540 output
->otmsStrikeoutSize
= HDPTOLP(output
->otmsStrikeoutSize
);
1541 output
->otmsStrikeoutPosition
= HDPTOLP(output
->otmsStrikeoutPosition
);
1542 output
->otmsUnderscoreSize
= HDPTOLP(output
->otmsUnderscoreSize
);
1543 output
->otmsUnderscorePosition
= HDPTOLP(output
->otmsUnderscorePosition
);
1546 if(output
!= lpOTM
) {
1547 memcpy(lpOTM
, output
, cbData
);
1548 HeapFree(GetProcessHeap(), 0, output
);
1554 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1555 but really this should just be a return 0. */
1557 ret
= sizeof(*lpOTM
);
1562 memset(lpOTM
, 0, ret
);
1563 lpOTM
->otmSize
= sizeof(*lpOTM
);
1564 GetTextMetricsW(hdc
, &lpOTM
->otmTextMetrics
);
1566 Further fill of the structure not implemented,
1567 Needs real values for the structure members
1572 GDI_ReleaseObj(hdc
);
1577 /***********************************************************************
1578 * GetCharWidthW (GDI32.@)
1579 * GetCharWidth32W (GDI32.@)
1581 BOOL WINAPI
GetCharWidth32W( HDC hdc
, UINT firstChar
, UINT lastChar
,
1586 DC
* dc
= DC_GetDCPtr( hdc
);
1587 if (!dc
) return FALSE
;
1590 ret
= WineEngGetCharWidth( dc
->gdiFont
, firstChar
, lastChar
, buffer
);
1591 else if (dc
->funcs
->pGetCharWidth
)
1592 ret
= dc
->funcs
->pGetCharWidth( dc
->physDev
, firstChar
, lastChar
, buffer
);
1596 /* convert device units to logical */
1597 for( i
= firstChar
; i
<= lastChar
; i
++, buffer
++ )
1598 *buffer
= INTERNAL_XDSTOWS(dc
, *buffer
);
1601 GDI_ReleaseObj( hdc
);
1606 /***********************************************************************
1607 * GetCharWidthA (GDI32.@)
1608 * GetCharWidth32A (GDI32.@)
1610 BOOL WINAPI
GetCharWidth32A( HDC hdc
, UINT firstChar
, UINT lastChar
,
1613 INT i
, wlen
, count
= (INT
)(lastChar
- firstChar
+ 1);
1618 if(count
<= 0) return FALSE
;
1620 str
= HeapAlloc(GetProcessHeap(), 0, count
);
1621 for(i
= 0; i
< count
; i
++)
1622 str
[i
] = (BYTE
)(firstChar
+ i
);
1624 wstr
= FONT_mbtowc(str
, count
, &wlen
);
1626 for(i
= 0; i
< wlen
; i
++)
1628 if(!GetCharWidth32W(hdc
, wstr
[i
], wstr
[i
], buffer
))
1636 HeapFree(GetProcessHeap(), 0, str
);
1637 HeapFree(GetProcessHeap(), 0, wstr
);
1643 /***********************************************************************
1644 * ExtTextOutA (GDI32.@)
1648 BOOL WINAPI
ExtTextOutA( HDC hdc
, INT x
, INT y
, UINT flags
,
1649 const RECT
*lprect
, LPCSTR str
, UINT count
, const INT
*lpDx
)
1656 if (flags
& ETO_GLYPH_INDEX
)
1657 return ExtTextOutW( hdc
, x
, y
, flags
, lprect
, (LPCWSTR
)str
, count
, lpDx
);
1659 p
= FONT_mbtowc(str
, count
, &wlen
);
1662 unsigned int i
= 0, j
= 0;
1664 lpDxW
= HeapAlloc( GetProcessHeap(), 0, wlen
*sizeof(INT
));
1666 if(IsDBCSLeadByte(str
[i
])) {
1667 lpDxW
[j
++] = lpDx
[i
] + lpDx
[i
+1];
1670 lpDxW
[j
++] = lpDx
[i
];
1676 ret
= ExtTextOutW( hdc
, x
, y
, flags
, lprect
, p
, wlen
, lpDxW
);
1678 HeapFree( GetProcessHeap(), 0, p
);
1679 HeapFree( GetProcessHeap(), 0, lpDxW
);
1684 /***********************************************************************
1685 * ExtTextOutW (GDI32.@)
1687 * Draws text using the currently selected font, background color, and text color.
1691 * x,y [I] coordinates of string
1693 * ETO_GRAYED - undocumented on MSDN
1694 * ETO_OPAQUE - use background color for fill the rectangle
1695 * ETO_CLIPPED - clipping text to the rectangle
1696 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1697 * than encoded characters. Implies ETO_IGNORELANGUAGE
1698 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1699 * Affects BiDi ordering
1700 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1701 * ETO_PDY - unimplemented
1702 * ETO_NUMERICSLATIN - unimplemented always assumed -
1703 * do not translate numbers into locale representations
1704 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1705 * lprect [I] dimensions for clipping or/and opaquing
1706 * str [I] text string
1707 * count [I] number of symbols in string
1708 * lpDx [I] optional parameter with distance between drawing characters
1714 BOOL WINAPI
ExtTextOutW( HDC hdc
, INT x
, INT y
, UINT flags
,
1715 const RECT
*lprect
, LPCWSTR str
, UINT count
, const INT
*lpDx
)
1718 LPWSTR reordered_str
= (LPWSTR
)str
;
1719 WORD
*glyphs
= NULL
;
1720 UINT align
= GetTextAlign( hdc
);
1724 double cosEsc
, sinEsc
;
1725 INT
*deltas
= NULL
, char_extra
;
1728 BOOL done_extents
= FALSE
;
1729 INT width
, xwidth
= 0, ywidth
= 0;
1731 DC
* dc
= DC_GetDCUpdate( hdc
);
1733 if (!dc
) return FALSE
;
1735 if (flags
& (ETO_NUMERICSLOCAL
| ETO_NUMERICSLATIN
| ETO_PDY
))
1736 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY unimplemented\n");
1738 if (!dc
->funcs
->pExtTextOut
&& !PATH_IsPathOpen(dc
->path
))
1740 GDI_ReleaseObj( hdc
);
1744 type
= GetObjectType(hdc
);
1745 if(type
== OBJ_METADC
|| type
== OBJ_ENHMETADC
)
1747 ret
= dc
->funcs
->pExtTextOut(dc
->physDev
, x
, y
, flags
, lprect
, str
, count
, lpDx
);
1748 GDI_ReleaseObj( hdc
);
1752 if( !(flags
& (ETO_GLYPH_INDEX
| ETO_IGNORELANGUAGE
)) && BidiAvail
&& count
> 0 )
1754 reordered_str
= HeapAlloc(GetProcessHeap(), 0, count
*sizeof(WCHAR
));
1756 BIDI_Reorder( str
, count
, GCP_REORDER
,
1757 ((flags
&ETO_RTLREADING
)!=0 || (GetTextAlign(hdc
)&TA_RTLREADING
)!=0)?
1758 WINE_GCPW_FORCE_RTL
:WINE_GCPW_FORCE_LTR
,
1759 reordered_str
, count
, NULL
);
1761 flags
|= ETO_IGNORELANGUAGE
;
1764 TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc
, x
, y
, flags
,
1765 lprect
, debugstr_wn(str
, count
), count
, lpDx
);
1767 if(flags
& ETO_GLYPH_INDEX
)
1768 glyphs
= reordered_str
;
1771 TRACE("rect: %ld,%ld - %ld,%ld\n", lprect
->left
, lprect
->top
, lprect
->right
,
1773 TRACE("align = %x bkmode = %x mapmode = %x\n", align
, GetBkMode(hdc
), GetMapMode(hdc
));
1775 if(align
& TA_UPDATECP
)
1777 GetCurrentPositionEx( hdc
, &pt
);
1782 GetTextMetricsW(hdc
, &tm
);
1783 GetObjectW(GetCurrentObject(hdc
, OBJ_FONT
), sizeof(lf
), &lf
);
1785 if(!(tm
.tmPitchAndFamily
& TMPF_VECTOR
)) /* Non-scalable fonts shouldn't be rotated */
1786 lf
.lfEscapement
= 0;
1788 if(lf
.lfEscapement
!= 0)
1790 cosEsc
= cos(lf
.lfEscapement
* M_PI
/ 1800);
1791 sinEsc
= sin(lf
.lfEscapement
* M_PI
/ 1800);
1799 if(flags
& (ETO_CLIPPED
| ETO_OPAQUE
))
1803 if(flags
& ETO_CLIPPED
) goto done
;
1804 if(flags
& ETO_GLYPH_INDEX
)
1805 GetTextExtentPointI(hdc
, glyphs
, count
, &sz
);
1807 GetTextExtentPointW(hdc
, reordered_str
, count
, &sz
);
1809 done_extents
= TRUE
;
1812 rc
.right
= x
+ sz
.cx
;
1813 rc
.bottom
= y
+ sz
.cy
;
1820 LPtoDP(hdc
, (POINT
*)&rc
, 2);
1822 if(rc
.left
> rc
.right
) {INT tmp
= rc
.left
; rc
.left
= rc
.right
; rc
.right
= tmp
;}
1823 if(rc
.top
> rc
.bottom
) {INT tmp
= rc
.top
; rc
.top
= rc
.bottom
; rc
.bottom
= tmp
;}
1826 if ((flags
& ETO_OPAQUE
) && !PATH_IsPathOpen(dc
->path
))
1827 dc
->funcs
->pExtTextOut(dc
->physDev
, 0, 0, ETO_OPAQUE
, &rc
, NULL
, 0, NULL
);
1837 LPtoDP(hdc
, &pt
, 1);
1841 char_extra
= GetTextCharacterExtra(hdc
);
1843 if(char_extra
|| dc
->breakExtra
|| lpDx
)
1847 deltas
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(INT
));
1848 for(i
= 0; i
< count
; i
++)
1851 deltas
[i
] = lpDx
[i
] + char_extra
;
1854 if(flags
& ETO_GLYPH_INDEX
)
1855 GetTextExtentPointI(hdc
, glyphs
+ i
, 1, &tmpsz
);
1857 GetTextExtentPointW(hdc
, reordered_str
+ i
, 1, &tmpsz
);
1859 deltas
[i
] = tmpsz
.cx
;
1862 if (!(flags
& ETO_GLYPH_INDEX
) && dc
->breakExtra
&& reordered_str
[i
] == tm
.tmBreakChar
)
1864 deltas
[i
] = deltas
[i
] + dc
->breakExtra
;
1866 deltas
[i
] = INTERNAL_XWSTODS(dc
, deltas
[i
]);
1874 if(flags
& ETO_GLYPH_INDEX
)
1875 GetTextExtentPointI(hdc
, glyphs
, count
, &sz
);
1877 GetTextExtentPointW(hdc
, reordered_str
, count
, &sz
);
1878 done_extents
= TRUE
;
1880 width
= INTERNAL_XWSTODS(dc
, sz
.cx
);
1882 xwidth
= width
* cosEsc
;
1883 ywidth
= width
* sinEsc
;
1885 tm
.tmAscent
= abs(INTERNAL_YWSTODS(dc
, tm
.tmAscent
));
1886 tm
.tmDescent
= abs(INTERNAL_YWSTODS(dc
, tm
.tmDescent
));
1887 switch( align
& (TA_LEFT
| TA_RIGHT
| TA_CENTER
) )
1890 if (align
& TA_UPDATECP
)
1894 DPtoLP(hdc
, &pt
, 1);
1895 MoveToEx(hdc
, pt
.x
, pt
.y
, NULL
);
1907 if (align
& TA_UPDATECP
)
1911 DPtoLP(hdc
, &pt
, 1);
1912 MoveToEx(hdc
, pt
.x
, pt
.y
, NULL
);
1917 switch( align
& (TA_TOP
| TA_BOTTOM
| TA_BASELINE
) )
1920 y
+= tm
.tmAscent
* cosEsc
;
1921 x
+= tm
.tmAscent
* sinEsc
;
1925 y
-= tm
.tmDescent
* cosEsc
;
1926 x
-= tm
.tmDescent
* sinEsc
;
1933 if (GetBkMode(hdc
) != TRANSPARENT
&& !PATH_IsPathOpen(dc
->path
))
1935 if(!((flags
& ETO_CLIPPED
) && (flags
& ETO_OPAQUE
)))
1937 if(!(flags
& ETO_OPAQUE
) || x
< rc
.left
|| x
+ width
>= rc
.right
||
1938 y
- tm
.tmAscent
< rc
.top
|| y
+ tm
.tmDescent
>= rc
.bottom
)
1942 rc
.right
= x
+ width
;
1943 rc
.top
= y
- tm
.tmAscent
;
1944 rc
.bottom
= y
+ tm
.tmDescent
;
1945 dc
->funcs
->pExtTextOut(dc
->physDev
, 0, 0, ETO_OPAQUE
, &rc
, NULL
, 0, NULL
);
1950 if(FontIsLinked(hdc
) && !(flags
& ETO_GLYPH_INDEX
))
1952 HFONT orig_font
= dc
->hFont
, cur_font
;
1954 INT span
= 0, *offsets
= NULL
, i
;
1956 glyphs
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(WORD
));
1957 for(i
= 0; i
< count
; i
++)
1959 WineEngGetLinkedHFont(dc
, reordered_str
[i
], &cur_font
, &glyph
);
1960 if(cur_font
!= dc
->hFont
)
1965 offsets
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(*deltas
));
1970 for(j
= 1; j
< count
; j
++)
1972 GetTextExtentPointW(hdc
, reordered_str
+ j
- 1, 1, &tmpsz
);
1973 offsets
[j
] = offsets
[j
-1] + INTERNAL_XWSTODS(dc
, tmpsz
.cx
);
1978 for(j
= 1; j
< count
; j
++)
1979 offsets
[j
] = offsets
[j
-1] + deltas
[j
];
1984 if (PATH_IsPathOpen(dc
->path
))
1985 ret
= PATH_ExtTextOut(dc
, x
+ offsets
[i
- span
] * cosEsc
, y
- offsets
[i
- span
] * sinEsc
,
1986 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
,
1987 glyphs
, span
, deltas
? deltas
+ i
- span
: NULL
);
1989 dc
->funcs
->pExtTextOut(dc
->physDev
, x
+ offsets
[i
- span
] * cosEsc
, y
- offsets
[i
- span
] * sinEsc
,
1990 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
,
1991 glyphs
, span
, deltas
? deltas
+ i
- span
: NULL
);
1994 SelectObject(hdc
, cur_font
);
1996 glyphs
[span
++] = glyph
;
2000 if (PATH_IsPathOpen(dc
->path
))
2001 ret
= PATH_ExtTextOut(dc
, x
+ (offsets
? offsets
[count
- span
] * cosEsc
: 0),
2002 y
- (offsets
? offsets
[count
- span
] * sinEsc
: 0),
2003 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
,
2004 glyphs
, span
, deltas
? deltas
+ count
- span
: NULL
);
2006 ret
= dc
->funcs
->pExtTextOut(dc
->physDev
, x
+ (offsets
? offsets
[count
- span
] * cosEsc
: 0),
2007 y
- (offsets
? offsets
[count
- span
] * sinEsc
: 0),
2008 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
,
2009 glyphs
, span
, deltas
? deltas
+ count
- span
: NULL
);
2010 SelectObject(hdc
, orig_font
);
2011 HeapFree(GetProcessHeap(), 0, offsets
);
2017 if(!(flags
& ETO_GLYPH_INDEX
) && dc
->gdiFont
)
2019 glyphs
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(WORD
));
2020 GetGlyphIndicesW(hdc
, reordered_str
, count
, glyphs
, 0);
2021 flags
|= ETO_GLYPH_INDEX
;
2024 if (PATH_IsPathOpen(dc
->path
))
2025 ret
= PATH_ExtTextOut(dc
, x
, y
, (flags
& ~ETO_OPAQUE
), &rc
,
2026 glyphs
? glyphs
: reordered_str
, count
, deltas
);
2028 ret
= dc
->funcs
->pExtTextOut(dc
->physDev
, x
, y
, (flags
& ~ETO_OPAQUE
), &rc
,
2029 glyphs
? glyphs
: reordered_str
, count
, deltas
);
2033 HeapFree(GetProcessHeap(), 0, deltas
);
2034 if(glyphs
!= reordered_str
)
2035 HeapFree(GetProcessHeap(), 0, glyphs
);
2036 if(reordered_str
!= str
)
2037 HeapFree(GetProcessHeap(), 0, reordered_str
);
2039 GDI_ReleaseObj( hdc
);
2041 if (ret
&& (lf
.lfUnderline
|| lf
.lfStrikeOut
))
2043 int underlinePos
, strikeoutPos
;
2044 int underlineWidth
, strikeoutWidth
;
2045 UINT size
= GetOutlineTextMetricsW(hdc
, 0, NULL
);
2046 OUTLINETEXTMETRICW
* otm
= NULL
;
2051 underlineWidth
= tm
.tmAscent
/ 20 + 1;
2052 strikeoutPos
= tm
.tmAscent
/ 2;
2053 strikeoutWidth
= underlineWidth
;
2057 otm
= HeapAlloc(GetProcessHeap(), 0, size
);
2058 GetOutlineTextMetricsW(hdc
, size
, otm
);
2059 underlinePos
= otm
->otmsUnderscorePosition
;
2060 underlineWidth
= otm
->otmsUnderscoreSize
;
2061 strikeoutPos
= otm
->otmsStrikeoutPosition
;
2062 strikeoutWidth
= otm
->otmsStrikeoutSize
;
2063 HeapFree(GetProcessHeap(), 0, otm
);
2066 if (PATH_IsPathOpen(dc
->path
))
2070 HBRUSH hbrush
= CreateSolidBrush(GetTextColor(hdc
));
2072 hbrush
= SelectObject(hdc
, hbrush
);
2073 hpen
= SelectObject(hdc
, GetStockObject(NULL_PEN
));
2077 pts
[0].x
= x
- underlinePos
* sinEsc
;
2078 pts
[0].y
= y
- underlinePos
* cosEsc
;
2079 pts
[1].x
= x
+ xwidth
- underlinePos
* sinEsc
;
2080 pts
[1].y
= y
- ywidth
- underlinePos
* cosEsc
;
2081 pts
[2].x
= pts
[1].x
+ underlineWidth
* sinEsc
;
2082 pts
[2].y
= pts
[1].y
+ underlineWidth
* cosEsc
;
2083 pts
[3].x
= pts
[0].x
+ underlineWidth
* sinEsc
;
2084 pts
[3].y
= pts
[0].y
+ underlineWidth
* cosEsc
;
2085 pts
[4].x
= pts
[0].x
;
2086 pts
[4].y
= pts
[0].y
;
2087 DPtoLP(hdc
, pts
, 5);
2088 Polygon(hdc
, pts
, 5);
2093 pts
[0].x
= x
- strikeoutPos
* sinEsc
;
2094 pts
[0].y
= y
- strikeoutPos
* cosEsc
;
2095 pts
[1].x
= x
+ xwidth
- strikeoutPos
* sinEsc
;
2096 pts
[1].y
= y
- ywidth
- strikeoutPos
* cosEsc
;
2097 pts
[2].x
= pts
[1].x
+ strikeoutWidth
* sinEsc
;
2098 pts
[2].y
= pts
[1].y
+ strikeoutWidth
* cosEsc
;
2099 pts
[3].x
= pts
[0].x
+ strikeoutWidth
* sinEsc
;
2100 pts
[3].y
= pts
[0].y
+ strikeoutWidth
* cosEsc
;
2101 pts
[4].x
= pts
[0].x
;
2102 pts
[4].y
= pts
[0].y
;
2103 DPtoLP(hdc
, pts
, 5);
2104 Polygon(hdc
, pts
, 5);
2107 SelectObject(hdc
, hpen
);
2108 hbrush
= SelectObject(hdc
, hbrush
);
2109 DeleteObject(hbrush
);
2113 POINT pts
[2], oldpt
;
2118 hpen
= CreatePen(PS_SOLID
, underlineWidth
, GetTextColor(hdc
));
2119 hpen
= SelectObject(hdc
, hpen
);
2122 pts
[1].x
= x
+ xwidth
;
2123 pts
[1].y
= y
- ywidth
;
2124 DPtoLP(hdc
, pts
, 2);
2125 MoveToEx(hdc
, pts
[0].x
- underlinePos
* sinEsc
, pts
[0].y
- underlinePos
* cosEsc
, &oldpt
);
2126 LineTo(hdc
, pts
[1].x
- underlinePos
* sinEsc
, pts
[1].y
- underlinePos
* cosEsc
);
2127 MoveToEx(hdc
, oldpt
.x
, oldpt
.y
, NULL
);
2128 DeleteObject(SelectObject(hdc
, hpen
));
2133 hpen
= CreatePen(PS_SOLID
, strikeoutWidth
, GetTextColor(hdc
));
2134 hpen
= SelectObject(hdc
, hpen
);
2137 pts
[1].x
= x
+ xwidth
;
2138 pts
[1].y
= y
- ywidth
;
2139 DPtoLP(hdc
, pts
, 2);
2140 MoveToEx(hdc
, pts
[0].x
- strikeoutPos
* sinEsc
, pts
[0].y
- strikeoutPos
* cosEsc
, &oldpt
);
2141 LineTo(hdc
, pts
[1].x
- strikeoutPos
* sinEsc
, pts
[1].y
- strikeoutPos
* cosEsc
);
2142 MoveToEx(hdc
, oldpt
.x
, oldpt
.y
, NULL
);
2143 DeleteObject(SelectObject(hdc
, hpen
));
2152 /***********************************************************************
2153 * TextOutA (GDI32.@)
2155 BOOL WINAPI
TextOutA( HDC hdc
, INT x
, INT y
, LPCSTR str
, INT count
)
2157 return ExtTextOutA( hdc
, x
, y
, 0, NULL
, str
, count
, NULL
);
2161 /***********************************************************************
2162 * TextOutW (GDI32.@)
2164 BOOL WINAPI
TextOutW(HDC hdc
, INT x
, INT y
, LPCWSTR str
, INT count
)
2166 return ExtTextOutW( hdc
, x
, y
, 0, NULL
, str
, count
, NULL
);
2170 /***********************************************************************
2171 * PolyTextOutA (GDI32.@)
2175 BOOL WINAPI
PolyTextOutA ( HDC hdc
, /* [in] Handle to device context */
2176 PPOLYTEXTA pptxt
, /* [in] Array of strings */
2177 INT cStrings
) /* [in] Number of strings in array */
2179 for (; cStrings
>0; cStrings
--, pptxt
++)
2180 if (!ExtTextOutA( hdc
, pptxt
->x
, pptxt
->y
, pptxt
->uiFlags
, &pptxt
->rcl
, pptxt
->lpstr
, pptxt
->n
, pptxt
->pdx
))
2187 /***********************************************************************
2188 * PolyTextOutW (GDI32.@)
2190 * Draw several Strings
2196 BOOL WINAPI
PolyTextOutW ( HDC hdc
, /* [in] Handle to device context */
2197 PPOLYTEXTW pptxt
, /* [in] Array of strings */
2198 INT cStrings
) /* [in] Number of strings in array */
2200 for (; cStrings
>0; cStrings
--, pptxt
++)
2201 if (!ExtTextOutW( hdc
, pptxt
->x
, pptxt
->y
, pptxt
->uiFlags
, &pptxt
->rcl
, pptxt
->lpstr
, pptxt
->n
, pptxt
->pdx
))
2207 /* FIXME: all following APIs ******************************************/
2210 /***********************************************************************
2211 * SetMapperFlags (GDI32.@)
2213 DWORD WINAPI
SetMapperFlags( HDC hDC
, DWORD dwFlag
)
2215 DC
*dc
= DC_GetDCPtr( hDC
);
2218 if(dc
->funcs
->pSetMapperFlags
)
2220 ret
= dc
->funcs
->pSetMapperFlags( dc
->physDev
, dwFlag
);
2221 /* FIXME: ret is just a success flag, we should return a proper value */
2224 FIXME("(%p, 0x%08lx): stub - harmless\n", hDC
, dwFlag
);
2225 GDI_ReleaseObj( hDC
);
2229 /***********************************************************************
2230 * GetAspectRatioFilterEx (GDI.486)
2232 BOOL16 WINAPI
GetAspectRatioFilterEx16( HDC16 hdc
, LPSIZE16 pAspectRatio
)
2234 FIXME("(%04x, %p): -- Empty Stub !\n", hdc
, pAspectRatio
);
2238 /***********************************************************************
2239 * GetAspectRatioFilterEx (GDI32.@)
2241 BOOL WINAPI
GetAspectRatioFilterEx( HDC hdc
, LPSIZE pAspectRatio
)
2243 FIXME("(%p, %p): -- Empty Stub !\n", hdc
, pAspectRatio
);
2248 /***********************************************************************
2249 * GetCharABCWidthsA (GDI32.@)
2251 * See GetCharABCWidthsW.
2253 BOOL WINAPI
GetCharABCWidthsA(HDC hdc
, UINT firstChar
, UINT lastChar
,
2256 INT i
, wlen
, count
= (INT
)(lastChar
- firstChar
+ 1);
2261 if(count
<= 0) return FALSE
;
2263 str
= HeapAlloc(GetProcessHeap(), 0, count
);
2264 for(i
= 0; i
< count
; i
++)
2265 str
[i
] = (BYTE
)(firstChar
+ i
);
2267 wstr
= FONT_mbtowc(str
, count
, &wlen
);
2269 for(i
= 0; i
< wlen
; i
++)
2271 if(!GetCharABCWidthsW(hdc
, wstr
[i
], wstr
[i
], abc
))
2279 HeapFree(GetProcessHeap(), 0, str
);
2280 HeapFree(GetProcessHeap(), 0, wstr
);
2286 /******************************************************************************
2287 * GetCharABCWidthsW [GDI32.@]
2289 * Retrieves widths of characters in range.
2292 * hdc [I] Handle of device context
2293 * firstChar [I] First character in range to query
2294 * lastChar [I] Last character in range to query
2295 * abc [O] Address of character-width structure
2298 * Only works with TrueType fonts
2304 BOOL WINAPI
GetCharABCWidthsW( HDC hdc
, UINT firstChar
, UINT lastChar
,
2307 DC
*dc
= DC_GetDCPtr(hdc
);
2311 if (!dc
) return FALSE
;
2314 ret
= WineEngGetCharABCWidths( dc
->gdiFont
, firstChar
, lastChar
, abc
);
2320 /* convert device units to logical */
2321 for( i
= firstChar
; i
<= lastChar
; i
++, abc
++ ) {
2322 abc
->abcA
= INTERNAL_XDSTOWS(dc
, abc
->abcA
);
2323 abc
->abcB
= INTERNAL_XDSTOWS(dc
, abc
->abcB
);
2324 abc
->abcC
= INTERNAL_XDSTOWS(dc
, abc
->abcC
);
2329 GDI_ReleaseObj(hdc
);
2334 /******************************************************************************
2335 * GetCharABCWidthsI [GDI32.@]
2337 * Retrieves widths of characters in range.
2340 * hdc [I] Handle of device context
2341 * firstChar [I] First glyphs in range to query
2342 * count [I] Last glyphs in range to query
2343 * pgi [i] Array of glyphs to query
2344 * abc [O] Address of character-width structure
2347 * Only works with TrueType fonts
2353 BOOL WINAPI
GetCharABCWidthsI( HDC hdc
, UINT firstChar
, UINT count
,
2354 LPWORD pgi
, LPABC abc
)
2356 DC
*dc
= DC_GetDCPtr(hdc
);
2360 if (!dc
) return FALSE
;
2363 ret
= WineEngGetCharABCWidthsI( dc
->gdiFont
, firstChar
, count
, pgi
, abc
);
2369 /* convert device units to logical */
2370 for( i
= firstChar
; i
<= count
; i
++, abc
++ ) {
2371 abc
->abcA
= INTERNAL_XDSTOWS(dc
, abc
->abcA
);
2372 abc
->abcB
= INTERNAL_XDSTOWS(dc
, abc
->abcB
);
2373 abc
->abcC
= INTERNAL_XDSTOWS(dc
, abc
->abcC
);
2378 GDI_ReleaseObj(hdc
);
2383 /***********************************************************************
2384 * GetGlyphOutlineA (GDI32.@)
2386 DWORD WINAPI
GetGlyphOutlineA( HDC hdc
, UINT uChar
, UINT fuFormat
,
2387 LPGLYPHMETRICS lpgm
, DWORD cbBuffer
,
2388 LPVOID lpBuffer
, const MAT2
*lpmat2
)
2394 if(!(fuFormat
& GGO_GLYPH_INDEX
)) {
2397 if(uChar
> 0xff) { /* but, 2 bytes character only */
2399 mbchs
[0] = (uChar
& 0xff00) >> 8;
2400 mbchs
[1] = (uChar
& 0xff);
2403 mbchs
[0] = (uChar
& 0xff);
2405 p
= FONT_mbtowc(mbchs
, len
, NULL
);
2409 ret
= GetGlyphOutlineW(hdc
, c
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
,
2411 HeapFree(GetProcessHeap(), 0, p
);
2415 /***********************************************************************
2416 * GetGlyphOutlineW (GDI32.@)
2418 DWORD WINAPI
GetGlyphOutlineW( HDC hdc
, UINT uChar
, UINT fuFormat
,
2419 LPGLYPHMETRICS lpgm
, DWORD cbBuffer
,
2420 LPVOID lpBuffer
, const MAT2
*lpmat2
)
2422 DC
*dc
= DC_GetDCPtr(hdc
);
2425 TRACE("(%p, %04x, %04x, %p, %ld, %p, %p)\n",
2426 hdc
, uChar
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
, lpmat2
);
2428 if(!dc
) return GDI_ERROR
;
2431 ret
= WineEngGetGlyphOutline(dc
->gdiFont
, uChar
, fuFormat
, lpgm
,
2432 cbBuffer
, lpBuffer
, lpmat2
);
2436 GDI_ReleaseObj(hdc
);
2441 /***********************************************************************
2442 * CreateScalableFontResourceA (GDI32.@)
2444 BOOL WINAPI
CreateScalableFontResourceA( DWORD fHidden
,
2445 LPCSTR lpszResourceFile
,
2446 LPCSTR lpszFontFile
,
2447 LPCSTR lpszCurrentPath
)
2451 /* fHidden=1 - only visible for the calling app, read-only, not
2452 * enumbered with EnumFonts/EnumFontFamilies
2453 * lpszCurrentPath can be NULL
2455 FIXME("(%ld,%s,%s,%s): stub\n",
2456 fHidden
, debugstr_a(lpszResourceFile
), debugstr_a(lpszFontFile
),
2457 debugstr_a(lpszCurrentPath
) );
2459 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2460 if ((f
= CreateFileA(lpszResourceFile
, 0, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, 0)) != INVALID_HANDLE_VALUE
) {
2462 SetLastError(ERROR_FILE_EXISTS
);
2465 return FALSE
; /* create failed */
2468 /***********************************************************************
2469 * CreateScalableFontResourceW (GDI32.@)
2471 BOOL WINAPI
CreateScalableFontResourceW( DWORD fHidden
,
2472 LPCWSTR lpszResourceFile
,
2473 LPCWSTR lpszFontFile
,
2474 LPCWSTR lpszCurrentPath
)
2476 FIXME("(%ld,%p,%p,%p): stub\n",
2477 fHidden
, lpszResourceFile
, lpszFontFile
, lpszCurrentPath
);
2478 return FALSE
; /* create failed */
2481 /*************************************************************************
2482 * GetKerningPairsA (GDI32.@)
2484 DWORD WINAPI
GetKerningPairsA( HDC hDC
, DWORD cPairs
,
2485 LPKERNINGPAIR lpKerningPairs
)
2487 return GetKerningPairsW( hDC
, cPairs
, lpKerningPairs
);
2491 /*************************************************************************
2492 * GetKerningPairsW (GDI32.@)
2494 DWORD WINAPI
GetKerningPairsW( HDC hDC
, DWORD cPairs
,
2495 LPKERNINGPAIR lpKerningPairs
)
2498 FIXME("(%p,%ld,%p): almost empty stub!\n", hDC
, cPairs
, lpKerningPairs
);
2500 if(!lpKerningPairs
) /* return the number of kerning pairs */
2503 for (i
= 0; i
< cPairs
; i
++)
2504 lpKerningPairs
[i
].iKernAmount
= 0;
2508 /*************************************************************************
2509 * TranslateCharsetInfo [GDI32.@]
2511 * Fills a CHARSETINFO structure for a character set, code page, or
2512 * font. This allows making the correspondance between different labelings
2513 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2514 * of the same encoding.
2516 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2517 * only one codepage should be set in *lpSrc.
2520 * TRUE on success, FALSE on failure.
2523 BOOL WINAPI
TranslateCharsetInfo(
2524 LPDWORD lpSrc
, /* [in]
2525 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2526 if flags == TCI_SRCCHARSET: a character set value
2527 if flags == TCI_SRCCODEPAGE: a code page value
2529 LPCHARSETINFO lpCs
, /* [out] structure to receive charset information */
2530 DWORD flags
/* [in] determines interpretation of lpSrc */)
2534 case TCI_SRCFONTSIG
:
2535 while (!(*lpSrc
>>index
& 0x0001) && index
<MAXTCIINDEX
) index
++;
2537 case TCI_SRCCODEPAGE
:
2538 while ((UINT
) (lpSrc
) != FONT_tci
[index
].ciACP
&& index
< MAXTCIINDEX
) index
++;
2540 case TCI_SRCCHARSET
:
2541 while ((UINT
) (lpSrc
) != FONT_tci
[index
].ciCharset
&& index
< MAXTCIINDEX
) index
++;
2546 if (index
>= MAXTCIINDEX
|| FONT_tci
[index
].ciCharset
== DEFAULT_CHARSET
) return FALSE
;
2547 memcpy(lpCs
, &FONT_tci
[index
], sizeof(CHARSETINFO
));
2551 /*************************************************************************
2552 * GetFontLanguageInfo (GDI32.@)
2554 DWORD WINAPI
GetFontLanguageInfo(HDC hdc
)
2556 FONTSIGNATURE fontsig
;
2557 static const DWORD GCP_DBCS_MASK
=0x003F0000,
2558 GCP_DIACRITIC_MASK
=0x00000000,
2559 FLI_GLYPHS_MASK
=0x00000000,
2560 GCP_GLYPHSHAPE_MASK
=0x00000040,
2561 GCP_KASHIDA_MASK
=0x00000000,
2562 GCP_LIGATE_MASK
=0x00000000,
2563 GCP_USEKERNING_MASK
=0x00000000,
2564 GCP_REORDER_MASK
=0x00000060;
2568 GetTextCharsetInfo( hdc
, &fontsig
, 0 );
2569 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2571 if( (fontsig
.fsCsb
[0]&GCP_DBCS_MASK
)!=0 )
2574 if( (fontsig
.fsCsb
[0]&GCP_DIACRITIC_MASK
)!=0 )
2575 result
|=GCP_DIACRITIC
;
2577 if( (fontsig
.fsCsb
[0]&FLI_GLYPHS_MASK
)!=0 )
2580 if( (fontsig
.fsCsb
[0]&GCP_GLYPHSHAPE_MASK
)!=0 )
2581 result
|=GCP_GLYPHSHAPE
;
2583 if( (fontsig
.fsCsb
[0]&GCP_KASHIDA_MASK
)!=0 )
2584 result
|=GCP_KASHIDA
;
2586 if( (fontsig
.fsCsb
[0]&GCP_LIGATE_MASK
)!=0 )
2589 if( (fontsig
.fsCsb
[0]&GCP_USEKERNING_MASK
)!=0 )
2590 result
|=GCP_USEKERNING
;
2592 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2593 if( GetTextAlign( hdc
) & TA_RTLREADING
)
2594 if( (fontsig
.fsCsb
[0]&GCP_REORDER_MASK
)!=0 )
2595 result
|=GCP_REORDER
;
2601 /*************************************************************************
2602 * GetFontData [GDI32.@]
2604 * Retrieve data for TrueType font.
2608 * success: Number of bytes returned
2609 * failure: GDI_ERROR
2613 * Calls SetLastError()
2616 DWORD WINAPI
GetFontData(HDC hdc
, DWORD table
, DWORD offset
,
2617 LPVOID buffer
, DWORD length
)
2619 DC
*dc
= DC_GetDCPtr(hdc
);
2620 DWORD ret
= GDI_ERROR
;
2622 if(!dc
) return GDI_ERROR
;
2625 ret
= WineEngGetFontData(dc
->gdiFont
, table
, offset
, buffer
, length
);
2627 GDI_ReleaseObj(hdc
);
2631 /*************************************************************************
2632 * GetGlyphIndicesA [GDI32.@]
2634 DWORD WINAPI
GetGlyphIndicesA(HDC hdc
, LPCSTR lpstr
, INT count
,
2635 LPWORD pgi
, DWORD flags
)
2641 TRACE("(%p, %s, %d, %p, 0x%lx)\n",
2642 hdc
, debugstr_an(lpstr
, count
), count
, pgi
, flags
);
2644 lpstrW
= FONT_mbtowc(lpstr
, count
, &countW
);
2645 ret
= GetGlyphIndicesW(hdc
, lpstrW
, countW
, pgi
, flags
);
2646 HeapFree(GetProcessHeap(), 0, lpstrW
);
2651 /*************************************************************************
2652 * GetGlyphIndicesW [GDI32.@]
2654 DWORD WINAPI
GetGlyphIndicesW(HDC hdc
, LPCWSTR lpstr
, INT count
,
2655 LPWORD pgi
, DWORD flags
)
2657 DC
*dc
= DC_GetDCPtr(hdc
);
2658 DWORD ret
= GDI_ERROR
;
2660 TRACE("(%p, %s, %d, %p, 0x%lx)\n",
2661 hdc
, debugstr_wn(lpstr
, count
), count
, pgi
, flags
);
2663 if(!dc
) return GDI_ERROR
;
2666 ret
= WineEngGetGlyphIndices(dc
->gdiFont
, lpstr
, count
, pgi
, flags
);
2668 GDI_ReleaseObj(hdc
);
2672 /*************************************************************************
2673 * GetCharacterPlacementA [GDI32.@]
2675 * See GetCharacterPlacementW.
2678 * the web browser control of ie4 calls this with dwFlags=0
2681 GetCharacterPlacementA(HDC hdc
, LPCSTR lpString
, INT uCount
,
2682 INT nMaxExtent
, GCP_RESULTSA
*lpResults
,
2687 GCP_RESULTSW resultsW
;
2690 TRACE("%s, %d, %d, 0x%08lx\n",
2691 debugstr_an(lpString
, uCount
), uCount
, nMaxExtent
, dwFlags
);
2693 /* both structs are equal in size */
2694 memcpy(&resultsW
, lpResults
, sizeof(resultsW
));
2696 lpStringW
= FONT_mbtowc(lpString
, uCount
, &uCountW
);
2697 if(lpResults
->lpOutString
)
2698 resultsW
.lpOutString
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*uCountW
);
2700 ret
= GetCharacterPlacementW(hdc
, lpStringW
, uCountW
, nMaxExtent
, &resultsW
, dwFlags
);
2702 lpResults
->nGlyphs
= resultsW
.nGlyphs
;
2703 lpResults
->nMaxFit
= resultsW
.nMaxFit
;
2705 if(lpResults
->lpOutString
) {
2706 WideCharToMultiByte(CP_ACP
, 0, resultsW
.lpOutString
, uCountW
,
2707 lpResults
->lpOutString
, uCount
, NULL
, NULL
);
2710 HeapFree(GetProcessHeap(), 0, lpStringW
);
2711 HeapFree(GetProcessHeap(), 0, resultsW
.lpOutString
);
2716 /*************************************************************************
2717 * GetCharacterPlacementW [GDI32.@]
2719 * Retrieve information about a string. This includes the width, reordering,
2720 * Glyphing and so on.
2724 * The width and height of the string if successful, 0 if failed.
2728 * All flags except GCP_REORDER are not yet implemented.
2729 * Reordering is not 100% complient to the Windows BiDi method.
2730 * Caret positioning is not yet implemented for BiDi.
2731 * Classes are not yet implemented.
2735 GetCharacterPlacementW(
2736 HDC hdc
, /* [in] Device context for which the rendering is to be done */
2737 LPCWSTR lpString
, /* [in] The string for which information is to be returned */
2738 INT uCount
, /* [in] Number of WORDS in string. */
2739 INT nMaxExtent
, /* [in] Maximum extent the string is to take (in HDC logical units) */
2740 GCP_RESULTSW
*lpResults
,/* [in/out] A pointer to a GCP_RESULTSW struct */
2741 DWORD dwFlags
/* [in] Flags specifying how to process the string */
2748 TRACE("%s, %d, %d, 0x%08lx\n",
2749 debugstr_wn(lpString
, uCount
), uCount
, nMaxExtent
, dwFlags
);
2751 TRACE("lStructSize=%ld, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2752 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2753 lpResults
->lStructSize
, lpResults
->lpOutString
, lpResults
->lpOrder
,
2754 lpResults
->lpDx
, lpResults
->lpCaretPos
, lpResults
->lpClass
,
2755 lpResults
->lpGlyphs
, lpResults
->nGlyphs
, lpResults
->nMaxFit
);
2757 if(dwFlags
&(~GCP_REORDER
)) FIXME("flags 0x%08lx ignored\n", dwFlags
);
2758 if(lpResults
->lpClass
) FIXME("classes not implemented\n");
2759 if (lpResults
->lpCaretPos
&& (dwFlags
& GCP_REORDER
))
2760 FIXME("Caret positions for complex scripts not implemented\n");
2762 nSet
= (UINT
)uCount
;
2763 if(nSet
> lpResults
->nGlyphs
)
2764 nSet
= lpResults
->nGlyphs
;
2766 /* return number of initialized fields */
2767 lpResults
->nGlyphs
= nSet
;
2769 if((dwFlags
&GCP_REORDER
)==0 || !BidiAvail
)
2771 /* Treat the case where no special handling was requested in a fastpath way */
2772 /* copy will do if the GCP_REORDER flag is not set */
2773 if(lpResults
->lpOutString
)
2774 memcpy( lpResults
->lpOutString
, lpString
, nSet
* sizeof(WCHAR
));
2776 if(lpResults
->lpOrder
)
2778 for(i
= 0; i
< nSet
; i
++)
2779 lpResults
->lpOrder
[i
] = i
;
2783 BIDI_Reorder( lpString
, uCount
, dwFlags
, WINE_GCPW_FORCE_LTR
, lpResults
->lpOutString
,
2784 nSet
, lpResults
->lpOrder
);
2787 /* FIXME: Will use the placement chars */
2788 if (lpResults
->lpDx
)
2791 for (i
= 0; i
< nSet
; i
++)
2793 if (GetCharWidth32W(hdc
, lpString
[i
], lpString
[i
], &c
))
2794 lpResults
->lpDx
[i
]= c
;
2798 if (lpResults
->lpCaretPos
&& !(dwFlags
& GCP_REORDER
))
2802 lpResults
->lpCaretPos
[0] = 0;
2803 for (i
= 1; i
< nSet
; i
++)
2804 if (GetTextExtentPoint32W(hdc
, &(lpString
[i
- 1]), 1, &size
))
2805 lpResults
->lpCaretPos
[i
] = (pos
+= size
.cx
);
2808 if(lpResults
->lpGlyphs
)
2809 GetGlyphIndicesW(hdc
, lpString
, nSet
, lpResults
->lpGlyphs
, 0);
2811 if (GetTextExtentPoint32W(hdc
, lpString
, uCount
, &size
))
2812 ret
= MAKELONG(size
.cx
, size
.cy
);
2817 /*************************************************************************
2818 * GetCharABCWidthsFloatA [GDI32.@]
2820 * See GetCharABCWidthsFloatW.
2822 BOOL WINAPI
GetCharABCWidthsFloatA( HDC hdc
, UINT first
, UINT last
, LPABCFLOAT abcf
)
2824 INT i
, wlen
, count
= (INT
)(last
- first
+ 1);
2829 if (count
<= 0) return FALSE
;
2831 str
= HeapAlloc(GetProcessHeap(), 0, count
);
2833 for(i
= 0; i
< count
; i
++)
2834 str
[i
] = (BYTE
)(first
+ i
);
2836 wstr
= FONT_mbtowc(str
, count
, &wlen
);
2838 for (i
= 0; i
< wlen
; i
++)
2840 if (!GetCharABCWidthsFloatW( hdc
, wstr
[i
], wstr
[i
], abcf
))
2848 HeapFree( GetProcessHeap(), 0, str
);
2849 HeapFree( GetProcessHeap(), 0, wstr
);
2854 /*************************************************************************
2855 * GetCharABCWidthsFloatW [GDI32.@]
2857 * Retrieves widths of a range of characters.
2860 * hdc [I] Handle to device context.
2861 * first [I] First character in range to query.
2862 * last [I] Last character in range to query.
2863 * abcf [O] Array of LPABCFLOAT structures.
2870 * Only works with TrueType fonts. It also doesn't return real
2871 * floats but converted integers because it's implemented on
2872 * top of GetCharABCWidthsW.
2874 BOOL WINAPI
GetCharABCWidthsFloatW( HDC hdc
, UINT first
, UINT last
, LPABCFLOAT abcf
)
2877 unsigned int i
, size
= sizeof(ABC
) * (last
- first
+ 1);
2880 TRACE("%p, %d, %d, %p - partial stub\n", hdc
, first
, last
, abcf
);
2882 abc
= HeapAlloc( GetProcessHeap(), 0, size
);
2883 if (!abc
) return FALSE
;
2885 ret
= GetCharABCWidthsW( hdc
, first
, last
, abc
);
2888 for (i
= first
; i
<= last
; i
++, abc
++, abcf
++)
2890 abcf
->abcfA
= abc
->abcA
;
2891 abcf
->abcfB
= abc
->abcB
;
2892 abcf
->abcfC
= abc
->abcC
;
2895 HeapFree( GetProcessHeap(), 0, abc
);
2899 /*************************************************************************
2900 * GetCharWidthFloatA [GDI32.@]
2902 BOOL WINAPI
GetCharWidthFloatA(HDC hdc
, UINT iFirstChar
,
2903 UINT iLastChar
, PFLOAT pxBuffer
)
2905 FIXME_(gdi
)("GetCharWidthFloatA, stub\n");
2909 /*************************************************************************
2910 * GetCharWidthFloatW [GDI32.@]
2912 BOOL WINAPI
GetCharWidthFloatW(HDC hdc
, UINT iFirstChar
,
2913 UINT iLastChar
, PFLOAT pxBuffer
)
2915 FIXME_(gdi
)("GetCharWidthFloatW, stub\n");
2920 /***********************************************************************
2922 * Font Resource API *
2924 ***********************************************************************/
2926 /***********************************************************************
2927 * AddFontResourceA (GDI32.@)
2929 INT WINAPI
AddFontResourceA( LPCSTR str
)
2931 return AddFontResourceExA( str
, 0, NULL
);
2934 /***********************************************************************
2935 * AddFontResourceW (GDI32.@)
2937 INT WINAPI
AddFontResourceW( LPCWSTR str
)
2939 return AddFontResourceExW(str
, 0, NULL
);
2943 /***********************************************************************
2944 * AddFontResourceExA (GDI32.@)
2946 INT WINAPI
AddFontResourceExA( LPCSTR str
, DWORD fl
, PVOID pdv
)
2948 DWORD len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
2949 LPWSTR strW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2952 MultiByteToWideChar(CP_ACP
, 0, str
, -1, strW
, len
);
2953 ret
= AddFontResourceExW(strW
, fl
, pdv
);
2954 HeapFree(GetProcessHeap(), 0, strW
);
2958 /***********************************************************************
2959 * AddFontResourceExW (GDI32.@)
2961 INT WINAPI
AddFontResourceExW( LPCWSTR str
, DWORD fl
, PVOID pdv
)
2963 return WineEngAddFontResourceEx(str
, fl
, pdv
);
2966 /***********************************************************************
2967 * RemoveFontResourceA (GDI32.@)
2969 BOOL WINAPI
RemoveFontResourceA( LPCSTR str
)
2971 return RemoveFontResourceExA(str
, 0, 0);
2974 /***********************************************************************
2975 * RemoveFontResourceW (GDI32.@)
2977 BOOL WINAPI
RemoveFontResourceW( LPCWSTR str
)
2979 return RemoveFontResourceExW(str
, 0, 0);
2982 /***********************************************************************
2983 * AddFontMemResourceEx (GDI32.@)
2985 HANDLE WINAPI
AddFontMemResourceEx( PVOID pbFont
, DWORD cbFont
, PVOID pdv
, DWORD
*pcFonts
)
2987 FIXME("(%p,%08lx,%p,%p): stub\n", pbFont
, cbFont
, pdv
, pcFonts
);
2991 /***********************************************************************
2992 * RemoveFontResourceExA (GDI32.@)
2994 BOOL WINAPI
RemoveFontResourceExA( LPCSTR str
, DWORD fl
, PVOID pdv
)
2996 DWORD len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
2997 LPWSTR strW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3000 MultiByteToWideChar(CP_ACP
, 0, str
, -1, strW
, len
);
3001 ret
= RemoveFontResourceExW(strW
, fl
, pdv
);
3002 HeapFree(GetProcessHeap(), 0, strW
);
3006 /***********************************************************************
3007 * RemoveFontResourceExW (GDI32.@)
3009 BOOL WINAPI
RemoveFontResourceExW( LPCWSTR str
, DWORD fl
, PVOID pdv
)
3011 return WineEngRemoveFontResourceEx(str
, fl
, pdv
);
3014 /***********************************************************************
3015 * GetTextCharset (GDI32.@)
3017 UINT WINAPI
GetTextCharset(HDC hdc
)
3019 /* MSDN docs say this is equivalent */
3020 return GetTextCharsetInfo(hdc
, NULL
, 0);
3023 /***********************************************************************
3024 * GetTextCharsetInfo (GDI32.@)
3026 UINT WINAPI
GetTextCharsetInfo(HDC hdc
, LPFONTSIGNATURE fs
, DWORD flags
)
3028 UINT ret
= DEFAULT_CHARSET
;
3029 DC
*dc
= DC_GetDCPtr(hdc
);
3034 ret
= WineEngGetTextCharsetInfo(dc
->gdiFont
, fs
, flags
);
3036 GDI_ReleaseObj(hdc
);
3039 if (ret
== DEFAULT_CHARSET
&& fs
)
3040 memset(fs
, 0, sizeof(FONTSIGNATURE
));
3044 /***********************************************************************
3045 * GdiGetCharDimensions (GDI32.@)
3047 * Gets the average width of the characters in the English alphabet.
3050 * hdc [I] Handle to the device context to measure on.
3051 * lptm [O] Pointer to memory to store the text metrics into.
3052 * height [O] On exit, the maximum height of characters in the English alphabet.
3055 * The average width of characters in the English alphabet.
3058 * This function is used by the dialog manager to get the size of a dialog
3059 * unit. It should also be used by other pieces of code that need to know
3060 * the size of a dialog unit in logical units without having access to the
3061 * window handle of the dialog.
3062 * Windows caches the font metrics from this function, but we don't and
3063 * there doesn't appear to be an immediate advantage to do so.
3066 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3068 LONG WINAPI
GdiGetCharDimensions(HDC hdc
, LPTEXTMETRICW lptm
, LONG
*height
)
3071 static const WCHAR alphabet
[] = {
3072 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3073 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3074 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3076 if(lptm
&& !GetTextMetricsW(hdc
, lptm
)) return 0;
3078 if(!GetTextExtentPointW(hdc
, alphabet
, 52, &sz
)) return 0;
3080 if (height
) *height
= sz
.cy
;
3081 return (sz
.cx
/ 26 + 1) / 2;
3084 BOOL WINAPI
EnableEUDC(BOOL fEnableEUDC
)
3086 FIXME("(%d): stub\n", fEnableEUDC
);
3090 /***********************************************************************
3091 * GetCharWidthI (GDI32.@)
3093 BOOL WINAPI
GetCharWidthI(HDC hdc
, UINT giFirst
, UINT cgi
, LPWORD pgi
, LPINT lpBuffer
)
3095 FIXME("(%p, %d, %d, %p, %p): stub\n", hdc
, giFirst
, cgi
, pgi
, lpBuffer
);
3099 /***********************************************************************
3100 * GetFontUnicodeRanges (GDI32.@)
3102 DWORD WINAPI
GetFontUnicodeRanges(HDC hdc
, LPGLYPHSET lpgs
)
3104 FIXME("(%p, %p): stub\n", hdc
, lpgs
);