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( (const LOGFONTW
*)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( (const LOGFONTW
*)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((const TEXTMETRICW
*)ptmW
, (LPTEXTMETRICA
)ptmA
);
336 ptmA
->ntmTm
.ntmFlags
= ptmW
->ntmTm
.ntmFlags
;
337 ptmA
->ntmTm
.ntmSizeEM
= ptmW
->ntmTm
.ntmSizeEM
;
338 ptmA
->ntmTm
.ntmCellHeight
= ptmW
->ntmTm
.ntmCellHeight
;
339 ptmA
->ntmTm
.ntmAvgWidth
= ptmW
->ntmTm
.ntmAvgWidth
;
340 memcpy(&ptmA
->ntmFontSig
, &ptmW
->ntmFontSig
, sizeof(FONTSIGNATURE
));
344 /***********************************************************************
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("(%d %d %d %d %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 %d x %d\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 %d x %d\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 %d x %d\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 = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1306 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1307 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1308 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1309 " PitchAndFamily = %02x\n"
1310 " --------------------\n"
1311 " InternalLeading = %i\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
);
1487 /* check if the string offsets really fit into the provided size */
1488 /* FIXME: should we check string length as well? */
1489 if ((UINT_PTR
)lpOTM
->otmpFamilyName
>= lpOTM
->otmSize
)
1490 lpOTM
->otmpFamilyName
= 0; /* doesn't fit */
1492 if ((UINT_PTR
)lpOTM
->otmpFaceName
>= lpOTM
->otmSize
)
1493 lpOTM
->otmpFaceName
= 0; /* doesn't fit */
1495 if ((UINT_PTR
)lpOTM
->otmpStyleName
>= lpOTM
->otmSize
)
1496 lpOTM
->otmpStyleName
= 0; /* doesn't fit */
1498 if ((UINT_PTR
)lpOTM
->otmpFullName
>= lpOTM
->otmSize
)
1499 lpOTM
->otmpFullName
= 0; /* doesn't fit */
1503 if(lpOTMW
!= (OUTLINETEXTMETRICW
*)buf
)
1504 HeapFree(GetProcessHeap(), 0, lpOTMW
);
1510 /***********************************************************************
1511 * GetOutlineTextMetricsW [GDI32.@]
1513 UINT WINAPI
GetOutlineTextMetricsW(
1514 HDC hdc
, /* [in] Handle of device context */
1515 UINT cbData
, /* [in] Size of metric data array */
1516 LPOUTLINETEXTMETRICW lpOTM
) /* [out] Address of metric data array */
1518 DC
*dc
= DC_GetDCPtr( hdc
);
1519 OUTLINETEXTMETRICW
*output
= lpOTM
;
1522 TRACE("(%p,%d,%p)\n", hdc
, cbData
, lpOTM
);
1526 ret
= WineEngGetOutlineTextMetrics(dc
->gdiFont
, cbData
, output
);
1529 output
= HeapAlloc(GetProcessHeap(), 0, ret
);
1530 WineEngGetOutlineTextMetrics(dc
->gdiFont
, ret
, output
);
1533 #define WDPTOLP(x) ((x<0)? \
1534 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1535 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1536 #define HDPTOLP(y) ((y<0)? \
1537 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1538 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1540 output
->otmTextMetrics
.tmHeight
= HDPTOLP(output
->otmTextMetrics
.tmHeight
);
1541 output
->otmTextMetrics
.tmAscent
= HDPTOLP(output
->otmTextMetrics
.tmAscent
);
1542 output
->otmTextMetrics
.tmDescent
= HDPTOLP(output
->otmTextMetrics
.tmDescent
);
1543 output
->otmTextMetrics
.tmInternalLeading
= HDPTOLP(output
->otmTextMetrics
.tmInternalLeading
);
1544 output
->otmTextMetrics
.tmExternalLeading
= HDPTOLP(output
->otmTextMetrics
.tmExternalLeading
);
1545 output
->otmTextMetrics
.tmAveCharWidth
= WDPTOLP(output
->otmTextMetrics
.tmAveCharWidth
);
1546 output
->otmTextMetrics
.tmMaxCharWidth
= WDPTOLP(output
->otmTextMetrics
.tmMaxCharWidth
);
1547 output
->otmTextMetrics
.tmOverhang
= WDPTOLP(output
->otmTextMetrics
.tmOverhang
);
1548 output
->otmAscent
= HDPTOLP(output
->otmAscent
);
1549 output
->otmDescent
= HDPTOLP(output
->otmDescent
);
1550 output
->otmLineGap
= HDPTOLP(output
->otmLineGap
);
1551 output
->otmsCapEmHeight
= HDPTOLP(output
->otmsCapEmHeight
);
1552 output
->otmsXHeight
= HDPTOLP(output
->otmsXHeight
);
1553 output
->otmrcFontBox
.top
= HDPTOLP(output
->otmrcFontBox
.top
);
1554 output
->otmrcFontBox
.bottom
= HDPTOLP(output
->otmrcFontBox
.bottom
);
1555 output
->otmrcFontBox
.left
= WDPTOLP(output
->otmrcFontBox
.left
);
1556 output
->otmrcFontBox
.right
= WDPTOLP(output
->otmrcFontBox
.right
);
1557 output
->otmMacAscent
= HDPTOLP(output
->otmMacAscent
);
1558 output
->otmMacDescent
= HDPTOLP(output
->otmMacDescent
);
1559 output
->otmMacLineGap
= HDPTOLP(output
->otmMacLineGap
);
1560 output
->otmptSubscriptSize
.x
= WDPTOLP(output
->otmptSubscriptSize
.x
);
1561 output
->otmptSubscriptSize
.y
= HDPTOLP(output
->otmptSubscriptSize
.y
);
1562 output
->otmptSubscriptOffset
.x
= WDPTOLP(output
->otmptSubscriptOffset
.x
);
1563 output
->otmptSubscriptOffset
.y
= HDPTOLP(output
->otmptSubscriptOffset
.y
);
1564 output
->otmptSuperscriptSize
.x
= WDPTOLP(output
->otmptSuperscriptSize
.x
);
1565 output
->otmptSuperscriptSize
.y
= HDPTOLP(output
->otmptSuperscriptSize
.y
);
1566 output
->otmptSuperscriptOffset
.x
= WDPTOLP(output
->otmptSuperscriptOffset
.x
);
1567 output
->otmptSuperscriptOffset
.y
= HDPTOLP(output
->otmptSuperscriptOffset
.y
);
1568 output
->otmsStrikeoutSize
= HDPTOLP(output
->otmsStrikeoutSize
);
1569 output
->otmsStrikeoutPosition
= HDPTOLP(output
->otmsStrikeoutPosition
);
1570 output
->otmsUnderscoreSize
= HDPTOLP(output
->otmsUnderscoreSize
);
1571 output
->otmsUnderscorePosition
= HDPTOLP(output
->otmsUnderscorePosition
);
1574 if(output
!= lpOTM
) {
1575 memcpy(lpOTM
, output
, cbData
);
1576 HeapFree(GetProcessHeap(), 0, output
);
1582 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1583 but really this should just be a return 0. */
1585 ret
= sizeof(*lpOTM
);
1590 memset(lpOTM
, 0, ret
);
1591 lpOTM
->otmSize
= sizeof(*lpOTM
);
1592 GetTextMetricsW(hdc
, &lpOTM
->otmTextMetrics
);
1594 Further fill of the structure not implemented,
1595 Needs real values for the structure members
1600 GDI_ReleaseObj(hdc
);
1605 /***********************************************************************
1606 * GetCharWidthW (GDI32.@)
1607 * GetCharWidth32W (GDI32.@)
1609 BOOL WINAPI
GetCharWidth32W( HDC hdc
, UINT firstChar
, UINT lastChar
,
1614 DC
* dc
= DC_GetDCPtr( hdc
);
1615 if (!dc
) return FALSE
;
1618 ret
= WineEngGetCharWidth( dc
->gdiFont
, firstChar
, lastChar
, buffer
);
1619 else if (dc
->funcs
->pGetCharWidth
)
1620 ret
= dc
->funcs
->pGetCharWidth( dc
->physDev
, firstChar
, lastChar
, buffer
);
1624 /* convert device units to logical */
1625 for( i
= firstChar
; i
<= lastChar
; i
++, buffer
++ )
1626 *buffer
= INTERNAL_XDSTOWS(dc
, *buffer
);
1629 GDI_ReleaseObj( hdc
);
1634 /***********************************************************************
1635 * GetCharWidthA (GDI32.@)
1636 * GetCharWidth32A (GDI32.@)
1638 BOOL WINAPI
GetCharWidth32A( HDC hdc
, UINT firstChar
, UINT lastChar
,
1641 INT i
, wlen
, count
= (INT
)(lastChar
- firstChar
+ 1);
1646 if(count
<= 0) return FALSE
;
1648 str
= HeapAlloc(GetProcessHeap(), 0, count
);
1649 for(i
= 0; i
< count
; i
++)
1650 str
[i
] = (BYTE
)(firstChar
+ i
);
1652 wstr
= FONT_mbtowc(str
, count
, &wlen
);
1654 for(i
= 0; i
< wlen
; i
++)
1656 if(!GetCharWidth32W(hdc
, wstr
[i
], wstr
[i
], buffer
))
1664 HeapFree(GetProcessHeap(), 0, str
);
1665 HeapFree(GetProcessHeap(), 0, wstr
);
1671 /***********************************************************************
1672 * ExtTextOutA (GDI32.@)
1676 BOOL WINAPI
ExtTextOutA( HDC hdc
, INT x
, INT y
, UINT flags
,
1677 const RECT
*lprect
, LPCSTR str
, UINT count
, const INT
*lpDx
)
1684 if (flags
& ETO_GLYPH_INDEX
)
1685 return ExtTextOutW( hdc
, x
, y
, flags
, lprect
, (LPCWSTR
)str
, count
, lpDx
);
1687 p
= FONT_mbtowc(str
, count
, &wlen
);
1690 unsigned int i
= 0, j
= 0;
1692 lpDxW
= HeapAlloc( GetProcessHeap(), 0, wlen
*sizeof(INT
));
1694 if(IsDBCSLeadByte(str
[i
])) {
1695 lpDxW
[j
++] = lpDx
[i
] + lpDx
[i
+1];
1698 lpDxW
[j
++] = lpDx
[i
];
1704 ret
= ExtTextOutW( hdc
, x
, y
, flags
, lprect
, p
, wlen
, lpDxW
);
1706 HeapFree( GetProcessHeap(), 0, p
);
1707 HeapFree( GetProcessHeap(), 0, lpDxW
);
1712 /***********************************************************************
1713 * ExtTextOutW (GDI32.@)
1715 * Draws text using the currently selected font, background color, and text color.
1719 * x,y [I] coordinates of string
1721 * ETO_GRAYED - undocumented on MSDN
1722 * ETO_OPAQUE - use background color for fill the rectangle
1723 * ETO_CLIPPED - clipping text to the rectangle
1724 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1725 * than encoded characters. Implies ETO_IGNORELANGUAGE
1726 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1727 * Affects BiDi ordering
1728 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1729 * ETO_PDY - unimplemented
1730 * ETO_NUMERICSLATIN - unimplemented always assumed -
1731 * do not translate numbers into locale representations
1732 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1733 * lprect [I] dimensions for clipping or/and opaquing
1734 * str [I] text string
1735 * count [I] number of symbols in string
1736 * lpDx [I] optional parameter with distance between drawing characters
1742 BOOL WINAPI
ExtTextOutW( HDC hdc
, INT x
, INT y
, UINT flags
,
1743 const RECT
*lprect
, LPCWSTR str
, UINT count
, const INT
*lpDx
)
1746 LPWSTR reordered_str
= (LPWSTR
)str
;
1747 WORD
*glyphs
= NULL
;
1748 UINT align
= GetTextAlign( hdc
);
1752 double cosEsc
, sinEsc
;
1753 INT
*deltas
= NULL
, char_extra
;
1756 BOOL done_extents
= FALSE
;
1757 INT width
, xwidth
= 0, ywidth
= 0;
1759 DC
* dc
= DC_GetDCUpdate( hdc
);
1761 if (!dc
) return FALSE
;
1763 if (flags
& (ETO_NUMERICSLOCAL
| ETO_NUMERICSLATIN
| ETO_PDY
))
1764 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY unimplemented\n");
1766 if (!dc
->funcs
->pExtTextOut
&& !PATH_IsPathOpen(dc
->path
))
1768 GDI_ReleaseObj( hdc
);
1772 type
= GetObjectType(hdc
);
1773 if(type
== OBJ_METADC
|| type
== OBJ_ENHMETADC
)
1775 ret
= dc
->funcs
->pExtTextOut(dc
->physDev
, x
, y
, flags
, lprect
, str
, count
, lpDx
);
1776 GDI_ReleaseObj( hdc
);
1781 flags
&= ~ETO_CLIPPED
;
1783 if( !(flags
& (ETO_GLYPH_INDEX
| ETO_IGNORELANGUAGE
)) && BidiAvail
&& count
> 0 )
1785 reordered_str
= HeapAlloc(GetProcessHeap(), 0, count
*sizeof(WCHAR
));
1787 BIDI_Reorder( str
, count
, GCP_REORDER
,
1788 ((flags
&ETO_RTLREADING
)!=0 || (GetTextAlign(hdc
)&TA_RTLREADING
)!=0)?
1789 WINE_GCPW_FORCE_RTL
:WINE_GCPW_FORCE_LTR
,
1790 reordered_str
, count
, NULL
);
1792 flags
|= ETO_IGNORELANGUAGE
;
1795 TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc
, x
, y
, flags
,
1796 lprect
, debugstr_wn(str
, count
), count
, lpDx
);
1798 if(flags
& ETO_GLYPH_INDEX
)
1799 glyphs
= reordered_str
;
1802 TRACE("rect: %d,%d - %d,%d\n", lprect
->left
, lprect
->top
, lprect
->right
,
1804 TRACE("align = %x bkmode = %x mapmode = %x\n", align
, GetBkMode(hdc
), GetMapMode(hdc
));
1806 if(align
& TA_UPDATECP
)
1808 GetCurrentPositionEx( hdc
, &pt
);
1813 GetTextMetricsW(hdc
, &tm
);
1814 GetObjectW(GetCurrentObject(hdc
, OBJ_FONT
), sizeof(lf
), &lf
);
1816 if(!(tm
.tmPitchAndFamily
& TMPF_VECTOR
)) /* Non-scalable fonts shouldn't be rotated */
1817 lf
.lfEscapement
= 0;
1819 if(lf
.lfEscapement
!= 0)
1821 cosEsc
= cos(lf
.lfEscapement
* M_PI
/ 1800);
1822 sinEsc
= sin(lf
.lfEscapement
* M_PI
/ 1800);
1830 if(flags
& (ETO_CLIPPED
| ETO_OPAQUE
))
1834 if(flags
& ETO_GLYPH_INDEX
)
1835 GetTextExtentPointI(hdc
, glyphs
, count
, &sz
);
1837 GetTextExtentPointW(hdc
, reordered_str
, count
, &sz
);
1839 done_extents
= TRUE
;
1842 rc
.right
= x
+ sz
.cx
;
1843 rc
.bottom
= y
+ sz
.cy
;
1850 LPtoDP(hdc
, (POINT
*)&rc
, 2);
1852 if(rc
.left
> rc
.right
) {INT tmp
= rc
.left
; rc
.left
= rc
.right
; rc
.right
= tmp
;}
1853 if(rc
.top
> rc
.bottom
) {INT tmp
= rc
.top
; rc
.top
= rc
.bottom
; rc
.bottom
= tmp
;}
1856 if ((flags
& ETO_OPAQUE
) && !PATH_IsPathOpen(dc
->path
))
1857 dc
->funcs
->pExtTextOut(dc
->physDev
, 0, 0, ETO_OPAQUE
, &rc
, NULL
, 0, NULL
);
1867 LPtoDP(hdc
, &pt
, 1);
1871 char_extra
= GetTextCharacterExtra(hdc
);
1873 if(char_extra
|| dc
->breakExtra
|| lpDx
)
1877 deltas
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(INT
));
1878 for(i
= 0; i
< count
; i
++)
1880 if(lpDx
&& (flags
& ETO_PDY
))
1881 deltas
[i
] = lpDx
[i
*2] + char_extra
;
1883 deltas
[i
] = lpDx
[i
] + char_extra
;
1886 if(flags
& ETO_GLYPH_INDEX
)
1887 GetTextExtentPointI(hdc
, glyphs
+ i
, 1, &tmpsz
);
1889 GetTextExtentPointW(hdc
, reordered_str
+ i
, 1, &tmpsz
);
1891 deltas
[i
] = tmpsz
.cx
;
1894 if (!(flags
& ETO_GLYPH_INDEX
) && dc
->breakExtra
&& reordered_str
[i
] == tm
.tmBreakChar
)
1896 deltas
[i
] = deltas
[i
] + dc
->breakExtra
;
1898 deltas
[i
] = INTERNAL_XWSTODS(dc
, deltas
[i
]);
1906 if(flags
& ETO_GLYPH_INDEX
)
1907 GetTextExtentPointI(hdc
, glyphs
, count
, &sz
);
1909 GetTextExtentPointW(hdc
, reordered_str
, count
, &sz
);
1910 done_extents
= TRUE
;
1912 width
= INTERNAL_XWSTODS(dc
, sz
.cx
);
1914 xwidth
= width
* cosEsc
;
1915 ywidth
= width
* sinEsc
;
1917 tm
.tmAscent
= abs(INTERNAL_YWSTODS(dc
, tm
.tmAscent
));
1918 tm
.tmDescent
= abs(INTERNAL_YWSTODS(dc
, tm
.tmDescent
));
1919 switch( align
& (TA_LEFT
| TA_RIGHT
| TA_CENTER
) )
1922 if (align
& TA_UPDATECP
)
1926 DPtoLP(hdc
, &pt
, 1);
1927 MoveToEx(hdc
, pt
.x
, pt
.y
, NULL
);
1939 if (align
& TA_UPDATECP
)
1943 DPtoLP(hdc
, &pt
, 1);
1944 MoveToEx(hdc
, pt
.x
, pt
.y
, NULL
);
1949 switch( align
& (TA_TOP
| TA_BOTTOM
| TA_BASELINE
) )
1952 y
+= tm
.tmAscent
* cosEsc
;
1953 x
+= tm
.tmAscent
* sinEsc
;
1957 y
-= tm
.tmDescent
* cosEsc
;
1958 x
-= tm
.tmDescent
* sinEsc
;
1965 if (GetBkMode(hdc
) != TRANSPARENT
&& !PATH_IsPathOpen(dc
->path
))
1967 if(!((flags
& ETO_CLIPPED
) && (flags
& ETO_OPAQUE
)))
1969 if(!(flags
& ETO_OPAQUE
) || x
< rc
.left
|| x
+ width
>= rc
.right
||
1970 y
- tm
.tmAscent
< rc
.top
|| y
+ tm
.tmDescent
>= rc
.bottom
)
1974 rc
.right
= x
+ width
;
1975 rc
.top
= y
- tm
.tmAscent
;
1976 rc
.bottom
= y
+ tm
.tmDescent
;
1977 dc
->funcs
->pExtTextOut(dc
->physDev
, 0, 0, ETO_OPAQUE
, &rc
, NULL
, 0, NULL
);
1982 if(FontIsLinked(hdc
) && !(flags
& ETO_GLYPH_INDEX
))
1984 HFONT orig_font
= dc
->hFont
, cur_font
;
1986 INT span
= 0, *offsets
= NULL
, i
;
1988 glyphs
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(WORD
));
1989 for(i
= 0; i
< count
; i
++)
1991 WineEngGetLinkedHFont(dc
, reordered_str
[i
], &cur_font
, &glyph
);
1992 if(cur_font
!= dc
->hFont
)
1997 offsets
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(*deltas
));
2002 for(j
= 1; j
< count
; j
++)
2004 GetTextExtentPointW(hdc
, reordered_str
+ j
- 1, 1, &tmpsz
);
2005 offsets
[j
] = offsets
[j
-1] + INTERNAL_XWSTODS(dc
, tmpsz
.cx
);
2010 for(j
= 1; j
< count
; j
++)
2011 offsets
[j
] = offsets
[j
-1] + deltas
[j
];
2016 if (PATH_IsPathOpen(dc
->path
))
2017 ret
= PATH_ExtTextOut(dc
, x
+ offsets
[i
- span
] * cosEsc
, y
- offsets
[i
- span
] * sinEsc
,
2018 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
,
2019 glyphs
, span
, deltas
? deltas
+ i
- span
: NULL
);
2021 dc
->funcs
->pExtTextOut(dc
->physDev
, x
+ offsets
[i
- span
] * cosEsc
, y
- offsets
[i
- span
] * sinEsc
,
2022 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
,
2023 glyphs
, span
, deltas
? deltas
+ i
- span
: NULL
);
2026 SelectObject(hdc
, cur_font
);
2028 glyphs
[span
++] = glyph
;
2032 if (PATH_IsPathOpen(dc
->path
))
2033 ret
= PATH_ExtTextOut(dc
, x
+ (offsets
? offsets
[count
- span
] * cosEsc
: 0),
2034 y
- (offsets
? offsets
[count
- span
] * sinEsc
: 0),
2035 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
,
2036 glyphs
, span
, deltas
? deltas
+ count
- span
: NULL
);
2038 ret
= dc
->funcs
->pExtTextOut(dc
->physDev
, x
+ (offsets
? offsets
[count
- span
] * cosEsc
: 0),
2039 y
- (offsets
? offsets
[count
- span
] * sinEsc
: 0),
2040 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
,
2041 glyphs
, span
, deltas
? deltas
+ count
- span
: NULL
);
2042 SelectObject(hdc
, orig_font
);
2043 HeapFree(GetProcessHeap(), 0, offsets
);
2049 if(!(flags
& ETO_GLYPH_INDEX
) && dc
->gdiFont
)
2051 glyphs
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(WORD
));
2052 GetGlyphIndicesW(hdc
, reordered_str
, count
, glyphs
, 0);
2053 flags
|= ETO_GLYPH_INDEX
;
2056 if (PATH_IsPathOpen(dc
->path
))
2057 ret
= PATH_ExtTextOut(dc
, x
, y
, (flags
& ~ETO_OPAQUE
), &rc
,
2058 glyphs
? glyphs
: reordered_str
, count
, deltas
);
2060 ret
= dc
->funcs
->pExtTextOut(dc
->physDev
, x
, y
, (flags
& ~ETO_OPAQUE
), &rc
,
2061 glyphs
? glyphs
: reordered_str
, count
, deltas
);
2065 HeapFree(GetProcessHeap(), 0, deltas
);
2066 if(glyphs
!= reordered_str
)
2067 HeapFree(GetProcessHeap(), 0, glyphs
);
2068 if(reordered_str
!= str
)
2069 HeapFree(GetProcessHeap(), 0, reordered_str
);
2071 GDI_ReleaseObj( hdc
);
2073 if (ret
&& (lf
.lfUnderline
|| lf
.lfStrikeOut
))
2075 int underlinePos
, strikeoutPos
;
2076 int underlineWidth
, strikeoutWidth
;
2077 UINT size
= GetOutlineTextMetricsW(hdc
, 0, NULL
);
2078 OUTLINETEXTMETRICW
* otm
= NULL
;
2083 underlineWidth
= tm
.tmAscent
/ 20 + 1;
2084 strikeoutPos
= tm
.tmAscent
/ 2;
2085 strikeoutWidth
= underlineWidth
;
2089 otm
= HeapAlloc(GetProcessHeap(), 0, size
);
2090 GetOutlineTextMetricsW(hdc
, size
, otm
);
2091 underlinePos
= otm
->otmsUnderscorePosition
;
2092 underlineWidth
= otm
->otmsUnderscoreSize
;
2093 strikeoutPos
= otm
->otmsStrikeoutPosition
;
2094 strikeoutWidth
= otm
->otmsStrikeoutSize
;
2095 HeapFree(GetProcessHeap(), 0, otm
);
2098 if (PATH_IsPathOpen(dc
->path
))
2102 HBRUSH hbrush
= CreateSolidBrush(GetTextColor(hdc
));
2104 hbrush
= SelectObject(hdc
, hbrush
);
2105 hpen
= SelectObject(hdc
, GetStockObject(NULL_PEN
));
2109 pts
[0].x
= x
- underlinePos
* sinEsc
;
2110 pts
[0].y
= y
- underlinePos
* cosEsc
;
2111 pts
[1].x
= x
+ xwidth
- underlinePos
* sinEsc
;
2112 pts
[1].y
= y
- ywidth
- underlinePos
* cosEsc
;
2113 pts
[2].x
= pts
[1].x
+ underlineWidth
* sinEsc
;
2114 pts
[2].y
= pts
[1].y
+ underlineWidth
* cosEsc
;
2115 pts
[3].x
= pts
[0].x
+ underlineWidth
* sinEsc
;
2116 pts
[3].y
= pts
[0].y
+ underlineWidth
* cosEsc
;
2117 pts
[4].x
= pts
[0].x
;
2118 pts
[4].y
= pts
[0].y
;
2119 DPtoLP(hdc
, pts
, 5);
2120 Polygon(hdc
, pts
, 5);
2125 pts
[0].x
= x
- strikeoutPos
* sinEsc
;
2126 pts
[0].y
= y
- strikeoutPos
* cosEsc
;
2127 pts
[1].x
= x
+ xwidth
- strikeoutPos
* sinEsc
;
2128 pts
[1].y
= y
- ywidth
- strikeoutPos
* cosEsc
;
2129 pts
[2].x
= pts
[1].x
+ strikeoutWidth
* sinEsc
;
2130 pts
[2].y
= pts
[1].y
+ strikeoutWidth
* cosEsc
;
2131 pts
[3].x
= pts
[0].x
+ strikeoutWidth
* sinEsc
;
2132 pts
[3].y
= pts
[0].y
+ strikeoutWidth
* cosEsc
;
2133 pts
[4].x
= pts
[0].x
;
2134 pts
[4].y
= pts
[0].y
;
2135 DPtoLP(hdc
, pts
, 5);
2136 Polygon(hdc
, pts
, 5);
2139 SelectObject(hdc
, hpen
);
2140 hbrush
= SelectObject(hdc
, hbrush
);
2141 DeleteObject(hbrush
);
2145 POINT pts
[2], oldpt
;
2150 hpen
= CreatePen(PS_SOLID
, underlineWidth
, GetTextColor(hdc
));
2151 hpen
= SelectObject(hdc
, hpen
);
2154 pts
[1].x
= x
+ xwidth
;
2155 pts
[1].y
= y
- ywidth
;
2156 DPtoLP(hdc
, pts
, 2);
2157 MoveToEx(hdc
, pts
[0].x
- underlinePos
* sinEsc
, pts
[0].y
- underlinePos
* cosEsc
, &oldpt
);
2158 LineTo(hdc
, pts
[1].x
- underlinePos
* sinEsc
, pts
[1].y
- underlinePos
* cosEsc
);
2159 MoveToEx(hdc
, oldpt
.x
, oldpt
.y
, NULL
);
2160 DeleteObject(SelectObject(hdc
, hpen
));
2165 hpen
= CreatePen(PS_SOLID
, strikeoutWidth
, GetTextColor(hdc
));
2166 hpen
= SelectObject(hdc
, hpen
);
2169 pts
[1].x
= x
+ xwidth
;
2170 pts
[1].y
= y
- ywidth
;
2171 DPtoLP(hdc
, pts
, 2);
2172 MoveToEx(hdc
, pts
[0].x
- strikeoutPos
* sinEsc
, pts
[0].y
- strikeoutPos
* cosEsc
, &oldpt
);
2173 LineTo(hdc
, pts
[1].x
- strikeoutPos
* sinEsc
, pts
[1].y
- strikeoutPos
* cosEsc
);
2174 MoveToEx(hdc
, oldpt
.x
, oldpt
.y
, NULL
);
2175 DeleteObject(SelectObject(hdc
, hpen
));
2184 /***********************************************************************
2185 * TextOutA (GDI32.@)
2187 BOOL WINAPI
TextOutA( HDC hdc
, INT x
, INT y
, LPCSTR str
, INT count
)
2189 return ExtTextOutA( hdc
, x
, y
, 0, NULL
, str
, count
, NULL
);
2193 /***********************************************************************
2194 * TextOutW (GDI32.@)
2196 BOOL WINAPI
TextOutW(HDC hdc
, INT x
, INT y
, LPCWSTR str
, INT count
)
2198 return ExtTextOutW( hdc
, x
, y
, 0, NULL
, str
, count
, NULL
);
2202 /***********************************************************************
2203 * PolyTextOutA (GDI32.@)
2207 BOOL WINAPI
PolyTextOutA ( HDC hdc
, /* [in] Handle to device context */
2208 PPOLYTEXTA pptxt
, /* [in] Array of strings */
2209 INT cStrings
) /* [in] Number of strings in array */
2211 for (; cStrings
>0; cStrings
--, pptxt
++)
2212 if (!ExtTextOutA( hdc
, pptxt
->x
, pptxt
->y
, pptxt
->uiFlags
, &pptxt
->rcl
, pptxt
->lpstr
, pptxt
->n
, pptxt
->pdx
))
2219 /***********************************************************************
2220 * PolyTextOutW (GDI32.@)
2222 * Draw several Strings
2228 BOOL WINAPI
PolyTextOutW ( HDC hdc
, /* [in] Handle to device context */
2229 PPOLYTEXTW pptxt
, /* [in] Array of strings */
2230 INT cStrings
) /* [in] Number of strings in array */
2232 for (; cStrings
>0; cStrings
--, pptxt
++)
2233 if (!ExtTextOutW( hdc
, pptxt
->x
, pptxt
->y
, pptxt
->uiFlags
, &pptxt
->rcl
, pptxt
->lpstr
, pptxt
->n
, pptxt
->pdx
))
2239 /* FIXME: all following APIs ******************************************/
2242 /***********************************************************************
2243 * SetMapperFlags (GDI32.@)
2245 DWORD WINAPI
SetMapperFlags( HDC hDC
, DWORD dwFlag
)
2247 DC
*dc
= DC_GetDCPtr( hDC
);
2250 if(dc
->funcs
->pSetMapperFlags
)
2252 ret
= dc
->funcs
->pSetMapperFlags( dc
->physDev
, dwFlag
);
2253 /* FIXME: ret is just a success flag, we should return a proper value */
2256 FIXME("(%p, 0x%08x): stub - harmless\n", hDC
, dwFlag
);
2257 GDI_ReleaseObj( hDC
);
2261 /***********************************************************************
2262 * GetAspectRatioFilterEx (GDI.486)
2264 BOOL16 WINAPI
GetAspectRatioFilterEx16( HDC16 hdc
, LPSIZE16 pAspectRatio
)
2266 FIXME("(%04x, %p): -- Empty Stub !\n", hdc
, pAspectRatio
);
2270 /***********************************************************************
2271 * GetAspectRatioFilterEx (GDI32.@)
2273 BOOL WINAPI
GetAspectRatioFilterEx( HDC hdc
, LPSIZE pAspectRatio
)
2275 FIXME("(%p, %p): -- Empty Stub !\n", hdc
, pAspectRatio
);
2280 /***********************************************************************
2281 * GetCharABCWidthsA (GDI32.@)
2283 * See GetCharABCWidthsW.
2285 BOOL WINAPI
GetCharABCWidthsA(HDC hdc
, UINT firstChar
, UINT lastChar
,
2288 INT i
, wlen
, count
= (INT
)(lastChar
- firstChar
+ 1);
2293 if(count
<= 0) return FALSE
;
2295 str
= HeapAlloc(GetProcessHeap(), 0, count
);
2296 for(i
= 0; i
< count
; i
++)
2297 str
[i
] = (BYTE
)(firstChar
+ i
);
2299 wstr
= FONT_mbtowc(str
, count
, &wlen
);
2301 for(i
= 0; i
< wlen
; i
++)
2303 if(!GetCharABCWidthsW(hdc
, wstr
[i
], wstr
[i
], abc
))
2311 HeapFree(GetProcessHeap(), 0, str
);
2312 HeapFree(GetProcessHeap(), 0, wstr
);
2318 /******************************************************************************
2319 * GetCharABCWidthsW [GDI32.@]
2321 * Retrieves widths of characters in range.
2324 * hdc [I] Handle of device context
2325 * firstChar [I] First character in range to query
2326 * lastChar [I] Last character in range to query
2327 * abc [O] Address of character-width structure
2330 * Only works with TrueType fonts
2336 BOOL WINAPI
GetCharABCWidthsW( HDC hdc
, UINT firstChar
, UINT lastChar
,
2339 DC
*dc
= DC_GetDCPtr(hdc
);
2343 if (!dc
) return FALSE
;
2346 ret
= WineEngGetCharABCWidths( dc
->gdiFont
, firstChar
, lastChar
, abc
);
2352 /* convert device units to logical */
2353 for( i
= firstChar
; i
<= lastChar
; i
++, abc
++ ) {
2354 abc
->abcA
= INTERNAL_XDSTOWS(dc
, abc
->abcA
);
2355 abc
->abcB
= INTERNAL_XDSTOWS(dc
, abc
->abcB
);
2356 abc
->abcC
= INTERNAL_XDSTOWS(dc
, abc
->abcC
);
2361 GDI_ReleaseObj(hdc
);
2366 /******************************************************************************
2367 * GetCharABCWidthsI [GDI32.@]
2369 * Retrieves widths of characters in range.
2372 * hdc [I] Handle of device context
2373 * firstChar [I] First glyphs in range to query
2374 * count [I] Last glyphs in range to query
2375 * pgi [i] Array of glyphs to query
2376 * abc [O] Address of character-width structure
2379 * Only works with TrueType fonts
2385 BOOL WINAPI
GetCharABCWidthsI( HDC hdc
, UINT firstChar
, UINT count
,
2386 LPWORD pgi
, LPABC abc
)
2388 DC
*dc
= DC_GetDCPtr(hdc
);
2392 if (!dc
) return FALSE
;
2395 ret
= WineEngGetCharABCWidthsI( dc
->gdiFont
, firstChar
, count
, pgi
, abc
);
2401 /* convert device units to logical */
2402 for( i
= 0; i
< count
; i
++, abc
++ ) {
2403 abc
->abcA
= INTERNAL_XDSTOWS(dc
, abc
->abcA
);
2404 abc
->abcB
= INTERNAL_XDSTOWS(dc
, abc
->abcB
);
2405 abc
->abcC
= INTERNAL_XDSTOWS(dc
, abc
->abcC
);
2410 GDI_ReleaseObj(hdc
);
2415 /***********************************************************************
2416 * GetGlyphOutlineA (GDI32.@)
2418 DWORD WINAPI
GetGlyphOutlineA( HDC hdc
, UINT uChar
, UINT fuFormat
,
2419 LPGLYPHMETRICS lpgm
, DWORD cbBuffer
,
2420 LPVOID lpBuffer
, const MAT2
*lpmat2
)
2426 if(!(fuFormat
& GGO_GLYPH_INDEX
)) {
2429 if(uChar
> 0xff) { /* but, 2 bytes character only */
2431 mbchs
[0] = (uChar
& 0xff00) >> 8;
2432 mbchs
[1] = (uChar
& 0xff);
2435 mbchs
[0] = (uChar
& 0xff);
2437 p
= FONT_mbtowc(mbchs
, len
, NULL
);
2441 ret
= GetGlyphOutlineW(hdc
, c
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
,
2443 HeapFree(GetProcessHeap(), 0, p
);
2447 /***********************************************************************
2448 * GetGlyphOutlineW (GDI32.@)
2450 DWORD WINAPI
GetGlyphOutlineW( HDC hdc
, UINT uChar
, UINT fuFormat
,
2451 LPGLYPHMETRICS lpgm
, DWORD cbBuffer
,
2452 LPVOID lpBuffer
, const MAT2
*lpmat2
)
2454 DC
*dc
= DC_GetDCPtr(hdc
);
2457 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2458 hdc
, uChar
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
, lpmat2
);
2460 if(!dc
) return GDI_ERROR
;
2463 ret
= WineEngGetGlyphOutline(dc
->gdiFont
, uChar
, fuFormat
, lpgm
,
2464 cbBuffer
, lpBuffer
, lpmat2
);
2468 GDI_ReleaseObj(hdc
);
2473 /***********************************************************************
2474 * CreateScalableFontResourceA (GDI32.@)
2476 BOOL WINAPI
CreateScalableFontResourceA( DWORD fHidden
,
2477 LPCSTR lpszResourceFile
,
2478 LPCSTR lpszFontFile
,
2479 LPCSTR lpszCurrentPath
)
2483 /* fHidden=1 - only visible for the calling app, read-only, not
2484 * enumbered with EnumFonts/EnumFontFamilies
2485 * lpszCurrentPath can be NULL
2487 FIXME("(%d,%s,%s,%s): stub\n",
2488 fHidden
, debugstr_a(lpszResourceFile
), debugstr_a(lpszFontFile
),
2489 debugstr_a(lpszCurrentPath
) );
2491 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2492 if ((f
= CreateFileA(lpszResourceFile
, 0, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, 0)) != INVALID_HANDLE_VALUE
) {
2494 SetLastError(ERROR_FILE_EXISTS
);
2497 return FALSE
; /* create failed */
2500 /***********************************************************************
2501 * CreateScalableFontResourceW (GDI32.@)
2503 BOOL WINAPI
CreateScalableFontResourceW( DWORD fHidden
,
2504 LPCWSTR lpszResourceFile
,
2505 LPCWSTR lpszFontFile
,
2506 LPCWSTR lpszCurrentPath
)
2508 FIXME("(%d,%p,%p,%p): stub\n",
2509 fHidden
, lpszResourceFile
, lpszFontFile
, lpszCurrentPath
);
2510 return FALSE
; /* create failed */
2513 /*************************************************************************
2514 * GetKerningPairsA (GDI32.@)
2516 DWORD WINAPI
GetKerningPairsA( HDC hDC
, DWORD cPairs
,
2517 LPKERNINGPAIR kern_pairA
)
2522 DWORD i
, total_kern_pairs
, kern_pairs_copied
= 0;
2523 KERNINGPAIR
*kern_pairW
;
2525 if (!cPairs
&& kern_pairA
)
2527 SetLastError(ERROR_INVALID_PARAMETER
);
2531 charset
= GetTextCharset(hDC
);
2532 if (!TranslateCharsetInfo((DWORD
*)charset
, &csi
, TCI_SRCCHARSET
))
2534 FIXME("Can't find codepage for charset %d\n", charset
);
2537 if (!GetCPInfo(csi
.ciACP
, &cpi
))
2539 FIXME("Can't find codepage %u info\n", csi
.ciACP
);
2542 TRACE("charset %d => codepage %u\n", charset
, csi
.ciACP
);
2544 total_kern_pairs
= GetKerningPairsW(hDC
, 0, NULL
);
2545 if (!total_kern_pairs
) return 0;
2547 kern_pairW
= HeapAlloc(GetProcessHeap(), 0, total_kern_pairs
* sizeof(*kern_pairW
));
2548 GetKerningPairsW(hDC
, total_kern_pairs
, kern_pairW
);
2550 for (i
= 0; i
< total_kern_pairs
; i
++)
2554 if (!WideCharToMultiByte(csi
.ciACP
, 0, &kern_pairW
[i
].wFirst
, 1, &first
, 1, NULL
, NULL
))
2557 if (!WideCharToMultiByte(csi
.ciACP
, 0, &kern_pairW
[i
].wSecond
, 1, &second
, 1, NULL
, NULL
))
2560 if (first
== cpi
.DefaultChar
[0] || second
== cpi
.DefaultChar
[0])
2565 if (kern_pairs_copied
>= cPairs
) break;
2567 kern_pairA
->wFirst
= (BYTE
)first
;
2568 kern_pairA
->wSecond
= (BYTE
)second
;
2569 kern_pairA
->iKernAmount
= kern_pairW
[i
].iKernAmount
;
2572 kern_pairs_copied
++;
2575 HeapFree(GetProcessHeap(), 0, kern_pairW
);
2577 return kern_pairs_copied
;
2580 /*************************************************************************
2581 * GetKerningPairsW (GDI32.@)
2583 DWORD WINAPI
GetKerningPairsW( HDC hDC
, DWORD cPairs
,
2584 LPKERNINGPAIR lpKerningPairs
)
2589 TRACE("(%p,%d,%p)\n", hDC
, cPairs
, lpKerningPairs
);
2591 if (!cPairs
&& lpKerningPairs
)
2593 SetLastError(ERROR_INVALID_PARAMETER
);
2597 dc
= DC_GetDCPtr(hDC
);
2601 ret
= WineEngGetKerningPairs(dc
->gdiFont
, cPairs
, lpKerningPairs
);
2603 GDI_ReleaseObj(hDC
);
2607 /*************************************************************************
2608 * TranslateCharsetInfo [GDI32.@]
2610 * Fills a CHARSETINFO structure for a character set, code page, or
2611 * font. This allows making the correspondance between different labelings
2612 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2613 * of the same encoding.
2615 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2616 * only one codepage should be set in *lpSrc.
2619 * TRUE on success, FALSE on failure.
2622 BOOL WINAPI
TranslateCharsetInfo(
2623 LPDWORD lpSrc
, /* [in]
2624 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2625 if flags == TCI_SRCCHARSET: a character set value
2626 if flags == TCI_SRCCODEPAGE: a code page value
2628 LPCHARSETINFO lpCs
, /* [out] structure to receive charset information */
2629 DWORD flags
/* [in] determines interpretation of lpSrc */)
2633 case TCI_SRCFONTSIG
:
2634 while (!(*lpSrc
>>index
& 0x0001) && index
<MAXTCIINDEX
) index
++;
2636 case TCI_SRCCODEPAGE
:
2637 while ((UINT
) (lpSrc
) != FONT_tci
[index
].ciACP
&& index
< MAXTCIINDEX
) index
++;
2639 case TCI_SRCCHARSET
:
2640 while ((UINT
) (lpSrc
) != FONT_tci
[index
].ciCharset
&& index
< MAXTCIINDEX
) index
++;
2645 if (index
>= MAXTCIINDEX
|| FONT_tci
[index
].ciCharset
== DEFAULT_CHARSET
) return FALSE
;
2646 memcpy(lpCs
, &FONT_tci
[index
], sizeof(CHARSETINFO
));
2650 /*************************************************************************
2651 * GetFontLanguageInfo (GDI32.@)
2653 DWORD WINAPI
GetFontLanguageInfo(HDC hdc
)
2655 FONTSIGNATURE fontsig
;
2656 static const DWORD GCP_DBCS_MASK
=0x003F0000,
2657 GCP_DIACRITIC_MASK
=0x00000000,
2658 FLI_GLYPHS_MASK
=0x00000000,
2659 GCP_GLYPHSHAPE_MASK
=0x00000040,
2660 GCP_KASHIDA_MASK
=0x00000000,
2661 GCP_LIGATE_MASK
=0x00000000,
2662 GCP_USEKERNING_MASK
=0x00000000,
2663 GCP_REORDER_MASK
=0x00000060;
2667 GetTextCharsetInfo( hdc
, &fontsig
, 0 );
2668 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2670 if( (fontsig
.fsCsb
[0]&GCP_DBCS_MASK
)!=0 )
2673 if( (fontsig
.fsCsb
[0]&GCP_DIACRITIC_MASK
)!=0 )
2674 result
|=GCP_DIACRITIC
;
2676 if( (fontsig
.fsCsb
[0]&FLI_GLYPHS_MASK
)!=0 )
2679 if( (fontsig
.fsCsb
[0]&GCP_GLYPHSHAPE_MASK
)!=0 )
2680 result
|=GCP_GLYPHSHAPE
;
2682 if( (fontsig
.fsCsb
[0]&GCP_KASHIDA_MASK
)!=0 )
2683 result
|=GCP_KASHIDA
;
2685 if( (fontsig
.fsCsb
[0]&GCP_LIGATE_MASK
)!=0 )
2688 if( (fontsig
.fsCsb
[0]&GCP_USEKERNING_MASK
)!=0 )
2689 result
|=GCP_USEKERNING
;
2691 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2692 if( GetTextAlign( hdc
) & TA_RTLREADING
)
2693 if( (fontsig
.fsCsb
[0]&GCP_REORDER_MASK
)!=0 )
2694 result
|=GCP_REORDER
;
2700 /*************************************************************************
2701 * GetFontData [GDI32.@]
2703 * Retrieve data for TrueType font.
2707 * success: Number of bytes returned
2708 * failure: GDI_ERROR
2712 * Calls SetLastError()
2715 DWORD WINAPI
GetFontData(HDC hdc
, DWORD table
, DWORD offset
,
2716 LPVOID buffer
, DWORD length
)
2718 DC
*dc
= DC_GetDCPtr(hdc
);
2719 DWORD ret
= GDI_ERROR
;
2721 if(!dc
) return GDI_ERROR
;
2724 ret
= WineEngGetFontData(dc
->gdiFont
, table
, offset
, buffer
, length
);
2726 GDI_ReleaseObj(hdc
);
2730 /*************************************************************************
2731 * GetGlyphIndicesA [GDI32.@]
2733 DWORD WINAPI
GetGlyphIndicesA(HDC hdc
, LPCSTR lpstr
, INT count
,
2734 LPWORD pgi
, DWORD flags
)
2740 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2741 hdc
, debugstr_an(lpstr
, count
), count
, pgi
, flags
);
2743 lpstrW
= FONT_mbtowc(lpstr
, count
, &countW
);
2744 ret
= GetGlyphIndicesW(hdc
, lpstrW
, countW
, pgi
, flags
);
2745 HeapFree(GetProcessHeap(), 0, lpstrW
);
2750 /*************************************************************************
2751 * GetGlyphIndicesW [GDI32.@]
2753 DWORD WINAPI
GetGlyphIndicesW(HDC hdc
, LPCWSTR lpstr
, INT count
,
2754 LPWORD pgi
, DWORD flags
)
2756 DC
*dc
= DC_GetDCPtr(hdc
);
2757 DWORD ret
= GDI_ERROR
;
2759 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2760 hdc
, debugstr_wn(lpstr
, count
), count
, pgi
, flags
);
2762 if(!dc
) return GDI_ERROR
;
2765 ret
= WineEngGetGlyphIndices(dc
->gdiFont
, lpstr
, count
, pgi
, flags
);
2767 GDI_ReleaseObj(hdc
);
2771 /*************************************************************************
2772 * GetCharacterPlacementA [GDI32.@]
2774 * See GetCharacterPlacementW.
2777 * the web browser control of ie4 calls this with dwFlags=0
2780 GetCharacterPlacementA(HDC hdc
, LPCSTR lpString
, INT uCount
,
2781 INT nMaxExtent
, GCP_RESULTSA
*lpResults
,
2786 GCP_RESULTSW resultsW
;
2789 TRACE("%s, %d, %d, 0x%08x\n",
2790 debugstr_an(lpString
, uCount
), uCount
, nMaxExtent
, dwFlags
);
2792 /* both structs are equal in size */
2793 memcpy(&resultsW
, lpResults
, sizeof(resultsW
));
2795 lpStringW
= FONT_mbtowc(lpString
, uCount
, &uCountW
);
2796 if(lpResults
->lpOutString
)
2797 resultsW
.lpOutString
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*uCountW
);
2799 ret
= GetCharacterPlacementW(hdc
, lpStringW
, uCountW
, nMaxExtent
, &resultsW
, dwFlags
);
2801 lpResults
->nGlyphs
= resultsW
.nGlyphs
;
2802 lpResults
->nMaxFit
= resultsW
.nMaxFit
;
2804 if(lpResults
->lpOutString
) {
2805 WideCharToMultiByte(CP_ACP
, 0, resultsW
.lpOutString
, uCountW
,
2806 lpResults
->lpOutString
, uCount
, NULL
, NULL
);
2809 HeapFree(GetProcessHeap(), 0, lpStringW
);
2810 HeapFree(GetProcessHeap(), 0, resultsW
.lpOutString
);
2815 /*************************************************************************
2816 * GetCharacterPlacementW [GDI32.@]
2818 * Retrieve information about a string. This includes the width, reordering,
2819 * Glyphing and so on.
2823 * The width and height of the string if successful, 0 if failed.
2827 * All flags except GCP_REORDER are not yet implemented.
2828 * Reordering is not 100% complient to the Windows BiDi method.
2829 * Caret positioning is not yet implemented for BiDi.
2830 * Classes are not yet implemented.
2834 GetCharacterPlacementW(
2835 HDC hdc
, /* [in] Device context for which the rendering is to be done */
2836 LPCWSTR lpString
, /* [in] The string for which information is to be returned */
2837 INT uCount
, /* [in] Number of WORDS in string. */
2838 INT nMaxExtent
, /* [in] Maximum extent the string is to take (in HDC logical units) */
2839 GCP_RESULTSW
*lpResults
,/* [in/out] A pointer to a GCP_RESULTSW struct */
2840 DWORD dwFlags
/* [in] Flags specifying how to process the string */
2847 TRACE("%s, %d, %d, 0x%08x\n",
2848 debugstr_wn(lpString
, uCount
), uCount
, nMaxExtent
, dwFlags
);
2850 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2851 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2852 lpResults
->lStructSize
, lpResults
->lpOutString
, lpResults
->lpOrder
,
2853 lpResults
->lpDx
, lpResults
->lpCaretPos
, lpResults
->lpClass
,
2854 lpResults
->lpGlyphs
, lpResults
->nGlyphs
, lpResults
->nMaxFit
);
2856 if(dwFlags
&(~GCP_REORDER
)) FIXME("flags 0x%08x ignored\n", dwFlags
);
2857 if(lpResults
->lpClass
) FIXME("classes not implemented\n");
2858 if (lpResults
->lpCaretPos
&& (dwFlags
& GCP_REORDER
))
2859 FIXME("Caret positions for complex scripts not implemented\n");
2861 nSet
= (UINT
)uCount
;
2862 if(nSet
> lpResults
->nGlyphs
)
2863 nSet
= lpResults
->nGlyphs
;
2865 /* return number of initialized fields */
2866 lpResults
->nGlyphs
= nSet
;
2868 if((dwFlags
&GCP_REORDER
)==0 || !BidiAvail
)
2870 /* Treat the case where no special handling was requested in a fastpath way */
2871 /* copy will do if the GCP_REORDER flag is not set */
2872 if(lpResults
->lpOutString
)
2873 memcpy( lpResults
->lpOutString
, lpString
, nSet
* sizeof(WCHAR
));
2875 if(lpResults
->lpOrder
)
2877 for(i
= 0; i
< nSet
; i
++)
2878 lpResults
->lpOrder
[i
] = i
;
2882 BIDI_Reorder( lpString
, uCount
, dwFlags
, WINE_GCPW_FORCE_LTR
, lpResults
->lpOutString
,
2883 nSet
, lpResults
->lpOrder
);
2886 /* FIXME: Will use the placement chars */
2887 if (lpResults
->lpDx
)
2890 for (i
= 0; i
< nSet
; i
++)
2892 if (GetCharWidth32W(hdc
, lpString
[i
], lpString
[i
], &c
))
2893 lpResults
->lpDx
[i
]= c
;
2897 if (lpResults
->lpCaretPos
&& !(dwFlags
& GCP_REORDER
))
2901 lpResults
->lpCaretPos
[0] = 0;
2902 for (i
= 1; i
< nSet
; i
++)
2903 if (GetTextExtentPoint32W(hdc
, &(lpString
[i
- 1]), 1, &size
))
2904 lpResults
->lpCaretPos
[i
] = (pos
+= size
.cx
);
2907 if(lpResults
->lpGlyphs
)
2908 GetGlyphIndicesW(hdc
, lpString
, nSet
, lpResults
->lpGlyphs
, 0);
2910 if (GetTextExtentPoint32W(hdc
, lpString
, uCount
, &size
))
2911 ret
= MAKELONG(size
.cx
, size
.cy
);
2916 /*************************************************************************
2917 * GetCharABCWidthsFloatA [GDI32.@]
2919 * See GetCharABCWidthsFloatW.
2921 BOOL WINAPI
GetCharABCWidthsFloatA( HDC hdc
, UINT first
, UINT last
, LPABCFLOAT abcf
)
2923 INT i
, wlen
, count
= (INT
)(last
- first
+ 1);
2928 if (count
<= 0) return FALSE
;
2930 str
= HeapAlloc(GetProcessHeap(), 0, count
);
2932 for(i
= 0; i
< count
; i
++)
2933 str
[i
] = (BYTE
)(first
+ i
);
2935 wstr
= FONT_mbtowc(str
, count
, &wlen
);
2937 for (i
= 0; i
< wlen
; i
++)
2939 if (!GetCharABCWidthsFloatW( hdc
, wstr
[i
], wstr
[i
], abcf
))
2947 HeapFree( GetProcessHeap(), 0, str
);
2948 HeapFree( GetProcessHeap(), 0, wstr
);
2953 /*************************************************************************
2954 * GetCharABCWidthsFloatW [GDI32.@]
2956 * Retrieves widths of a range of characters.
2959 * hdc [I] Handle to device context.
2960 * first [I] First character in range to query.
2961 * last [I] Last character in range to query.
2962 * abcf [O] Array of LPABCFLOAT structures.
2969 * Only works with TrueType fonts. It also doesn't return real
2970 * floats but converted integers because it's implemented on
2971 * top of GetCharABCWidthsW.
2973 BOOL WINAPI
GetCharABCWidthsFloatW( HDC hdc
, UINT first
, UINT last
, LPABCFLOAT abcf
)
2976 unsigned int i
, size
= sizeof(ABC
) * (last
- first
+ 1);
2979 TRACE("%p, %d, %d, %p - partial stub\n", hdc
, first
, last
, abcf
);
2981 abc
= HeapAlloc( GetProcessHeap(), 0, size
);
2982 if (!abc
) return FALSE
;
2984 ret
= GetCharABCWidthsW( hdc
, first
, last
, abc
);
2987 for (i
= first
; i
<= last
; i
++, abc
++, abcf
++)
2989 abcf
->abcfA
= abc
->abcA
;
2990 abcf
->abcfB
= abc
->abcB
;
2991 abcf
->abcfC
= abc
->abcC
;
2994 HeapFree( GetProcessHeap(), 0, abc
);
2998 /*************************************************************************
2999 * GetCharWidthFloatA [GDI32.@]
3001 BOOL WINAPI
GetCharWidthFloatA(HDC hdc
, UINT iFirstChar
,
3002 UINT iLastChar
, PFLOAT pxBuffer
)
3004 FIXME_(gdi
)("GetCharWidthFloatA, stub\n");
3008 /*************************************************************************
3009 * GetCharWidthFloatW [GDI32.@]
3011 BOOL WINAPI
GetCharWidthFloatW(HDC hdc
, UINT iFirstChar
,
3012 UINT iLastChar
, PFLOAT pxBuffer
)
3014 FIXME_(gdi
)("GetCharWidthFloatW, stub\n");
3019 /***********************************************************************
3021 * Font Resource API *
3023 ***********************************************************************/
3025 /***********************************************************************
3026 * AddFontResourceA (GDI32.@)
3028 INT WINAPI
AddFontResourceA( LPCSTR str
)
3030 return AddFontResourceExA( str
, 0, NULL
);
3033 /***********************************************************************
3034 * AddFontResourceW (GDI32.@)
3036 INT WINAPI
AddFontResourceW( LPCWSTR str
)
3038 return AddFontResourceExW(str
, 0, NULL
);
3042 /***********************************************************************
3043 * AddFontResourceExA (GDI32.@)
3045 INT WINAPI
AddFontResourceExA( LPCSTR str
, DWORD fl
, PVOID pdv
)
3047 DWORD len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
3048 LPWSTR strW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3051 MultiByteToWideChar(CP_ACP
, 0, str
, -1, strW
, len
);
3052 ret
= AddFontResourceExW(strW
, fl
, pdv
);
3053 HeapFree(GetProcessHeap(), 0, strW
);
3057 /***********************************************************************
3058 * AddFontResourceExW (GDI32.@)
3060 INT WINAPI
AddFontResourceExW( LPCWSTR str
, DWORD fl
, PVOID pdv
)
3062 return WineEngAddFontResourceEx(str
, fl
, pdv
);
3065 /***********************************************************************
3066 * RemoveFontResourceA (GDI32.@)
3068 BOOL WINAPI
RemoveFontResourceA( LPCSTR str
)
3070 return RemoveFontResourceExA(str
, 0, 0);
3073 /***********************************************************************
3074 * RemoveFontResourceW (GDI32.@)
3076 BOOL WINAPI
RemoveFontResourceW( LPCWSTR str
)
3078 return RemoveFontResourceExW(str
, 0, 0);
3081 /***********************************************************************
3082 * AddFontMemResourceEx (GDI32.@)
3084 HANDLE WINAPI
AddFontMemResourceEx( PVOID pbFont
, DWORD cbFont
, PVOID pdv
, DWORD
*pcFonts
)
3086 FIXME("(%p,%08x,%p,%p): stub\n", pbFont
, cbFont
, pdv
, pcFonts
);
3090 /***********************************************************************
3091 * RemoveFontResourceExA (GDI32.@)
3093 BOOL WINAPI
RemoveFontResourceExA( LPCSTR str
, DWORD fl
, PVOID pdv
)
3095 DWORD len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
3096 LPWSTR strW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3099 MultiByteToWideChar(CP_ACP
, 0, str
, -1, strW
, len
);
3100 ret
= RemoveFontResourceExW(strW
, fl
, pdv
);
3101 HeapFree(GetProcessHeap(), 0, strW
);
3105 /***********************************************************************
3106 * RemoveFontResourceExW (GDI32.@)
3108 BOOL WINAPI
RemoveFontResourceExW( LPCWSTR str
, DWORD fl
, PVOID pdv
)
3110 return WineEngRemoveFontResourceEx(str
, fl
, pdv
);
3113 /***********************************************************************
3114 * GetTextCharset (GDI32.@)
3116 UINT WINAPI
GetTextCharset(HDC hdc
)
3118 /* MSDN docs say this is equivalent */
3119 return GetTextCharsetInfo(hdc
, NULL
, 0);
3122 /***********************************************************************
3123 * GetTextCharsetInfo (GDI32.@)
3125 UINT WINAPI
GetTextCharsetInfo(HDC hdc
, LPFONTSIGNATURE fs
, DWORD flags
)
3127 UINT ret
= DEFAULT_CHARSET
;
3128 DC
*dc
= DC_GetDCPtr(hdc
);
3133 ret
= WineEngGetTextCharsetInfo(dc
->gdiFont
, fs
, flags
);
3135 GDI_ReleaseObj(hdc
);
3138 if (ret
== DEFAULT_CHARSET
&& fs
)
3139 memset(fs
, 0, sizeof(FONTSIGNATURE
));
3143 /***********************************************************************
3144 * GdiGetCharDimensions (GDI32.@)
3146 * Gets the average width of the characters in the English alphabet.
3149 * hdc [I] Handle to the device context to measure on.
3150 * lptm [O] Pointer to memory to store the text metrics into.
3151 * height [O] On exit, the maximum height of characters in the English alphabet.
3154 * The average width of characters in the English alphabet.
3157 * This function is used by the dialog manager to get the size of a dialog
3158 * unit. It should also be used by other pieces of code that need to know
3159 * the size of a dialog unit in logical units without having access to the
3160 * window handle of the dialog.
3161 * Windows caches the font metrics from this function, but we don't and
3162 * there doesn't appear to be an immediate advantage to do so.
3165 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3167 LONG WINAPI
GdiGetCharDimensions(HDC hdc
, LPTEXTMETRICW lptm
, LONG
*height
)
3170 static const WCHAR alphabet
[] = {
3171 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3172 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3173 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3175 if(lptm
&& !GetTextMetricsW(hdc
, lptm
)) return 0;
3177 if(!GetTextExtentPointW(hdc
, alphabet
, 52, &sz
)) return 0;
3179 if (height
) *height
= sz
.cy
;
3180 return (sz
.cx
/ 26 + 1) / 2;
3183 BOOL WINAPI
EnableEUDC(BOOL fEnableEUDC
)
3185 FIXME("(%d): stub\n", fEnableEUDC
);
3189 /***********************************************************************
3190 * GetCharWidthI (GDI32.@)
3192 BOOL WINAPI
GetCharWidthI(HDC hdc
, UINT giFirst
, UINT cgi
, LPWORD pgi
, LPINT lpBuffer
)
3194 FIXME("(%p, %d, %d, %p, %p): stub\n", hdc
, giFirst
, cgi
, pgi
, lpBuffer
);
3198 /***********************************************************************
3199 * GetFontUnicodeRanges (GDI32.@)
3201 DWORD WINAPI
GetFontUnicodeRanges(HDC hdc
, LPGLYPHSET lpgs
)
3203 FIXME("(%p, %p): stub\n", hdc
, lpgs
);