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"
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 */
1056 return GetTextExtentExPointW(hdc
, str
, count
, 0, NULL
, NULL
, size
);
1059 /***********************************************************************
1060 * GetTextExtentPointI [GDI32.@]
1062 * Computes width and height of the array of glyph indices.
1068 BOOL WINAPI
GetTextExtentPointI(
1069 HDC hdc
, /* [in] Handle of device context */
1070 const WORD
*indices
, /* [in] Address of glyph index array */
1071 INT count
, /* [in] Number of glyphs in array */
1072 LPSIZE size
) /* [out] Address of structure for string size */
1075 DC
* dc
= DC_GetDCPtr( hdc
);
1076 if (!dc
) return FALSE
;
1079 ret
= WineEngGetTextExtentPointI(dc
->gdiFont
, indices
, count
, size
);
1080 size
->cx
= abs(INTERNAL_XDSTOWS(dc
, size
->cx
));
1081 size
->cy
= abs(INTERNAL_YDSTOWS(dc
, size
->cy
));
1082 size
->cx
+= count
* dc
->charExtra
;
1084 else if(dc
->funcs
->pGetTextExtentExPoint
) {
1085 FIXME("calling GetTextExtentExPoint\n");
1086 ret
= dc
->funcs
->pGetTextExtentExPoint( dc
->physDev
, (LPCWSTR
)indices
,
1087 count
, 0, NULL
, NULL
, size
);
1090 GDI_ReleaseObj( hdc
);
1092 TRACE("(%p %p %d %p): returning %ld x %ld\n",
1093 hdc
, indices
, count
, size
, size
->cx
, size
->cy
);
1098 /***********************************************************************
1099 * GetTextExtentPointA (GDI32.@)
1101 BOOL WINAPI
GetTextExtentPointA( HDC hdc
, LPCSTR str
, INT count
,
1104 TRACE("not bug compatible.\n");
1105 return GetTextExtentPoint32A( hdc
, str
, count
, size
);
1108 /***********************************************************************
1109 * GetTextExtentPointW (GDI32.@)
1111 BOOL WINAPI
GetTextExtentPointW( HDC hdc
, LPCWSTR str
, INT count
,
1114 TRACE("not bug compatible.\n");
1115 return GetTextExtentPoint32W( hdc
, str
, count
, size
);
1119 /***********************************************************************
1120 * GetTextExtentExPointA (GDI32.@)
1122 BOOL WINAPI
GetTextExtentExPointA( HDC hdc
, LPCSTR str
, INT count
,
1123 INT maxExt
, LPINT lpnFit
,
1124 LPINT alpDx
, LPSIZE size
)
1132 NULL
== (walpDx
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(INT
))))
1135 p
= FONT_mbtowc(str
, count
, &wlen
);
1136 ret
= GetTextExtentExPointW( hdc
, p
, wlen
, maxExt
, lpnFit
, walpDx
, size
);
1139 INT n
= lpnFit
? *lpnFit
: wlen
;
1141 for(i
= 0, j
= 0; i
< n
; i
++, j
++)
1143 alpDx
[j
] = walpDx
[i
];
1144 if (IsDBCSLeadByte(str
[j
])) alpDx
[++j
] = walpDx
[i
];
1147 if (lpnFit
) *lpnFit
= WideCharToMultiByte(CP_ACP
,0,p
,*lpnFit
,NULL
,0,NULL
,NULL
);
1148 HeapFree( GetProcessHeap(), 0, p
);
1149 HeapFree( GetProcessHeap(), 0, walpDx
);
1154 /***********************************************************************
1155 * GetTextExtentExPointW (GDI32.@)
1157 * Return the size of the string as it would be if it was output properly by
1160 * This should include
1161 * - Intercharacter spacing
1162 * - justification spacing (not yet done)
1163 * - kerning? see below
1165 * Kerning. Since kerning would be carried out by the rendering code it should
1166 * be done by the driver. However they don't support it yet. Also I am not
1167 * yet persuaded that (certainly under Win95) any kerning is actually done.
1169 * str: According to MSDN this should be null-terminated. That is not true; a
1170 * null will not terminate it early.
1171 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1172 * than count. I have seen it be either the size of the full string or
1173 * 1 less than the size of the full string. I have not seen it bear any
1174 * resemblance to the portion that would fit.
1175 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1176 * trailing intercharacter spacing and any trailing justification.
1179 * Currently we do this by measuring each character etc. We should do it by
1180 * passing the request to the driver, perhaps by extending the
1181 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1182 * thinking about kerning issues and rounding issues in the justification.
1185 BOOL WINAPI
GetTextExtentExPointW( HDC hdc
, LPCWSTR str
, INT count
,
1186 INT maxExt
, LPINT lpnFit
,
1187 LPINT alpDx
, LPSIZE size
)
1194 TRACE("(%p, %s, %d)\n",hdc
,debugstr_wn(str
,count
),maxExt
);
1196 dc
= DC_GetDCPtr(hdc
);
1200 /* If we need to calculate nFit, then we need the partial extents even if
1201 the user hasn't provided us with an array. */
1204 dxs
= alpDx
? alpDx
: HeapAlloc(GetProcessHeap(), 0, count
* sizeof alpDx
[0]);
1207 GDI_ReleaseObj(hdc
);
1208 SetLastError(ERROR_OUTOFMEMORY
);
1216 ret
= WineEngGetTextExtentExPoint(dc
->gdiFont
, str
, count
,
1217 0, NULL
, dxs
, size
);
1218 else if (dc
->funcs
->pGetTextExtentExPoint
)
1219 ret
= dc
->funcs
->pGetTextExtentExPoint(dc
->physDev
, str
, count
,
1220 0, NULL
, dxs
, size
);
1222 /* Perform device size to world size transformations. */
1225 INT extra
= dc
->charExtra
, breakRem
= dc
->breakRem
;
1230 for (i
= 0; i
< count
; ++i
)
1232 dxs
[i
] = abs(INTERNAL_XDSTOWS(dc
, dxs
[i
]));
1233 dxs
[i
] += (i
+1) * extra
+ breakRem
;
1234 if (dxs
[i
] <= maxExt
)
1238 size
->cx
= abs(INTERNAL_XDSTOWS(dc
, size
->cx
));
1239 size
->cy
= abs(INTERNAL_YDSTOWS(dc
, size
->cy
));
1240 size
->cx
+= count
* extra
+ breakRem
;
1247 HeapFree(GetProcessHeap(), 0, dxs
);
1249 GDI_ReleaseObj( hdc
);
1251 TRACE("returning %d %ld x %ld\n",nFit
,size
->cx
,size
->cy
);
1255 /***********************************************************************
1256 * GetTextMetricsA (GDI32.@)
1258 BOOL WINAPI
GetTextMetricsA( HDC hdc
, TEXTMETRICA
*metrics
)
1262 if (!GetTextMetricsW( hdc
, &tm32
)) return FALSE
;
1263 FONT_TextMetricWToA( &tm32
, metrics
);
1267 /***********************************************************************
1268 * GetTextMetricsW (GDI32.@)
1270 BOOL WINAPI
GetTextMetricsW( HDC hdc
, TEXTMETRICW
*metrics
)
1273 DC
* dc
= DC_GetDCPtr( hdc
);
1274 if (!dc
) return FALSE
;
1277 ret
= WineEngGetTextMetrics(dc
->gdiFont
, metrics
);
1278 else if (dc
->funcs
->pGetTextMetrics
)
1279 ret
= dc
->funcs
->pGetTextMetrics( dc
->physDev
, metrics
);
1283 /* device layer returns values in device units
1284 * therefore we have to convert them to logical */
1286 #define WDPTOLP(x) ((x<0)? \
1287 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1288 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1289 #define HDPTOLP(y) ((y<0)? \
1290 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1291 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1293 metrics
->tmHeight
= HDPTOLP(metrics
->tmHeight
);
1294 metrics
->tmAscent
= HDPTOLP(metrics
->tmAscent
);
1295 metrics
->tmDescent
= HDPTOLP(metrics
->tmDescent
);
1296 metrics
->tmInternalLeading
= HDPTOLP(metrics
->tmInternalLeading
);
1297 metrics
->tmExternalLeading
= HDPTOLP(metrics
->tmExternalLeading
);
1298 metrics
->tmAveCharWidth
= WDPTOLP(metrics
->tmAveCharWidth
);
1299 metrics
->tmMaxCharWidth
= WDPTOLP(metrics
->tmMaxCharWidth
);
1300 metrics
->tmOverhang
= WDPTOLP(metrics
->tmOverhang
);
1304 TRACE("text metrics:\n"
1305 " Weight = %03li\t FirstChar = %i\t AveCharWidth = %li\n"
1306 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %li\n"
1307 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %li\n"
1308 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1309 " PitchAndFamily = %02x\n"
1310 " --------------------\n"
1311 " InternalLeading = %li\n"
1315 metrics
->tmWeight
, metrics
->tmFirstChar
, metrics
->tmAveCharWidth
,
1316 metrics
->tmItalic
, metrics
->tmLastChar
, metrics
->tmMaxCharWidth
,
1317 metrics
->tmUnderlined
, metrics
->tmDefaultChar
, metrics
->tmOverhang
,
1318 metrics
->tmStruckOut
, metrics
->tmBreakChar
, metrics
->tmCharSet
,
1319 metrics
->tmPitchAndFamily
,
1320 metrics
->tmInternalLeading
,
1323 metrics
->tmHeight
);
1325 GDI_ReleaseObj( hdc
);
1330 /***********************************************************************
1331 * GetOutlineTextMetrics [GDI.308] Gets metrics for TrueType fonts.
1334 * lpOTM should be LPOUTLINETEXTMETRIC
1337 * Success: Non-zero or size of required buffer
1340 UINT16 WINAPI
GetOutlineTextMetrics16(
1341 HDC16 hdc
, /* [in] Handle of device context */
1342 UINT16 cbData
, /* [in] Size of metric data array */
1343 LPOUTLINETEXTMETRIC16 lpOTM
) /* [out] Address of metric data array */
1345 FIXME("(%04x,%04x,%p): stub\n", hdc
,cbData
,lpOTM
);
1350 /***********************************************************************
1351 * GetOutlineTextMetricsA (GDI32.@)
1352 * Gets metrics for TrueType fonts.
1355 * If the supplied buffer isn't big enough Windows partially fills it up to
1356 * its given length and returns that length.
1359 * Success: Non-zero or size of required buffer
1362 UINT WINAPI
GetOutlineTextMetricsA(
1363 HDC hdc
, /* [in] Handle of device context */
1364 UINT cbData
, /* [in] Size of metric data array */
1365 LPOUTLINETEXTMETRICA lpOTM
) /* [out] Address of metric data array */
1367 char buf
[512], *ptr
;
1369 OUTLINETEXTMETRICW
*lpOTMW
= (OUTLINETEXTMETRICW
*)buf
;
1370 OUTLINETEXTMETRICA
*output
= lpOTM
;
1373 if((ret
= GetOutlineTextMetricsW(hdc
, 0, NULL
)) == 0)
1375 if(ret
> sizeof(buf
))
1376 lpOTMW
= HeapAlloc(GetProcessHeap(), 0, ret
);
1377 GetOutlineTextMetricsW(hdc
, ret
, lpOTMW
);
1379 needed
= sizeof(OUTLINETEXTMETRICA
);
1380 if(lpOTMW
->otmpFamilyName
)
1381 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1382 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFamilyName
), -1,
1383 NULL
, 0, NULL
, NULL
);
1384 if(lpOTMW
->otmpFaceName
)
1385 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1386 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFaceName
), -1,
1387 NULL
, 0, NULL
, NULL
);
1388 if(lpOTMW
->otmpStyleName
)
1389 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1390 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpStyleName
), -1,
1391 NULL
, 0, NULL
, NULL
);
1392 if(lpOTMW
->otmpFullName
)
1393 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1394 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFullName
), -1,
1395 NULL
, 0, NULL
, NULL
);
1402 TRACE("needed = %d\n", needed
);
1404 /* Since the supplied buffer isn't big enough, we'll alloc one
1405 that is and memcpy the first cbData bytes into the lpOTM at
1407 output
= HeapAlloc(GetProcessHeap(), 0, needed
);
1409 ret
= output
->otmSize
= min(needed
, cbData
);
1410 FONT_TextMetricWToA( &lpOTMW
->otmTextMetrics
, &output
->otmTextMetrics
);
1411 output
->otmFiller
= 0;
1412 output
->otmPanoseNumber
= lpOTMW
->otmPanoseNumber
;
1413 output
->otmfsSelection
= lpOTMW
->otmfsSelection
;
1414 output
->otmfsType
= lpOTMW
->otmfsType
;
1415 output
->otmsCharSlopeRise
= lpOTMW
->otmsCharSlopeRise
;
1416 output
->otmsCharSlopeRun
= lpOTMW
->otmsCharSlopeRun
;
1417 output
->otmItalicAngle
= lpOTMW
->otmItalicAngle
;
1418 output
->otmEMSquare
= lpOTMW
->otmEMSquare
;
1419 output
->otmAscent
= lpOTMW
->otmAscent
;
1420 output
->otmDescent
= lpOTMW
->otmDescent
;
1421 output
->otmLineGap
= lpOTMW
->otmLineGap
;
1422 output
->otmsCapEmHeight
= lpOTMW
->otmsCapEmHeight
;
1423 output
->otmsXHeight
= lpOTMW
->otmsXHeight
;
1424 output
->otmrcFontBox
= lpOTMW
->otmrcFontBox
;
1425 output
->otmMacAscent
= lpOTMW
->otmMacAscent
;
1426 output
->otmMacDescent
= lpOTMW
->otmMacDescent
;
1427 output
->otmMacLineGap
= lpOTMW
->otmMacLineGap
;
1428 output
->otmusMinimumPPEM
= lpOTMW
->otmusMinimumPPEM
;
1429 output
->otmptSubscriptSize
= lpOTMW
->otmptSubscriptSize
;
1430 output
->otmptSubscriptOffset
= lpOTMW
->otmptSubscriptOffset
;
1431 output
->otmptSuperscriptSize
= lpOTMW
->otmptSuperscriptSize
;
1432 output
->otmptSuperscriptOffset
= lpOTMW
->otmptSuperscriptOffset
;
1433 output
->otmsStrikeoutSize
= lpOTMW
->otmsStrikeoutSize
;
1434 output
->otmsStrikeoutPosition
= lpOTMW
->otmsStrikeoutPosition
;
1435 output
->otmsUnderscoreSize
= lpOTMW
->otmsUnderscoreSize
;
1436 output
->otmsUnderscorePosition
= lpOTMW
->otmsUnderscorePosition
;
1439 ptr
= (char*)(output
+ 1);
1440 left
= needed
- sizeof(*output
);
1442 if(lpOTMW
->otmpFamilyName
) {
1443 output
->otmpFamilyName
= (LPSTR
)(ptr
- (char*)output
);
1444 len
= WideCharToMultiByte(CP_ACP
, 0,
1445 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFamilyName
), -1,
1446 ptr
, left
, NULL
, NULL
);
1450 output
->otmpFamilyName
= 0;
1452 if(lpOTMW
->otmpFaceName
) {
1453 output
->otmpFaceName
= (LPSTR
)(ptr
- (char*)output
);
1454 len
= WideCharToMultiByte(CP_ACP
, 0,
1455 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFaceName
), -1,
1456 ptr
, left
, NULL
, NULL
);
1460 output
->otmpFaceName
= 0;
1462 if(lpOTMW
->otmpStyleName
) {
1463 output
->otmpStyleName
= (LPSTR
)(ptr
- (char*)output
);
1464 len
= WideCharToMultiByte(CP_ACP
, 0,
1465 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpStyleName
), -1,
1466 ptr
, left
, NULL
, NULL
);
1470 output
->otmpStyleName
= 0;
1472 if(lpOTMW
->otmpFullName
) {
1473 output
->otmpFullName
= (LPSTR
)(ptr
- (char*)output
);
1474 len
= WideCharToMultiByte(CP_ACP
, 0,
1475 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFullName
), -1,
1476 ptr
, left
, NULL
, NULL
);
1479 output
->otmpFullName
= 0;
1483 if(output
!= lpOTM
) {
1484 memcpy(lpOTM
, output
, cbData
);
1485 HeapFree(GetProcessHeap(), 0, output
);
1489 if(lpOTMW
!= (OUTLINETEXTMETRICW
*)buf
)
1490 HeapFree(GetProcessHeap(), 0, lpOTMW
);
1496 /***********************************************************************
1497 * GetOutlineTextMetricsW [GDI32.@]
1499 UINT WINAPI
GetOutlineTextMetricsW(
1500 HDC hdc
, /* [in] Handle of device context */
1501 UINT cbData
, /* [in] Size of metric data array */
1502 LPOUTLINETEXTMETRICW lpOTM
) /* [out] Address of metric data array */
1504 DC
*dc
= DC_GetDCPtr( hdc
);
1505 OUTLINETEXTMETRICW
*output
= lpOTM
;
1508 TRACE("(%p,%d,%p)\n", hdc
, cbData
, lpOTM
);
1512 ret
= WineEngGetOutlineTextMetrics(dc
->gdiFont
, cbData
, output
);
1515 output
= HeapAlloc(GetProcessHeap(), 0, ret
);
1516 WineEngGetOutlineTextMetrics(dc
->gdiFont
, ret
, output
);
1519 #define WDPTOLP(x) ((x<0)? \
1520 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1521 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1522 #define HDPTOLP(y) ((y<0)? \
1523 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1524 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1526 output
->otmTextMetrics
.tmHeight
= HDPTOLP(output
->otmTextMetrics
.tmHeight
);
1527 output
->otmTextMetrics
.tmAscent
= HDPTOLP(output
->otmTextMetrics
.tmAscent
);
1528 output
->otmTextMetrics
.tmDescent
= HDPTOLP(output
->otmTextMetrics
.tmDescent
);
1529 output
->otmTextMetrics
.tmInternalLeading
= HDPTOLP(output
->otmTextMetrics
.tmInternalLeading
);
1530 output
->otmTextMetrics
.tmExternalLeading
= HDPTOLP(output
->otmTextMetrics
.tmExternalLeading
);
1531 output
->otmTextMetrics
.tmAveCharWidth
= WDPTOLP(output
->otmTextMetrics
.tmAveCharWidth
);
1532 output
->otmTextMetrics
.tmMaxCharWidth
= WDPTOLP(output
->otmTextMetrics
.tmMaxCharWidth
);
1533 output
->otmTextMetrics
.tmOverhang
= WDPTOLP(output
->otmTextMetrics
.tmOverhang
);
1534 output
->otmAscent
= HDPTOLP(output
->otmAscent
);
1535 output
->otmDescent
= HDPTOLP(output
->otmDescent
);
1536 output
->otmLineGap
= HDPTOLP(output
->otmLineGap
);
1537 output
->otmsCapEmHeight
= HDPTOLP(output
->otmsCapEmHeight
);
1538 output
->otmsXHeight
= HDPTOLP(output
->otmsXHeight
);
1539 output
->otmrcFontBox
.top
= HDPTOLP(output
->otmrcFontBox
.top
);
1540 output
->otmrcFontBox
.bottom
= HDPTOLP(output
->otmrcFontBox
.bottom
);
1541 output
->otmrcFontBox
.left
= WDPTOLP(output
->otmrcFontBox
.left
);
1542 output
->otmrcFontBox
.right
= WDPTOLP(output
->otmrcFontBox
.right
);
1543 output
->otmMacAscent
= HDPTOLP(output
->otmMacAscent
);
1544 output
->otmMacDescent
= HDPTOLP(output
->otmMacDescent
);
1545 output
->otmMacLineGap
= HDPTOLP(output
->otmMacLineGap
);
1546 output
->otmptSubscriptSize
.x
= WDPTOLP(output
->otmptSubscriptSize
.x
);
1547 output
->otmptSubscriptSize
.y
= HDPTOLP(output
->otmptSubscriptSize
.y
);
1548 output
->otmptSubscriptOffset
.x
= WDPTOLP(output
->otmptSubscriptOffset
.x
);
1549 output
->otmptSubscriptOffset
.y
= HDPTOLP(output
->otmptSubscriptOffset
.y
);
1550 output
->otmptSuperscriptSize
.x
= WDPTOLP(output
->otmptSuperscriptSize
.x
);
1551 output
->otmptSuperscriptSize
.y
= HDPTOLP(output
->otmptSuperscriptSize
.y
);
1552 output
->otmptSuperscriptOffset
.x
= WDPTOLP(output
->otmptSuperscriptOffset
.x
);
1553 output
->otmptSuperscriptOffset
.y
= HDPTOLP(output
->otmptSuperscriptOffset
.y
);
1554 output
->otmsStrikeoutSize
= HDPTOLP(output
->otmsStrikeoutSize
);
1555 output
->otmsStrikeoutPosition
= HDPTOLP(output
->otmsStrikeoutPosition
);
1556 output
->otmsUnderscoreSize
= HDPTOLP(output
->otmsUnderscoreSize
);
1557 output
->otmsUnderscorePosition
= HDPTOLP(output
->otmsUnderscorePosition
);
1560 if(output
!= lpOTM
) {
1561 memcpy(lpOTM
, output
, cbData
);
1562 HeapFree(GetProcessHeap(), 0, output
);
1568 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1569 but really this should just be a return 0. */
1571 ret
= sizeof(*lpOTM
);
1576 memset(lpOTM
, 0, ret
);
1577 lpOTM
->otmSize
= sizeof(*lpOTM
);
1578 GetTextMetricsW(hdc
, &lpOTM
->otmTextMetrics
);
1580 Further fill of the structure not implemented,
1581 Needs real values for the structure members
1586 GDI_ReleaseObj(hdc
);
1591 /***********************************************************************
1592 * GetCharWidthW (GDI32.@)
1593 * GetCharWidth32W (GDI32.@)
1595 BOOL WINAPI
GetCharWidth32W( HDC hdc
, UINT firstChar
, UINT lastChar
,
1600 DC
* dc
= DC_GetDCPtr( hdc
);
1601 if (!dc
) return FALSE
;
1604 ret
= WineEngGetCharWidth( dc
->gdiFont
, firstChar
, lastChar
, buffer
);
1605 else if (dc
->funcs
->pGetCharWidth
)
1606 ret
= dc
->funcs
->pGetCharWidth( dc
->physDev
, firstChar
, lastChar
, buffer
);
1610 /* convert device units to logical */
1611 for( i
= firstChar
; i
<= lastChar
; i
++, buffer
++ )
1612 *buffer
= INTERNAL_XDSTOWS(dc
, *buffer
);
1615 GDI_ReleaseObj( hdc
);
1620 /***********************************************************************
1621 * GetCharWidthA (GDI32.@)
1622 * GetCharWidth32A (GDI32.@)
1624 BOOL WINAPI
GetCharWidth32A( HDC hdc
, UINT firstChar
, UINT lastChar
,
1627 INT i
, wlen
, count
= (INT
)(lastChar
- firstChar
+ 1);
1632 if(count
<= 0) return FALSE
;
1634 str
= HeapAlloc(GetProcessHeap(), 0, count
);
1635 for(i
= 0; i
< count
; i
++)
1636 str
[i
] = (BYTE
)(firstChar
+ i
);
1638 wstr
= FONT_mbtowc(str
, count
, &wlen
);
1640 for(i
= 0; i
< wlen
; i
++)
1642 if(!GetCharWidth32W(hdc
, wstr
[i
], wstr
[i
], buffer
))
1650 HeapFree(GetProcessHeap(), 0, str
);
1651 HeapFree(GetProcessHeap(), 0, wstr
);
1657 /***********************************************************************
1658 * ExtTextOutA (GDI32.@)
1662 BOOL WINAPI
ExtTextOutA( HDC hdc
, INT x
, INT y
, UINT flags
,
1663 const RECT
*lprect
, LPCSTR str
, UINT count
, const INT
*lpDx
)
1670 if (flags
& ETO_GLYPH_INDEX
)
1671 return ExtTextOutW( hdc
, x
, y
, flags
, lprect
, (LPCWSTR
)str
, count
, lpDx
);
1673 p
= FONT_mbtowc(str
, count
, &wlen
);
1676 unsigned int i
= 0, j
= 0;
1678 lpDxW
= HeapAlloc( GetProcessHeap(), 0, wlen
*sizeof(INT
));
1680 if(IsDBCSLeadByte(str
[i
])) {
1681 lpDxW
[j
++] = lpDx
[i
] + lpDx
[i
+1];
1684 lpDxW
[j
++] = lpDx
[i
];
1690 ret
= ExtTextOutW( hdc
, x
, y
, flags
, lprect
, p
, wlen
, lpDxW
);
1692 HeapFree( GetProcessHeap(), 0, p
);
1693 HeapFree( GetProcessHeap(), 0, lpDxW
);
1698 /***********************************************************************
1699 * ExtTextOutW (GDI32.@)
1701 * Draws text using the currently selected font, background color, and text color.
1705 * x,y [I] coordinates of string
1707 * ETO_GRAYED - undocumented on MSDN
1708 * ETO_OPAQUE - use background color for fill the rectangle
1709 * ETO_CLIPPED - clipping text to the rectangle
1710 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1711 * than encoded characters. Implies ETO_IGNORELANGUAGE
1712 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1713 * Affects BiDi ordering
1714 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1715 * ETO_PDY - unimplemented
1716 * ETO_NUMERICSLATIN - unimplemented always assumed -
1717 * do not translate numbers into locale representations
1718 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1719 * lprect [I] dimensions for clipping or/and opaquing
1720 * str [I] text string
1721 * count [I] number of symbols in string
1722 * lpDx [I] optional parameter with distance between drawing characters
1728 BOOL WINAPI
ExtTextOutW( HDC hdc
, INT x
, INT y
, UINT flags
,
1729 const RECT
*lprect
, LPCWSTR str
, UINT count
, const INT
*lpDx
)
1732 LPWSTR reordered_str
= (LPWSTR
)str
;
1733 WORD
*glyphs
= NULL
;
1734 UINT align
= GetTextAlign( hdc
);
1738 double cosEsc
, sinEsc
;
1739 INT
*deltas
= NULL
, char_extra
;
1742 BOOL done_extents
= FALSE
;
1743 INT width
, xwidth
= 0, ywidth
= 0;
1745 DC
* dc
= DC_GetDCUpdate( hdc
);
1747 if (!dc
) return FALSE
;
1749 if (flags
& (ETO_NUMERICSLOCAL
| ETO_NUMERICSLATIN
| ETO_PDY
))
1750 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY unimplemented\n");
1752 if (!dc
->funcs
->pExtTextOut
&& !PATH_IsPathOpen(dc
->path
))
1754 GDI_ReleaseObj( hdc
);
1758 type
= GetObjectType(hdc
);
1759 if(type
== OBJ_METADC
|| type
== OBJ_ENHMETADC
)
1761 ret
= dc
->funcs
->pExtTextOut(dc
->physDev
, x
, y
, flags
, lprect
, str
, count
, lpDx
);
1762 GDI_ReleaseObj( hdc
);
1767 flags
&= ~ETO_CLIPPED
;
1769 if( !(flags
& (ETO_GLYPH_INDEX
| ETO_IGNORELANGUAGE
)) && BidiAvail
&& count
> 0 )
1771 reordered_str
= HeapAlloc(GetProcessHeap(), 0, count
*sizeof(WCHAR
));
1773 BIDI_Reorder( str
, count
, GCP_REORDER
,
1774 ((flags
&ETO_RTLREADING
)!=0 || (GetTextAlign(hdc
)&TA_RTLREADING
)!=0)?
1775 WINE_GCPW_FORCE_RTL
:WINE_GCPW_FORCE_LTR
,
1776 reordered_str
, count
, NULL
);
1778 flags
|= ETO_IGNORELANGUAGE
;
1781 TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc
, x
, y
, flags
,
1782 lprect
, debugstr_wn(str
, count
), count
, lpDx
);
1784 if(flags
& ETO_GLYPH_INDEX
)
1785 glyphs
= reordered_str
;
1788 TRACE("rect: %ld,%ld - %ld,%ld\n", lprect
->left
, lprect
->top
, lprect
->right
,
1790 TRACE("align = %x bkmode = %x mapmode = %x\n", align
, GetBkMode(hdc
), GetMapMode(hdc
));
1792 if(align
& TA_UPDATECP
)
1794 GetCurrentPositionEx( hdc
, &pt
);
1799 GetTextMetricsW(hdc
, &tm
);
1800 GetObjectW(GetCurrentObject(hdc
, OBJ_FONT
), sizeof(lf
), &lf
);
1802 if(!(tm
.tmPitchAndFamily
& TMPF_VECTOR
)) /* Non-scalable fonts shouldn't be rotated */
1803 lf
.lfEscapement
= 0;
1805 if(lf
.lfEscapement
!= 0)
1807 cosEsc
= cos(lf
.lfEscapement
* M_PI
/ 1800);
1808 sinEsc
= sin(lf
.lfEscapement
* M_PI
/ 1800);
1816 if(flags
& (ETO_CLIPPED
| ETO_OPAQUE
))
1820 if(flags
& ETO_GLYPH_INDEX
)
1821 GetTextExtentPointI(hdc
, glyphs
, count
, &sz
);
1823 GetTextExtentPointW(hdc
, reordered_str
, count
, &sz
);
1825 done_extents
= TRUE
;
1828 rc
.right
= x
+ sz
.cx
;
1829 rc
.bottom
= y
+ sz
.cy
;
1836 LPtoDP(hdc
, (POINT
*)&rc
, 2);
1838 if(rc
.left
> rc
.right
) {INT tmp
= rc
.left
; rc
.left
= rc
.right
; rc
.right
= tmp
;}
1839 if(rc
.top
> rc
.bottom
) {INT tmp
= rc
.top
; rc
.top
= rc
.bottom
; rc
.bottom
= tmp
;}
1842 if ((flags
& ETO_OPAQUE
) && !PATH_IsPathOpen(dc
->path
))
1843 dc
->funcs
->pExtTextOut(dc
->physDev
, 0, 0, ETO_OPAQUE
, &rc
, NULL
, 0, NULL
);
1853 LPtoDP(hdc
, &pt
, 1);
1857 char_extra
= GetTextCharacterExtra(hdc
);
1859 if(char_extra
|| dc
->breakExtra
|| lpDx
)
1863 deltas
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(INT
));
1864 for(i
= 0; i
< count
; i
++)
1866 if(lpDx
&& (flags
& ETO_PDY
))
1867 deltas
[i
] = lpDx
[i
*2] + char_extra
;
1869 deltas
[i
] = lpDx
[i
] + char_extra
;
1872 if(flags
& ETO_GLYPH_INDEX
)
1873 GetTextExtentPointI(hdc
, glyphs
+ i
, 1, &tmpsz
);
1875 GetTextExtentPointW(hdc
, reordered_str
+ i
, 1, &tmpsz
);
1877 deltas
[i
] = tmpsz
.cx
;
1880 if (!(flags
& ETO_GLYPH_INDEX
) && dc
->breakExtra
&& reordered_str
[i
] == tm
.tmBreakChar
)
1882 deltas
[i
] = deltas
[i
] + dc
->breakExtra
;
1884 deltas
[i
] = INTERNAL_XWSTODS(dc
, deltas
[i
]);
1892 if(flags
& ETO_GLYPH_INDEX
)
1893 GetTextExtentPointI(hdc
, glyphs
, count
, &sz
);
1895 GetTextExtentPointW(hdc
, reordered_str
, count
, &sz
);
1896 done_extents
= TRUE
;
1898 width
= INTERNAL_XWSTODS(dc
, sz
.cx
);
1900 xwidth
= width
* cosEsc
;
1901 ywidth
= width
* sinEsc
;
1903 tm
.tmAscent
= abs(INTERNAL_YWSTODS(dc
, tm
.tmAscent
));
1904 tm
.tmDescent
= abs(INTERNAL_YWSTODS(dc
, tm
.tmDescent
));
1905 switch( align
& (TA_LEFT
| TA_RIGHT
| TA_CENTER
) )
1908 if (align
& TA_UPDATECP
)
1912 DPtoLP(hdc
, &pt
, 1);
1913 MoveToEx(hdc
, pt
.x
, pt
.y
, NULL
);
1925 if (align
& TA_UPDATECP
)
1929 DPtoLP(hdc
, &pt
, 1);
1930 MoveToEx(hdc
, pt
.x
, pt
.y
, NULL
);
1935 switch( align
& (TA_TOP
| TA_BOTTOM
| TA_BASELINE
) )
1938 y
+= tm
.tmAscent
* cosEsc
;
1939 x
+= tm
.tmAscent
* sinEsc
;
1943 y
-= tm
.tmDescent
* cosEsc
;
1944 x
-= tm
.tmDescent
* sinEsc
;
1951 if (GetBkMode(hdc
) != TRANSPARENT
&& !PATH_IsPathOpen(dc
->path
))
1953 if(!((flags
& ETO_CLIPPED
) && (flags
& ETO_OPAQUE
)))
1955 if(!(flags
& ETO_OPAQUE
) || x
< rc
.left
|| x
+ width
>= rc
.right
||
1956 y
- tm
.tmAscent
< rc
.top
|| y
+ tm
.tmDescent
>= rc
.bottom
)
1960 rc
.right
= x
+ width
;
1961 rc
.top
= y
- tm
.tmAscent
;
1962 rc
.bottom
= y
+ tm
.tmDescent
;
1963 dc
->funcs
->pExtTextOut(dc
->physDev
, 0, 0, ETO_OPAQUE
, &rc
, NULL
, 0, NULL
);
1968 if(FontIsLinked(hdc
) && !(flags
& ETO_GLYPH_INDEX
))
1970 HFONT orig_font
= dc
->hFont
, cur_font
;
1972 INT span
= 0, *offsets
= NULL
, i
;
1974 glyphs
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(WORD
));
1975 for(i
= 0; i
< count
; i
++)
1977 WineEngGetLinkedHFont(dc
, reordered_str
[i
], &cur_font
, &glyph
);
1978 if(cur_font
!= dc
->hFont
)
1983 offsets
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(*deltas
));
1988 for(j
= 1; j
< count
; j
++)
1990 GetTextExtentPointW(hdc
, reordered_str
+ j
- 1, 1, &tmpsz
);
1991 offsets
[j
] = offsets
[j
-1] + INTERNAL_XWSTODS(dc
, tmpsz
.cx
);
1996 for(j
= 1; j
< count
; j
++)
1997 offsets
[j
] = offsets
[j
-1] + deltas
[j
];
2002 if (PATH_IsPathOpen(dc
->path
))
2003 ret
= PATH_ExtTextOut(dc
, x
+ offsets
[i
- span
] * cosEsc
, y
- offsets
[i
- span
] * sinEsc
,
2004 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
,
2005 glyphs
, span
, deltas
? deltas
+ i
- span
: NULL
);
2007 dc
->funcs
->pExtTextOut(dc
->physDev
, x
+ offsets
[i
- span
] * cosEsc
, y
- offsets
[i
- span
] * sinEsc
,
2008 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
,
2009 glyphs
, span
, deltas
? deltas
+ i
- span
: NULL
);
2012 SelectObject(hdc
, cur_font
);
2014 glyphs
[span
++] = glyph
;
2018 if (PATH_IsPathOpen(dc
->path
))
2019 ret
= PATH_ExtTextOut(dc
, x
+ (offsets
? offsets
[count
- span
] * cosEsc
: 0),
2020 y
- (offsets
? offsets
[count
- span
] * sinEsc
: 0),
2021 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
,
2022 glyphs
, span
, deltas
? deltas
+ count
- span
: NULL
);
2024 ret
= dc
->funcs
->pExtTextOut(dc
->physDev
, x
+ (offsets
? offsets
[count
- span
] * cosEsc
: 0),
2025 y
- (offsets
? offsets
[count
- span
] * sinEsc
: 0),
2026 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
,
2027 glyphs
, span
, deltas
? deltas
+ count
- span
: NULL
);
2028 SelectObject(hdc
, orig_font
);
2029 HeapFree(GetProcessHeap(), 0, offsets
);
2035 if(!(flags
& ETO_GLYPH_INDEX
) && dc
->gdiFont
)
2037 glyphs
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(WORD
));
2038 GetGlyphIndicesW(hdc
, reordered_str
, count
, glyphs
, 0);
2039 flags
|= ETO_GLYPH_INDEX
;
2042 if (PATH_IsPathOpen(dc
->path
))
2043 ret
= PATH_ExtTextOut(dc
, x
, y
, (flags
& ~ETO_OPAQUE
), &rc
,
2044 glyphs
? glyphs
: reordered_str
, count
, deltas
);
2046 ret
= dc
->funcs
->pExtTextOut(dc
->physDev
, x
, y
, (flags
& ~ETO_OPAQUE
), &rc
,
2047 glyphs
? glyphs
: reordered_str
, count
, deltas
);
2051 HeapFree(GetProcessHeap(), 0, deltas
);
2052 if(glyphs
!= reordered_str
)
2053 HeapFree(GetProcessHeap(), 0, glyphs
);
2054 if(reordered_str
!= str
)
2055 HeapFree(GetProcessHeap(), 0, reordered_str
);
2057 GDI_ReleaseObj( hdc
);
2059 if (ret
&& (lf
.lfUnderline
|| lf
.lfStrikeOut
))
2061 int underlinePos
, strikeoutPos
;
2062 int underlineWidth
, strikeoutWidth
;
2063 UINT size
= GetOutlineTextMetricsW(hdc
, 0, NULL
);
2064 OUTLINETEXTMETRICW
* otm
= NULL
;
2069 underlineWidth
= tm
.tmAscent
/ 20 + 1;
2070 strikeoutPos
= tm
.tmAscent
/ 2;
2071 strikeoutWidth
= underlineWidth
;
2075 otm
= HeapAlloc(GetProcessHeap(), 0, size
);
2076 GetOutlineTextMetricsW(hdc
, size
, otm
);
2077 underlinePos
= otm
->otmsUnderscorePosition
;
2078 underlineWidth
= otm
->otmsUnderscoreSize
;
2079 strikeoutPos
= otm
->otmsStrikeoutPosition
;
2080 strikeoutWidth
= otm
->otmsStrikeoutSize
;
2081 HeapFree(GetProcessHeap(), 0, otm
);
2084 if (PATH_IsPathOpen(dc
->path
))
2088 HBRUSH hbrush
= CreateSolidBrush(GetTextColor(hdc
));
2090 hbrush
= SelectObject(hdc
, hbrush
);
2091 hpen
= SelectObject(hdc
, GetStockObject(NULL_PEN
));
2095 pts
[0].x
= x
- underlinePos
* sinEsc
;
2096 pts
[0].y
= y
- underlinePos
* cosEsc
;
2097 pts
[1].x
= x
+ xwidth
- underlinePos
* sinEsc
;
2098 pts
[1].y
= y
- ywidth
- underlinePos
* cosEsc
;
2099 pts
[2].x
= pts
[1].x
+ underlineWidth
* sinEsc
;
2100 pts
[2].y
= pts
[1].y
+ underlineWidth
* cosEsc
;
2101 pts
[3].x
= pts
[0].x
+ underlineWidth
* sinEsc
;
2102 pts
[3].y
= pts
[0].y
+ underlineWidth
* cosEsc
;
2103 pts
[4].x
= pts
[0].x
;
2104 pts
[4].y
= pts
[0].y
;
2105 DPtoLP(hdc
, pts
, 5);
2106 Polygon(hdc
, pts
, 5);
2111 pts
[0].x
= x
- strikeoutPos
* sinEsc
;
2112 pts
[0].y
= y
- strikeoutPos
* cosEsc
;
2113 pts
[1].x
= x
+ xwidth
- strikeoutPos
* sinEsc
;
2114 pts
[1].y
= y
- ywidth
- strikeoutPos
* cosEsc
;
2115 pts
[2].x
= pts
[1].x
+ strikeoutWidth
* sinEsc
;
2116 pts
[2].y
= pts
[1].y
+ strikeoutWidth
* cosEsc
;
2117 pts
[3].x
= pts
[0].x
+ strikeoutWidth
* sinEsc
;
2118 pts
[3].y
= pts
[0].y
+ strikeoutWidth
* cosEsc
;
2119 pts
[4].x
= pts
[0].x
;
2120 pts
[4].y
= pts
[0].y
;
2121 DPtoLP(hdc
, pts
, 5);
2122 Polygon(hdc
, pts
, 5);
2125 SelectObject(hdc
, hpen
);
2126 hbrush
= SelectObject(hdc
, hbrush
);
2127 DeleteObject(hbrush
);
2131 POINT pts
[2], oldpt
;
2136 hpen
= CreatePen(PS_SOLID
, underlineWidth
, GetTextColor(hdc
));
2137 hpen
= SelectObject(hdc
, hpen
);
2140 pts
[1].x
= x
+ xwidth
;
2141 pts
[1].y
= y
- ywidth
;
2142 DPtoLP(hdc
, pts
, 2);
2143 MoveToEx(hdc
, pts
[0].x
- underlinePos
* sinEsc
, pts
[0].y
- underlinePos
* cosEsc
, &oldpt
);
2144 LineTo(hdc
, pts
[1].x
- underlinePos
* sinEsc
, pts
[1].y
- underlinePos
* cosEsc
);
2145 MoveToEx(hdc
, oldpt
.x
, oldpt
.y
, NULL
);
2146 DeleteObject(SelectObject(hdc
, hpen
));
2151 hpen
= CreatePen(PS_SOLID
, strikeoutWidth
, GetTextColor(hdc
));
2152 hpen
= SelectObject(hdc
, hpen
);
2155 pts
[1].x
= x
+ xwidth
;
2156 pts
[1].y
= y
- ywidth
;
2157 DPtoLP(hdc
, pts
, 2);
2158 MoveToEx(hdc
, pts
[0].x
- strikeoutPos
* sinEsc
, pts
[0].y
- strikeoutPos
* cosEsc
, &oldpt
);
2159 LineTo(hdc
, pts
[1].x
- strikeoutPos
* sinEsc
, pts
[1].y
- strikeoutPos
* cosEsc
);
2160 MoveToEx(hdc
, oldpt
.x
, oldpt
.y
, NULL
);
2161 DeleteObject(SelectObject(hdc
, hpen
));
2170 /***********************************************************************
2171 * TextOutA (GDI32.@)
2173 BOOL WINAPI
TextOutA( HDC hdc
, INT x
, INT y
, LPCSTR str
, INT count
)
2175 return ExtTextOutA( hdc
, x
, y
, 0, NULL
, str
, count
, NULL
);
2179 /***********************************************************************
2180 * TextOutW (GDI32.@)
2182 BOOL WINAPI
TextOutW(HDC hdc
, INT x
, INT y
, LPCWSTR str
, INT count
)
2184 return ExtTextOutW( hdc
, x
, y
, 0, NULL
, str
, count
, NULL
);
2188 /***********************************************************************
2189 * PolyTextOutA (GDI32.@)
2193 BOOL WINAPI
PolyTextOutA ( HDC hdc
, /* [in] Handle to device context */
2194 PPOLYTEXTA pptxt
, /* [in] Array of strings */
2195 INT cStrings
) /* [in] Number of strings in array */
2197 for (; cStrings
>0; cStrings
--, pptxt
++)
2198 if (!ExtTextOutA( hdc
, pptxt
->x
, pptxt
->y
, pptxt
->uiFlags
, &pptxt
->rcl
, pptxt
->lpstr
, pptxt
->n
, pptxt
->pdx
))
2205 /***********************************************************************
2206 * PolyTextOutW (GDI32.@)
2208 * Draw several Strings
2214 BOOL WINAPI
PolyTextOutW ( HDC hdc
, /* [in] Handle to device context */
2215 PPOLYTEXTW pptxt
, /* [in] Array of strings */
2216 INT cStrings
) /* [in] Number of strings in array */
2218 for (; cStrings
>0; cStrings
--, pptxt
++)
2219 if (!ExtTextOutW( hdc
, pptxt
->x
, pptxt
->y
, pptxt
->uiFlags
, &pptxt
->rcl
, pptxt
->lpstr
, pptxt
->n
, pptxt
->pdx
))
2225 /* FIXME: all following APIs ******************************************/
2228 /***********************************************************************
2229 * SetMapperFlags (GDI32.@)
2231 DWORD WINAPI
SetMapperFlags( HDC hDC
, DWORD dwFlag
)
2233 DC
*dc
= DC_GetDCPtr( hDC
);
2236 if(dc
->funcs
->pSetMapperFlags
)
2238 ret
= dc
->funcs
->pSetMapperFlags( dc
->physDev
, dwFlag
);
2239 /* FIXME: ret is just a success flag, we should return a proper value */
2242 FIXME("(%p, 0x%08lx): stub - harmless\n", hDC
, dwFlag
);
2243 GDI_ReleaseObj( hDC
);
2247 /***********************************************************************
2248 * GetAspectRatioFilterEx (GDI.486)
2250 BOOL16 WINAPI
GetAspectRatioFilterEx16( HDC16 hdc
, LPSIZE16 pAspectRatio
)
2252 FIXME("(%04x, %p): -- Empty Stub !\n", hdc
, pAspectRatio
);
2256 /***********************************************************************
2257 * GetAspectRatioFilterEx (GDI32.@)
2259 BOOL WINAPI
GetAspectRatioFilterEx( HDC hdc
, LPSIZE pAspectRatio
)
2261 FIXME("(%p, %p): -- Empty Stub !\n", hdc
, pAspectRatio
);
2266 /***********************************************************************
2267 * GetCharABCWidthsA (GDI32.@)
2269 * See GetCharABCWidthsW.
2271 BOOL WINAPI
GetCharABCWidthsA(HDC hdc
, UINT firstChar
, UINT lastChar
,
2274 INT i
, wlen
, count
= (INT
)(lastChar
- firstChar
+ 1);
2279 if(count
<= 0) return FALSE
;
2281 str
= HeapAlloc(GetProcessHeap(), 0, count
);
2282 for(i
= 0; i
< count
; i
++)
2283 str
[i
] = (BYTE
)(firstChar
+ i
);
2285 wstr
= FONT_mbtowc(str
, count
, &wlen
);
2287 for(i
= 0; i
< wlen
; i
++)
2289 if(!GetCharABCWidthsW(hdc
, wstr
[i
], wstr
[i
], abc
))
2297 HeapFree(GetProcessHeap(), 0, str
);
2298 HeapFree(GetProcessHeap(), 0, wstr
);
2304 /******************************************************************************
2305 * GetCharABCWidthsW [GDI32.@]
2307 * Retrieves widths of characters in range.
2310 * hdc [I] Handle of device context
2311 * firstChar [I] First character in range to query
2312 * lastChar [I] Last character in range to query
2313 * abc [O] Address of character-width structure
2316 * Only works with TrueType fonts
2322 BOOL WINAPI
GetCharABCWidthsW( HDC hdc
, UINT firstChar
, UINT lastChar
,
2325 DC
*dc
= DC_GetDCPtr(hdc
);
2329 if (!dc
) return FALSE
;
2332 ret
= WineEngGetCharABCWidths( dc
->gdiFont
, firstChar
, lastChar
, abc
);
2338 /* convert device units to logical */
2339 for( i
= firstChar
; i
<= lastChar
; i
++, abc
++ ) {
2340 abc
->abcA
= INTERNAL_XDSTOWS(dc
, abc
->abcA
);
2341 abc
->abcB
= INTERNAL_XDSTOWS(dc
, abc
->abcB
);
2342 abc
->abcC
= INTERNAL_XDSTOWS(dc
, abc
->abcC
);
2347 GDI_ReleaseObj(hdc
);
2352 /******************************************************************************
2353 * GetCharABCWidthsI [GDI32.@]
2355 * Retrieves widths of characters in range.
2358 * hdc [I] Handle of device context
2359 * firstChar [I] First glyphs in range to query
2360 * count [I] Last glyphs in range to query
2361 * pgi [i] Array of glyphs to query
2362 * abc [O] Address of character-width structure
2365 * Only works with TrueType fonts
2371 BOOL WINAPI
GetCharABCWidthsI( HDC hdc
, UINT firstChar
, UINT count
,
2372 LPWORD pgi
, LPABC abc
)
2374 DC
*dc
= DC_GetDCPtr(hdc
);
2378 if (!dc
) return FALSE
;
2381 ret
= WineEngGetCharABCWidthsI( dc
->gdiFont
, firstChar
, count
, pgi
, abc
);
2387 /* convert device units to logical */
2388 for( i
= 0; i
< count
; i
++, abc
++ ) {
2389 abc
->abcA
= INTERNAL_XDSTOWS(dc
, abc
->abcA
);
2390 abc
->abcB
= INTERNAL_XDSTOWS(dc
, abc
->abcB
);
2391 abc
->abcC
= INTERNAL_XDSTOWS(dc
, abc
->abcC
);
2396 GDI_ReleaseObj(hdc
);
2401 /***********************************************************************
2402 * GetGlyphOutlineA (GDI32.@)
2404 DWORD WINAPI
GetGlyphOutlineA( HDC hdc
, UINT uChar
, UINT fuFormat
,
2405 LPGLYPHMETRICS lpgm
, DWORD cbBuffer
,
2406 LPVOID lpBuffer
, const MAT2
*lpmat2
)
2412 if(!(fuFormat
& GGO_GLYPH_INDEX
)) {
2415 if(uChar
> 0xff) { /* but, 2 bytes character only */
2417 mbchs
[0] = (uChar
& 0xff00) >> 8;
2418 mbchs
[1] = (uChar
& 0xff);
2421 mbchs
[0] = (uChar
& 0xff);
2423 p
= FONT_mbtowc(mbchs
, len
, NULL
);
2427 ret
= GetGlyphOutlineW(hdc
, c
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
,
2429 HeapFree(GetProcessHeap(), 0, p
);
2433 /***********************************************************************
2434 * GetGlyphOutlineW (GDI32.@)
2436 DWORD WINAPI
GetGlyphOutlineW( HDC hdc
, UINT uChar
, UINT fuFormat
,
2437 LPGLYPHMETRICS lpgm
, DWORD cbBuffer
,
2438 LPVOID lpBuffer
, const MAT2
*lpmat2
)
2440 DC
*dc
= DC_GetDCPtr(hdc
);
2443 TRACE("(%p, %04x, %04x, %p, %ld, %p, %p)\n",
2444 hdc
, uChar
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
, lpmat2
);
2446 if(!dc
) return GDI_ERROR
;
2449 ret
= WineEngGetGlyphOutline(dc
->gdiFont
, uChar
, fuFormat
, lpgm
,
2450 cbBuffer
, lpBuffer
, lpmat2
);
2454 GDI_ReleaseObj(hdc
);
2459 /***********************************************************************
2460 * CreateScalableFontResourceA (GDI32.@)
2462 BOOL WINAPI
CreateScalableFontResourceA( DWORD fHidden
,
2463 LPCSTR lpszResourceFile
,
2464 LPCSTR lpszFontFile
,
2465 LPCSTR lpszCurrentPath
)
2469 /* fHidden=1 - only visible for the calling app, read-only, not
2470 * enumbered with EnumFonts/EnumFontFamilies
2471 * lpszCurrentPath can be NULL
2473 FIXME("(%ld,%s,%s,%s): stub\n",
2474 fHidden
, debugstr_a(lpszResourceFile
), debugstr_a(lpszFontFile
),
2475 debugstr_a(lpszCurrentPath
) );
2477 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2478 if ((f
= CreateFileA(lpszResourceFile
, 0, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, 0)) != INVALID_HANDLE_VALUE
) {
2480 SetLastError(ERROR_FILE_EXISTS
);
2483 return FALSE
; /* create failed */
2486 /***********************************************************************
2487 * CreateScalableFontResourceW (GDI32.@)
2489 BOOL WINAPI
CreateScalableFontResourceW( DWORD fHidden
,
2490 LPCWSTR lpszResourceFile
,
2491 LPCWSTR lpszFontFile
,
2492 LPCWSTR lpszCurrentPath
)
2494 FIXME("(%ld,%p,%p,%p): stub\n",
2495 fHidden
, lpszResourceFile
, lpszFontFile
, lpszCurrentPath
);
2496 return FALSE
; /* create failed */
2499 /*************************************************************************
2500 * GetKerningPairsA (GDI32.@)
2502 DWORD WINAPI
GetKerningPairsA( HDC hDC
, DWORD cPairs
,
2503 LPKERNINGPAIR lpKerningPairs
)
2505 return GetKerningPairsW( hDC
, cPairs
, lpKerningPairs
);
2509 /*************************************************************************
2510 * GetKerningPairsW (GDI32.@)
2512 DWORD WINAPI
GetKerningPairsW( HDC hDC
, DWORD cPairs
,
2513 LPKERNINGPAIR lpKerningPairs
)
2516 FIXME("(%p,%ld,%p): almost empty stub!\n", hDC
, cPairs
, lpKerningPairs
);
2518 if(!lpKerningPairs
) /* return the number of kerning pairs */
2521 for (i
= 0; i
< cPairs
; i
++)
2522 lpKerningPairs
[i
].iKernAmount
= 0;
2526 /*************************************************************************
2527 * TranslateCharsetInfo [GDI32.@]
2529 * Fills a CHARSETINFO structure for a character set, code page, or
2530 * font. This allows making the correspondance between different labelings
2531 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2532 * of the same encoding.
2534 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2535 * only one codepage should be set in *lpSrc.
2538 * TRUE on success, FALSE on failure.
2541 BOOL WINAPI
TranslateCharsetInfo(
2542 LPDWORD lpSrc
, /* [in]
2543 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2544 if flags == TCI_SRCCHARSET: a character set value
2545 if flags == TCI_SRCCODEPAGE: a code page value
2547 LPCHARSETINFO lpCs
, /* [out] structure to receive charset information */
2548 DWORD flags
/* [in] determines interpretation of lpSrc */)
2552 case TCI_SRCFONTSIG
:
2553 while (!(*lpSrc
>>index
& 0x0001) && index
<MAXTCIINDEX
) index
++;
2555 case TCI_SRCCODEPAGE
:
2556 while ((UINT
) (lpSrc
) != FONT_tci
[index
].ciACP
&& index
< MAXTCIINDEX
) index
++;
2558 case TCI_SRCCHARSET
:
2559 while ((UINT
) (lpSrc
) != FONT_tci
[index
].ciCharset
&& index
< MAXTCIINDEX
) index
++;
2564 if (index
>= MAXTCIINDEX
|| FONT_tci
[index
].ciCharset
== DEFAULT_CHARSET
) return FALSE
;
2565 memcpy(lpCs
, &FONT_tci
[index
], sizeof(CHARSETINFO
));
2569 /*************************************************************************
2570 * GetFontLanguageInfo (GDI32.@)
2572 DWORD WINAPI
GetFontLanguageInfo(HDC hdc
)
2574 FONTSIGNATURE fontsig
;
2575 static const DWORD GCP_DBCS_MASK
=0x003F0000,
2576 GCP_DIACRITIC_MASK
=0x00000000,
2577 FLI_GLYPHS_MASK
=0x00000000,
2578 GCP_GLYPHSHAPE_MASK
=0x00000040,
2579 GCP_KASHIDA_MASK
=0x00000000,
2580 GCP_LIGATE_MASK
=0x00000000,
2581 GCP_USEKERNING_MASK
=0x00000000,
2582 GCP_REORDER_MASK
=0x00000060;
2586 GetTextCharsetInfo( hdc
, &fontsig
, 0 );
2587 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2589 if( (fontsig
.fsCsb
[0]&GCP_DBCS_MASK
)!=0 )
2592 if( (fontsig
.fsCsb
[0]&GCP_DIACRITIC_MASK
)!=0 )
2593 result
|=GCP_DIACRITIC
;
2595 if( (fontsig
.fsCsb
[0]&FLI_GLYPHS_MASK
)!=0 )
2598 if( (fontsig
.fsCsb
[0]&GCP_GLYPHSHAPE_MASK
)!=0 )
2599 result
|=GCP_GLYPHSHAPE
;
2601 if( (fontsig
.fsCsb
[0]&GCP_KASHIDA_MASK
)!=0 )
2602 result
|=GCP_KASHIDA
;
2604 if( (fontsig
.fsCsb
[0]&GCP_LIGATE_MASK
)!=0 )
2607 if( (fontsig
.fsCsb
[0]&GCP_USEKERNING_MASK
)!=0 )
2608 result
|=GCP_USEKERNING
;
2610 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2611 if( GetTextAlign( hdc
) & TA_RTLREADING
)
2612 if( (fontsig
.fsCsb
[0]&GCP_REORDER_MASK
)!=0 )
2613 result
|=GCP_REORDER
;
2619 /*************************************************************************
2620 * GetFontData [GDI32.@]
2622 * Retrieve data for TrueType font.
2626 * success: Number of bytes returned
2627 * failure: GDI_ERROR
2631 * Calls SetLastError()
2634 DWORD WINAPI
GetFontData(HDC hdc
, DWORD table
, DWORD offset
,
2635 LPVOID buffer
, DWORD length
)
2637 DC
*dc
= DC_GetDCPtr(hdc
);
2638 DWORD ret
= GDI_ERROR
;
2640 if(!dc
) return GDI_ERROR
;
2643 ret
= WineEngGetFontData(dc
->gdiFont
, table
, offset
, buffer
, length
);
2645 GDI_ReleaseObj(hdc
);
2649 /*************************************************************************
2650 * GetGlyphIndicesA [GDI32.@]
2652 DWORD WINAPI
GetGlyphIndicesA(HDC hdc
, LPCSTR lpstr
, INT count
,
2653 LPWORD pgi
, DWORD flags
)
2659 TRACE("(%p, %s, %d, %p, 0x%lx)\n",
2660 hdc
, debugstr_an(lpstr
, count
), count
, pgi
, flags
);
2662 lpstrW
= FONT_mbtowc(lpstr
, count
, &countW
);
2663 ret
= GetGlyphIndicesW(hdc
, lpstrW
, countW
, pgi
, flags
);
2664 HeapFree(GetProcessHeap(), 0, lpstrW
);
2669 /*************************************************************************
2670 * GetGlyphIndicesW [GDI32.@]
2672 DWORD WINAPI
GetGlyphIndicesW(HDC hdc
, LPCWSTR lpstr
, INT count
,
2673 LPWORD pgi
, DWORD flags
)
2675 DC
*dc
= DC_GetDCPtr(hdc
);
2676 DWORD ret
= GDI_ERROR
;
2678 TRACE("(%p, %s, %d, %p, 0x%lx)\n",
2679 hdc
, debugstr_wn(lpstr
, count
), count
, pgi
, flags
);
2681 if(!dc
) return GDI_ERROR
;
2684 ret
= WineEngGetGlyphIndices(dc
->gdiFont
, lpstr
, count
, pgi
, flags
);
2686 GDI_ReleaseObj(hdc
);
2690 /*************************************************************************
2691 * GetCharacterPlacementA [GDI32.@]
2693 * See GetCharacterPlacementW.
2696 * the web browser control of ie4 calls this with dwFlags=0
2699 GetCharacterPlacementA(HDC hdc
, LPCSTR lpString
, INT uCount
,
2700 INT nMaxExtent
, GCP_RESULTSA
*lpResults
,
2705 GCP_RESULTSW resultsW
;
2708 TRACE("%s, %d, %d, 0x%08lx\n",
2709 debugstr_an(lpString
, uCount
), uCount
, nMaxExtent
, dwFlags
);
2711 /* both structs are equal in size */
2712 memcpy(&resultsW
, lpResults
, sizeof(resultsW
));
2714 lpStringW
= FONT_mbtowc(lpString
, uCount
, &uCountW
);
2715 if(lpResults
->lpOutString
)
2716 resultsW
.lpOutString
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*uCountW
);
2718 ret
= GetCharacterPlacementW(hdc
, lpStringW
, uCountW
, nMaxExtent
, &resultsW
, dwFlags
);
2720 lpResults
->nGlyphs
= resultsW
.nGlyphs
;
2721 lpResults
->nMaxFit
= resultsW
.nMaxFit
;
2723 if(lpResults
->lpOutString
) {
2724 WideCharToMultiByte(CP_ACP
, 0, resultsW
.lpOutString
, uCountW
,
2725 lpResults
->lpOutString
, uCount
, NULL
, NULL
);
2728 HeapFree(GetProcessHeap(), 0, lpStringW
);
2729 HeapFree(GetProcessHeap(), 0, resultsW
.lpOutString
);
2734 /*************************************************************************
2735 * GetCharacterPlacementW [GDI32.@]
2737 * Retrieve information about a string. This includes the width, reordering,
2738 * Glyphing and so on.
2742 * The width and height of the string if successful, 0 if failed.
2746 * All flags except GCP_REORDER are not yet implemented.
2747 * Reordering is not 100% complient to the Windows BiDi method.
2748 * Caret positioning is not yet implemented for BiDi.
2749 * Classes are not yet implemented.
2753 GetCharacterPlacementW(
2754 HDC hdc
, /* [in] Device context for which the rendering is to be done */
2755 LPCWSTR lpString
, /* [in] The string for which information is to be returned */
2756 INT uCount
, /* [in] Number of WORDS in string. */
2757 INT nMaxExtent
, /* [in] Maximum extent the string is to take (in HDC logical units) */
2758 GCP_RESULTSW
*lpResults
,/* [in/out] A pointer to a GCP_RESULTSW struct */
2759 DWORD dwFlags
/* [in] Flags specifying how to process the string */
2766 TRACE("%s, %d, %d, 0x%08lx\n",
2767 debugstr_wn(lpString
, uCount
), uCount
, nMaxExtent
, dwFlags
);
2769 TRACE("lStructSize=%ld, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2770 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2771 lpResults
->lStructSize
, lpResults
->lpOutString
, lpResults
->lpOrder
,
2772 lpResults
->lpDx
, lpResults
->lpCaretPos
, lpResults
->lpClass
,
2773 lpResults
->lpGlyphs
, lpResults
->nGlyphs
, lpResults
->nMaxFit
);
2775 if(dwFlags
&(~GCP_REORDER
)) FIXME("flags 0x%08lx ignored\n", dwFlags
);
2776 if(lpResults
->lpClass
) FIXME("classes not implemented\n");
2777 if (lpResults
->lpCaretPos
&& (dwFlags
& GCP_REORDER
))
2778 FIXME("Caret positions for complex scripts not implemented\n");
2780 nSet
= (UINT
)uCount
;
2781 if(nSet
> lpResults
->nGlyphs
)
2782 nSet
= lpResults
->nGlyphs
;
2784 /* return number of initialized fields */
2785 lpResults
->nGlyphs
= nSet
;
2787 if((dwFlags
&GCP_REORDER
)==0 || !BidiAvail
)
2789 /* Treat the case where no special handling was requested in a fastpath way */
2790 /* copy will do if the GCP_REORDER flag is not set */
2791 if(lpResults
->lpOutString
)
2792 memcpy( lpResults
->lpOutString
, lpString
, nSet
* sizeof(WCHAR
));
2794 if(lpResults
->lpOrder
)
2796 for(i
= 0; i
< nSet
; i
++)
2797 lpResults
->lpOrder
[i
] = i
;
2801 BIDI_Reorder( lpString
, uCount
, dwFlags
, WINE_GCPW_FORCE_LTR
, lpResults
->lpOutString
,
2802 nSet
, lpResults
->lpOrder
);
2805 /* FIXME: Will use the placement chars */
2806 if (lpResults
->lpDx
)
2809 for (i
= 0; i
< nSet
; i
++)
2811 if (GetCharWidth32W(hdc
, lpString
[i
], lpString
[i
], &c
))
2812 lpResults
->lpDx
[i
]= c
;
2816 if (lpResults
->lpCaretPos
&& !(dwFlags
& GCP_REORDER
))
2820 lpResults
->lpCaretPos
[0] = 0;
2821 for (i
= 1; i
< nSet
; i
++)
2822 if (GetTextExtentPoint32W(hdc
, &(lpString
[i
- 1]), 1, &size
))
2823 lpResults
->lpCaretPos
[i
] = (pos
+= size
.cx
);
2826 if(lpResults
->lpGlyphs
)
2827 GetGlyphIndicesW(hdc
, lpString
, nSet
, lpResults
->lpGlyphs
, 0);
2829 if (GetTextExtentPoint32W(hdc
, lpString
, uCount
, &size
))
2830 ret
= MAKELONG(size
.cx
, size
.cy
);
2835 /*************************************************************************
2836 * GetCharABCWidthsFloatA [GDI32.@]
2838 * See GetCharABCWidthsFloatW.
2840 BOOL WINAPI
GetCharABCWidthsFloatA( HDC hdc
, UINT first
, UINT last
, LPABCFLOAT abcf
)
2842 INT i
, wlen
, count
= (INT
)(last
- first
+ 1);
2847 if (count
<= 0) return FALSE
;
2849 str
= HeapAlloc(GetProcessHeap(), 0, count
);
2851 for(i
= 0; i
< count
; i
++)
2852 str
[i
] = (BYTE
)(first
+ i
);
2854 wstr
= FONT_mbtowc(str
, count
, &wlen
);
2856 for (i
= 0; i
< wlen
; i
++)
2858 if (!GetCharABCWidthsFloatW( hdc
, wstr
[i
], wstr
[i
], abcf
))
2866 HeapFree( GetProcessHeap(), 0, str
);
2867 HeapFree( GetProcessHeap(), 0, wstr
);
2872 /*************************************************************************
2873 * GetCharABCWidthsFloatW [GDI32.@]
2875 * Retrieves widths of a range of characters.
2878 * hdc [I] Handle to device context.
2879 * first [I] First character in range to query.
2880 * last [I] Last character in range to query.
2881 * abcf [O] Array of LPABCFLOAT structures.
2888 * Only works with TrueType fonts. It also doesn't return real
2889 * floats but converted integers because it's implemented on
2890 * top of GetCharABCWidthsW.
2892 BOOL WINAPI
GetCharABCWidthsFloatW( HDC hdc
, UINT first
, UINT last
, LPABCFLOAT abcf
)
2895 unsigned int i
, size
= sizeof(ABC
) * (last
- first
+ 1);
2898 TRACE("%p, %d, %d, %p - partial stub\n", hdc
, first
, last
, abcf
);
2900 abc
= HeapAlloc( GetProcessHeap(), 0, size
);
2901 if (!abc
) return FALSE
;
2903 ret
= GetCharABCWidthsW( hdc
, first
, last
, abc
);
2906 for (i
= first
; i
<= last
; i
++, abc
++, abcf
++)
2908 abcf
->abcfA
= abc
->abcA
;
2909 abcf
->abcfB
= abc
->abcB
;
2910 abcf
->abcfC
= abc
->abcC
;
2913 HeapFree( GetProcessHeap(), 0, abc
);
2917 /*************************************************************************
2918 * GetCharWidthFloatA [GDI32.@]
2920 BOOL WINAPI
GetCharWidthFloatA(HDC hdc
, UINT iFirstChar
,
2921 UINT iLastChar
, PFLOAT pxBuffer
)
2923 FIXME_(gdi
)("GetCharWidthFloatA, stub\n");
2927 /*************************************************************************
2928 * GetCharWidthFloatW [GDI32.@]
2930 BOOL WINAPI
GetCharWidthFloatW(HDC hdc
, UINT iFirstChar
,
2931 UINT iLastChar
, PFLOAT pxBuffer
)
2933 FIXME_(gdi
)("GetCharWidthFloatW, stub\n");
2938 /***********************************************************************
2940 * Font Resource API *
2942 ***********************************************************************/
2944 /***********************************************************************
2945 * AddFontResourceA (GDI32.@)
2947 INT WINAPI
AddFontResourceA( LPCSTR str
)
2949 return AddFontResourceExA( str
, 0, NULL
);
2952 /***********************************************************************
2953 * AddFontResourceW (GDI32.@)
2955 INT WINAPI
AddFontResourceW( LPCWSTR str
)
2957 return AddFontResourceExW(str
, 0, NULL
);
2961 /***********************************************************************
2962 * AddFontResourceExA (GDI32.@)
2964 INT WINAPI
AddFontResourceExA( LPCSTR str
, DWORD fl
, PVOID pdv
)
2966 DWORD len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
2967 LPWSTR strW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2970 MultiByteToWideChar(CP_ACP
, 0, str
, -1, strW
, len
);
2971 ret
= AddFontResourceExW(strW
, fl
, pdv
);
2972 HeapFree(GetProcessHeap(), 0, strW
);
2976 /***********************************************************************
2977 * AddFontResourceExW (GDI32.@)
2979 INT WINAPI
AddFontResourceExW( LPCWSTR str
, DWORD fl
, PVOID pdv
)
2981 return WineEngAddFontResourceEx(str
, fl
, pdv
);
2984 /***********************************************************************
2985 * RemoveFontResourceA (GDI32.@)
2987 BOOL WINAPI
RemoveFontResourceA( LPCSTR str
)
2989 return RemoveFontResourceExA(str
, 0, 0);
2992 /***********************************************************************
2993 * RemoveFontResourceW (GDI32.@)
2995 BOOL WINAPI
RemoveFontResourceW( LPCWSTR str
)
2997 return RemoveFontResourceExW(str
, 0, 0);
3000 /***********************************************************************
3001 * AddFontMemResourceEx (GDI32.@)
3003 HANDLE WINAPI
AddFontMemResourceEx( PVOID pbFont
, DWORD cbFont
, PVOID pdv
, DWORD
*pcFonts
)
3005 FIXME("(%p,%08lx,%p,%p): stub\n", pbFont
, cbFont
, pdv
, pcFonts
);
3009 /***********************************************************************
3010 * RemoveFontResourceExA (GDI32.@)
3012 BOOL WINAPI
RemoveFontResourceExA( LPCSTR str
, DWORD fl
, PVOID pdv
)
3014 DWORD len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
3015 LPWSTR strW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3018 MultiByteToWideChar(CP_ACP
, 0, str
, -1, strW
, len
);
3019 ret
= RemoveFontResourceExW(strW
, fl
, pdv
);
3020 HeapFree(GetProcessHeap(), 0, strW
);
3024 /***********************************************************************
3025 * RemoveFontResourceExW (GDI32.@)
3027 BOOL WINAPI
RemoveFontResourceExW( LPCWSTR str
, DWORD fl
, PVOID pdv
)
3029 return WineEngRemoveFontResourceEx(str
, fl
, pdv
);
3032 /***********************************************************************
3033 * GetTextCharset (GDI32.@)
3035 UINT WINAPI
GetTextCharset(HDC hdc
)
3037 /* MSDN docs say this is equivalent */
3038 return GetTextCharsetInfo(hdc
, NULL
, 0);
3041 /***********************************************************************
3042 * GetTextCharsetInfo (GDI32.@)
3044 UINT WINAPI
GetTextCharsetInfo(HDC hdc
, LPFONTSIGNATURE fs
, DWORD flags
)
3046 UINT ret
= DEFAULT_CHARSET
;
3047 DC
*dc
= DC_GetDCPtr(hdc
);
3052 ret
= WineEngGetTextCharsetInfo(dc
->gdiFont
, fs
, flags
);
3054 GDI_ReleaseObj(hdc
);
3057 if (ret
== DEFAULT_CHARSET
&& fs
)
3058 memset(fs
, 0, sizeof(FONTSIGNATURE
));
3062 /***********************************************************************
3063 * GdiGetCharDimensions (GDI32.@)
3065 * Gets the average width of the characters in the English alphabet.
3068 * hdc [I] Handle to the device context to measure on.
3069 * lptm [O] Pointer to memory to store the text metrics into.
3070 * height [O] On exit, the maximum height of characters in the English alphabet.
3073 * The average width of characters in the English alphabet.
3076 * This function is used by the dialog manager to get the size of a dialog
3077 * unit. It should also be used by other pieces of code that need to know
3078 * the size of a dialog unit in logical units without having access to the
3079 * window handle of the dialog.
3080 * Windows caches the font metrics from this function, but we don't and
3081 * there doesn't appear to be an immediate advantage to do so.
3084 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3086 LONG WINAPI
GdiGetCharDimensions(HDC hdc
, LPTEXTMETRICW lptm
, LONG
*height
)
3089 static const WCHAR alphabet
[] = {
3090 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3091 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3092 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3094 if(lptm
&& !GetTextMetricsW(hdc
, lptm
)) return 0;
3096 if(!GetTextExtentPointW(hdc
, alphabet
, 52, &sz
)) return 0;
3098 if (height
) *height
= sz
.cy
;
3099 return (sz
.cx
/ 26 + 1) / 2;
3102 BOOL WINAPI
EnableEUDC(BOOL fEnableEUDC
)
3104 FIXME("(%d): stub\n", fEnableEUDC
);
3108 /***********************************************************************
3109 * GetCharWidthI (GDI32.@)
3111 BOOL WINAPI
GetCharWidthI(HDC hdc
, UINT giFirst
, UINT cgi
, LPWORD pgi
, LPINT lpBuffer
)
3113 FIXME("(%p, %d, %d, %p, %p): stub\n", hdc
, giFirst
, cgi
, pgi
, lpBuffer
);
3117 /***********************************************************************
3118 * GetFontUnicodeRanges (GDI32.@)
3120 DWORD WINAPI
GetFontUnicodeRanges(HDC hdc
, LPGLYPHSET lpgs
)
3122 FIXME("(%p, %p): stub\n", hdc
, lpgs
);