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"
34 #include "gdi_private.h"
35 #include "wine/exception.h"
36 #include "wine/unicode.h"
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(font
);
41 /* Device -> World size conversion */
43 /* Performs a device to world transformation on the specified width (which
44 * is in integer format).
46 static inline INT
INTERNAL_XDSTOWS(DC
*dc
, INT width
)
50 /* Perform operation with floating point */
51 floatWidth
= (double)width
* dc
->xformVport2World
.eM11
;
52 /* Round to integers */
53 return GDI_ROUND(floatWidth
);
56 /* Performs a device to world transformation on the specified size (which
57 * is in integer format).
59 static inline INT
INTERNAL_YDSTOWS(DC
*dc
, INT height
)
63 /* Perform operation with floating point */
64 floatHeight
= (double)height
* dc
->xformVport2World
.eM22
;
65 /* Round to integers */
66 return GDI_ROUND(floatHeight
);
69 static inline INT
INTERNAL_XWSTODS(DC
*dc
, INT width
)
72 pt
[0].x
= pt
[0].y
= 0;
75 LPtoDP(dc
->hSelf
, pt
, 2);
76 return pt
[1].x
- pt
[0].x
;
79 static inline INT
INTERNAL_YWSTODS(DC
*dc
, INT height
)
82 pt
[0].x
= pt
[0].y
= 0;
85 LPtoDP(dc
->hSelf
, pt
, 2);
86 return pt
[1].y
- pt
[0].y
;
89 static HGDIOBJ
FONT_SelectObject( HGDIOBJ handle
, HDC hdc
);
90 static INT
FONT_GetObjectA( HGDIOBJ handle
, INT count
, LPVOID buffer
);
91 static INT
FONT_GetObjectW( HGDIOBJ handle
, INT count
, LPVOID buffer
);
92 static BOOL
FONT_DeleteObject( HGDIOBJ handle
);
94 static const struct gdi_obj_funcs font_funcs
=
96 FONT_SelectObject
, /* pSelectObject */
97 FONT_GetObjectA
, /* pGetObjectA */
98 FONT_GetObjectW
, /* pGetObjectW */
99 NULL
, /* pUnrealizeObject */
100 FONT_DeleteObject
/* pDeleteObject */
111 LPLOGFONTW lpLogFontParam
;
112 FONTENUMPROCW lpEnumFunc
;
119 * For TranslateCharsetInfo
121 #define MAXTCIINDEX 32
122 static const CHARSETINFO FONT_tci
[MAXTCIINDEX
] = {
124 { ANSI_CHARSET
, 1252, {{0,0,0,0},{FS_LATIN1
,0}} },
125 { EASTEUROPE_CHARSET
, 1250, {{0,0,0,0},{FS_LATIN2
,0}} },
126 { RUSSIAN_CHARSET
, 1251, {{0,0,0,0},{FS_CYRILLIC
,0}} },
127 { GREEK_CHARSET
, 1253, {{0,0,0,0},{FS_GREEK
,0}} },
128 { TURKISH_CHARSET
, 1254, {{0,0,0,0},{FS_TURKISH
,0}} },
129 { HEBREW_CHARSET
, 1255, {{0,0,0,0},{FS_HEBREW
,0}} },
130 { ARABIC_CHARSET
, 1256, {{0,0,0,0},{FS_ARABIC
,0}} },
131 { BALTIC_CHARSET
, 1257, {{0,0,0,0},{FS_BALTIC
,0}} },
132 { VIETNAMESE_CHARSET
, 1258, {{0,0,0,0},{FS_VIETNAMESE
,0}} },
133 /* reserved by ANSI */
134 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
135 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
136 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
137 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
138 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
139 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
140 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
142 { THAI_CHARSET
, 874, {{0,0,0,0},{FS_THAI
,0}} },
143 { SHIFTJIS_CHARSET
, 932, {{0,0,0,0},{FS_JISJAPAN
,0}} },
144 { GB2312_CHARSET
, 936, {{0,0,0,0},{FS_CHINESESIMP
,0}} },
145 { HANGEUL_CHARSET
, 949, {{0,0,0,0},{FS_WANSUNG
,0}} },
146 { CHINESEBIG5_CHARSET
, 950, {{0,0,0,0},{FS_CHINESETRAD
,0}} },
147 { JOHAB_CHARSET
, 1361, {{0,0,0,0},{FS_JOHAB
,0}} },
148 /* reserved for alternate ANSI and OEM */
149 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
150 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
151 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
152 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
153 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
154 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
155 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
156 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
157 /* reserved for system */
158 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
159 { SYMBOL_CHARSET
, CP_SYMBOL
, {{0,0,0,0},{FS_SYMBOL
,0}} }
162 static void FONT_LogFontAToW( const LOGFONTA
*fontA
, LPLOGFONTW fontW
)
164 memcpy(fontW
, fontA
, sizeof(LOGFONTA
) - LF_FACESIZE
);
165 MultiByteToWideChar(CP_ACP
, 0, fontA
->lfFaceName
, -1, fontW
->lfFaceName
,
167 fontW
->lfFaceName
[LF_FACESIZE
-1] = 0;
170 static void FONT_LogFontWToA( const LOGFONTW
*fontW
, LPLOGFONTA fontA
)
172 memcpy(fontA
, fontW
, sizeof(LOGFONTA
) - LF_FACESIZE
);
173 WideCharToMultiByte(CP_ACP
, 0, fontW
->lfFaceName
, -1, fontA
->lfFaceName
,
174 LF_FACESIZE
, NULL
, NULL
);
175 fontA
->lfFaceName
[LF_FACESIZE
-1] = 0;
178 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW
*fontW
, LPENUMLOGFONTEXA fontA
)
180 FONT_LogFontWToA( &fontW
->elfLogFont
, &fontA
->elfLogFont
);
182 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfFullName
, -1,
183 (LPSTR
) fontA
->elfFullName
, LF_FULLFACESIZE
, NULL
, NULL
);
184 fontA
->elfFullName
[LF_FULLFACESIZE
-1] = '\0';
185 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfStyle
, -1,
186 (LPSTR
) fontA
->elfStyle
, LF_FACESIZE
, NULL
, NULL
);
187 fontA
->elfStyle
[LF_FACESIZE
-1] = '\0';
188 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfScript
, -1,
189 (LPSTR
) fontA
->elfScript
, LF_FACESIZE
, NULL
, NULL
);
190 fontA
->elfScript
[LF_FACESIZE
-1] = '\0';
193 static void FONT_EnumLogFontExAToW( const ENUMLOGFONTEXA
*fontA
, LPENUMLOGFONTEXW fontW
)
195 FONT_LogFontAToW( &fontA
->elfLogFont
, &fontW
->elfLogFont
);
197 MultiByteToWideChar( CP_ACP
, 0, (LPCSTR
)fontA
->elfFullName
, -1,
198 fontW
->elfFullName
, LF_FULLFACESIZE
);
199 fontW
->elfFullName
[LF_FULLFACESIZE
-1] = '\0';
200 MultiByteToWideChar( CP_ACP
, 0, (LPCSTR
)fontA
->elfStyle
, -1,
201 fontW
->elfStyle
, LF_FACESIZE
);
202 fontW
->elfStyle
[LF_FACESIZE
-1] = '\0';
203 MultiByteToWideChar( CP_ACP
, 0, (LPCSTR
)fontA
->elfScript
, -1,
204 fontW
->elfScript
, LF_FACESIZE
);
205 fontW
->elfScript
[LF_FACESIZE
-1] = '\0';
208 /***********************************************************************
209 * TEXTMETRIC conversion functions.
211 static void FONT_TextMetricWToA(const TEXTMETRICW
*ptmW
, LPTEXTMETRICA ptmA
)
213 ptmA
->tmHeight
= ptmW
->tmHeight
;
214 ptmA
->tmAscent
= ptmW
->tmAscent
;
215 ptmA
->tmDescent
= ptmW
->tmDescent
;
216 ptmA
->tmInternalLeading
= ptmW
->tmInternalLeading
;
217 ptmA
->tmExternalLeading
= ptmW
->tmExternalLeading
;
218 ptmA
->tmAveCharWidth
= ptmW
->tmAveCharWidth
;
219 ptmA
->tmMaxCharWidth
= ptmW
->tmMaxCharWidth
;
220 ptmA
->tmWeight
= ptmW
->tmWeight
;
221 ptmA
->tmOverhang
= ptmW
->tmOverhang
;
222 ptmA
->tmDigitizedAspectX
= ptmW
->tmDigitizedAspectX
;
223 ptmA
->tmDigitizedAspectY
= ptmW
->tmDigitizedAspectY
;
224 ptmA
->tmFirstChar
= min(ptmW
->tmFirstChar
, 255);
225 if (ptmW
->tmCharSet
== SYMBOL_CHARSET
)
227 ptmA
->tmFirstChar
= 0x1e;
228 ptmA
->tmLastChar
= 0xff; /* win9x behaviour - we need the OS2 table data to calculate correctly */
230 else if (ptmW
->tmPitchAndFamily
& TMPF_TRUETYPE
)
232 ptmA
->tmFirstChar
= ptmW
->tmDefaultChar
- 1;
233 ptmA
->tmLastChar
= min(ptmW
->tmLastChar
, 0xff);
237 ptmA
->tmFirstChar
= min(ptmW
->tmFirstChar
, 0xff);
238 ptmA
->tmLastChar
= min(ptmW
->tmLastChar
, 0xff);
240 ptmA
->tmDefaultChar
= ptmW
->tmDefaultChar
;
241 ptmA
->tmBreakChar
= ptmW
->tmBreakChar
;
242 ptmA
->tmItalic
= ptmW
->tmItalic
;
243 ptmA
->tmUnderlined
= ptmW
->tmUnderlined
;
244 ptmA
->tmStruckOut
= ptmW
->tmStruckOut
;
245 ptmA
->tmPitchAndFamily
= ptmW
->tmPitchAndFamily
;
246 ptmA
->tmCharSet
= ptmW
->tmCharSet
;
250 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW
*ptmW
, NEWTEXTMETRICEXA
*ptmA
)
252 FONT_TextMetricWToA((const TEXTMETRICW
*)ptmW
, (LPTEXTMETRICA
)ptmA
);
253 ptmA
->ntmTm
.ntmFlags
= ptmW
->ntmTm
.ntmFlags
;
254 ptmA
->ntmTm
.ntmSizeEM
= ptmW
->ntmTm
.ntmSizeEM
;
255 ptmA
->ntmTm
.ntmCellHeight
= ptmW
->ntmTm
.ntmCellHeight
;
256 ptmA
->ntmTm
.ntmAvgWidth
= ptmW
->ntmTm
.ntmAvgWidth
;
257 memcpy(&ptmA
->ntmFontSig
, &ptmW
->ntmFontSig
, sizeof(FONTSIGNATURE
));
261 /***********************************************************************
262 * GdiGetCodePage (GDI32.@)
264 DWORD WINAPI
GdiGetCodePage( HDC hdc
)
267 DC
*dc
= get_dc_ptr( hdc
);
271 cp
= dc
->font_code_page
;
272 release_dc_ptr( dc
);
277 /***********************************************************************
280 * Returns a Unicode translation of str using the charset of the
281 * currently selected font in hdc. If count is -1 then str is assumed
282 * to be '\0' terminated, otherwise it contains the number of bytes to
283 * convert. If plenW is non-NULL, on return it will point to the
284 * number of WCHARs that have been written. If pCP is non-NULL, on
285 * return it will point to the codepage used in the conversion. The
286 * caller should free the returned LPWSTR from the process heap
289 static LPWSTR
FONT_mbtowc(HDC hdc
, LPCSTR str
, INT count
, INT
*plenW
, UINT
*pCP
)
295 cp
= GdiGetCodePage( hdc
);
297 if(count
== -1) count
= strlen(str
);
298 lenW
= MultiByteToWideChar(cp
, 0, str
, count
, NULL
, 0);
299 strW
= HeapAlloc(GetProcessHeap(), 0, lenW
*sizeof(WCHAR
));
300 MultiByteToWideChar(cp
, 0, str
, count
, strW
, lenW
);
301 TRACE("mapped %s -> %s\n", debugstr_an(str
, count
), debugstr_wn(strW
, lenW
));
302 if(plenW
) *plenW
= lenW
;
307 /***********************************************************************
308 * CreateFontIndirectExA (GDI32.@)
310 HFONT WINAPI
CreateFontIndirectExA( const ENUMLOGFONTEXDVA
*penumexA
)
312 ENUMLOGFONTEXDVW enumexW
;
314 if (!penumexA
) return 0;
316 FONT_EnumLogFontExAToW( &penumexA
->elfEnumLogfontEx
, &enumexW
.elfEnumLogfontEx
);
317 enumexW
.elfDesignVector
= penumexA
->elfDesignVector
;
318 return CreateFontIndirectExW( &enumexW
);
321 /***********************************************************************
322 * CreateFontIndirectExW (GDI32.@)
324 HFONT WINAPI
CreateFontIndirectExW( const ENUMLOGFONTEXDVW
*penumex
)
330 if (!penumex
) return 0;
332 if (penumex
->elfEnumLogfontEx
.elfFullName
[0] ||
333 penumex
->elfEnumLogfontEx
.elfStyle
[0] ||
334 penumex
->elfEnumLogfontEx
.elfScript
[0])
336 FIXME("some fields ignored. fullname=%s, style=%s, script=%s\n",
337 debugstr_w(penumex
->elfEnumLogfontEx
.elfFullName
),
338 debugstr_w(penumex
->elfEnumLogfontEx
.elfStyle
),
339 debugstr_w(penumex
->elfEnumLogfontEx
.elfScript
));
342 plf
= &penumex
->elfEnumLogfontEx
.elfLogFont
;
343 if (!(fontPtr
= HeapAlloc( GetProcessHeap(), 0, sizeof(*fontPtr
) ))) return 0;
345 fontPtr
->logfont
= *plf
;
347 if (plf
->lfEscapement
!= plf
->lfOrientation
)
349 /* this should really depend on whether GM_ADVANCED is set */
350 fontPtr
->logfont
.lfOrientation
= fontPtr
->logfont
.lfEscapement
;
351 WARN("orientation angle %f set to "
352 "escapement angle %f for new font %p\n",
353 plf
->lfOrientation
/10., plf
->lfEscapement
/10., fontPtr
);
356 if (!(hFont
= alloc_gdi_handle( &fontPtr
->header
, OBJ_FONT
, &font_funcs
)))
358 HeapFree( GetProcessHeap(), 0, fontPtr
);
362 TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
363 plf
->lfHeight
, plf
->lfWidth
,
364 plf
->lfEscapement
, plf
->lfOrientation
,
365 plf
->lfPitchAndFamily
,
366 plf
->lfOutPrecision
, plf
->lfClipPrecision
,
367 plf
->lfQuality
, plf
->lfCharSet
,
368 debugstr_w(plf
->lfFaceName
),
369 plf
->lfWeight
> 400 ? "Bold" : "",
370 plf
->lfItalic
? "Italic" : "",
371 plf
->lfUnderline
? "Underline" : "", hFont
);
376 /***********************************************************************
377 * CreateFontIndirectA (GDI32.@)
379 HFONT WINAPI
CreateFontIndirectA( const LOGFONTA
*plfA
)
385 FONT_LogFontAToW( plfA
, &lfW
);
386 return CreateFontIndirectW( &lfW
);
389 /***********************************************************************
390 * CreateFontIndirectW (GDI32.@)
392 HFONT WINAPI
CreateFontIndirectW( const LOGFONTW
*plf
)
394 ENUMLOGFONTEXDVW exdv
;
398 exdv
.elfEnumLogfontEx
.elfLogFont
= *plf
;
399 exdv
.elfEnumLogfontEx
.elfFullName
[0] = 0;
400 exdv
.elfEnumLogfontEx
.elfStyle
[0] = 0;
401 exdv
.elfEnumLogfontEx
.elfScript
[0] = 0;
402 return CreateFontIndirectExW( &exdv
);
405 /*************************************************************************
406 * CreateFontA (GDI32.@)
408 HFONT WINAPI
CreateFontA( INT height
, INT width
, INT esc
,
409 INT orient
, INT weight
, DWORD italic
,
410 DWORD underline
, DWORD strikeout
, DWORD charset
,
411 DWORD outpres
, DWORD clippres
, DWORD quality
,
412 DWORD pitch
, LPCSTR name
)
416 logfont
.lfHeight
= height
;
417 logfont
.lfWidth
= width
;
418 logfont
.lfEscapement
= esc
;
419 logfont
.lfOrientation
= orient
;
420 logfont
.lfWeight
= weight
;
421 logfont
.lfItalic
= italic
;
422 logfont
.lfUnderline
= underline
;
423 logfont
.lfStrikeOut
= strikeout
;
424 logfont
.lfCharSet
= charset
;
425 logfont
.lfOutPrecision
= outpres
;
426 logfont
.lfClipPrecision
= clippres
;
427 logfont
.lfQuality
= quality
;
428 logfont
.lfPitchAndFamily
= pitch
;
431 lstrcpynA(logfont
.lfFaceName
,name
,sizeof(logfont
.lfFaceName
));
433 logfont
.lfFaceName
[0] = '\0';
435 return CreateFontIndirectA( &logfont
);
438 /*************************************************************************
439 * CreateFontW (GDI32.@)
441 HFONT WINAPI
CreateFontW( INT height
, INT width
, INT esc
,
442 INT orient
, INT weight
, DWORD italic
,
443 DWORD underline
, DWORD strikeout
, DWORD charset
,
444 DWORD outpres
, DWORD clippres
, DWORD quality
,
445 DWORD pitch
, LPCWSTR name
)
449 logfont
.lfHeight
= height
;
450 logfont
.lfWidth
= width
;
451 logfont
.lfEscapement
= esc
;
452 logfont
.lfOrientation
= orient
;
453 logfont
.lfWeight
= weight
;
454 logfont
.lfItalic
= italic
;
455 logfont
.lfUnderline
= underline
;
456 logfont
.lfStrikeOut
= strikeout
;
457 logfont
.lfCharSet
= charset
;
458 logfont
.lfOutPrecision
= outpres
;
459 logfont
.lfClipPrecision
= clippres
;
460 logfont
.lfQuality
= quality
;
461 logfont
.lfPitchAndFamily
= pitch
;
464 lstrcpynW(logfont
.lfFaceName
, name
,
465 sizeof(logfont
.lfFaceName
) / sizeof(WCHAR
));
467 logfont
.lfFaceName
[0] = '\0';
469 return CreateFontIndirectW( &logfont
);
472 static void update_font_code_page( DC
*dc
)
475 int charset
= DEFAULT_CHARSET
;
478 charset
= WineEngGetTextCharsetInfo( dc
->gdiFont
, NULL
, 0 );
480 /* Hmm, nicely designed api this one! */
481 if (TranslateCharsetInfo( ULongToPtr(charset
), &csi
, TCI_SRCCHARSET
) )
482 dc
->font_code_page
= csi
.ciACP
;
486 dc
->font_code_page
= GetOEMCP();
488 case DEFAULT_CHARSET
:
489 dc
->font_code_page
= GetACP();
499 /* FIXME: These have no place here, but because x11drv
500 enumerates fonts with these (made up) charsets some apps
501 might use them and then the FIXME below would become
502 annoying. Now we could pick the intended codepage for
503 each of these, but since it's broken anyway we'll just
504 use CP_ACP and hope it'll go away...
506 dc
->font_code_page
= CP_ACP
;
510 FIXME("Can't find codepage for charset %d\n", charset
);
511 dc
->font_code_page
= CP_ACP
;
516 TRACE("charset %d => cp %d\n", charset
, dc
->font_code_page
);
519 /***********************************************************************
522 static HGDIOBJ
FONT_SelectObject( HGDIOBJ handle
, HDC hdc
)
525 DC
*dc
= get_dc_ptr( hdc
);
530 if (!GDI_inc_ref_count( handle
))
532 release_dc_ptr( dc
);
536 physdev
= GET_DC_PHYSDEV( dc
, pSelectFont
);
537 if (physdev
->funcs
->pSelectFont( physdev
, handle
))
541 update_font_code_page( dc
);
542 GDI_dec_ref_count( ret
);
544 else GDI_dec_ref_count( handle
);
546 release_dc_ptr( dc
);
551 /***********************************************************************
554 static INT
FONT_GetObjectA( HGDIOBJ handle
, INT count
, LPVOID buffer
)
556 FONTOBJ
*font
= GDI_GetObjPtr( handle
, OBJ_FONT
);
562 FONT_LogFontWToA( &font
->logfont
, &lfA
);
563 if (count
> sizeof(lfA
)) count
= sizeof(lfA
);
564 memcpy( buffer
, &lfA
, count
);
566 else count
= sizeof(lfA
);
567 GDI_ReleaseObj( handle
);
571 /***********************************************************************
574 static INT
FONT_GetObjectW( HGDIOBJ handle
, INT count
, LPVOID buffer
)
576 FONTOBJ
*font
= GDI_GetObjPtr( handle
, OBJ_FONT
);
581 if (count
> sizeof(LOGFONTW
)) count
= sizeof(LOGFONTW
);
582 memcpy( buffer
, &font
->logfont
, count
);
584 else count
= sizeof(LOGFONTW
);
585 GDI_ReleaseObj( handle
);
590 /***********************************************************************
593 static BOOL
FONT_DeleteObject( HGDIOBJ handle
)
597 WineEngDestroyFontInstance( handle
);
599 if (!(obj
= free_gdi_handle( handle
))) return FALSE
;
600 return HeapFree( GetProcessHeap(), 0, obj
);
604 /***********************************************************************
607 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
608 * We have to use other types because of the FONTENUMPROCW definition.
610 static INT CALLBACK
FONT_EnumInstance( const LOGFONTW
*plf
, const TEXTMETRICW
*ptm
,
611 DWORD fType
, LPARAM lp
)
613 struct font_enum
*pfe
= (struct font_enum
*)lp
;
616 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
617 if ((!pfe
->lpLogFontParam
||
618 pfe
->lpLogFontParam
->lfCharSet
== DEFAULT_CHARSET
||
619 pfe
->lpLogFontParam
->lfCharSet
== plf
->lfCharSet
) &&
620 (!(fType
& RASTER_FONTTYPE
) || GetDeviceCaps(pfe
->hdc
, TEXTCAPS
) & TC_RA_ABLE
) )
622 /* convert font metrics */
623 ENUMLOGFONTEXA logfont
;
624 NEWTEXTMETRICEXA tmA
;
628 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW
*)plf
, &logfont
);
629 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW
*)ptm
, &tmA
);
630 plf
= (LOGFONTW
*)&logfont
.elfLogFont
;
631 ptm
= (TEXTMETRICW
*)&tmA
;
633 ret
= pfe
->lpEnumFunc( plf
, ptm
, fType
, pfe
->lpData
);
638 /***********************************************************************
639 * FONT_EnumFontFamiliesEx
641 static INT
FONT_EnumFontFamiliesEx( HDC hDC
, LPLOGFONTW plf
, FONTENUMPROCW efproc
,
642 LPARAM lParam
, BOOL unicode
)
645 DC
*dc
= get_dc_ptr( hDC
);
650 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pEnumFonts
);
652 if (plf
) TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf
->lfFaceName
), plf
->lfCharSet
);
653 fe
.lpLogFontParam
= plf
;
654 fe
.lpEnumFunc
= efproc
;
656 fe
.unicode
= unicode
;
658 ret
= physdev
->funcs
->pEnumFonts( physdev
, plf
, FONT_EnumInstance
, (LPARAM
)&fe
);
660 release_dc_ptr( dc
);
664 /***********************************************************************
665 * EnumFontFamiliesExW (GDI32.@)
667 INT WINAPI
EnumFontFamiliesExW( HDC hDC
, LPLOGFONTW plf
,
668 FONTENUMPROCW efproc
,
669 LPARAM lParam
, DWORD dwFlags
)
671 return FONT_EnumFontFamiliesEx( hDC
, plf
, efproc
, lParam
, TRUE
);
674 /***********************************************************************
675 * EnumFontFamiliesExA (GDI32.@)
677 INT WINAPI
EnumFontFamiliesExA( HDC hDC
, LPLOGFONTA plf
,
678 FONTENUMPROCA efproc
,
679 LPARAM lParam
, DWORD dwFlags
)
685 FONT_LogFontAToW( plf
, &lfW
);
690 return FONT_EnumFontFamiliesEx( hDC
, plfW
, (FONTENUMPROCW
)efproc
, lParam
, FALSE
);
693 /***********************************************************************
694 * EnumFontFamiliesA (GDI32.@)
696 INT WINAPI
EnumFontFamiliesA( HDC hDC
, LPCSTR lpFamily
,
697 FONTENUMPROCA efproc
, LPARAM lpData
)
703 if (!*lpFamily
) return 1;
704 lstrcpynA( lf
.lfFaceName
, lpFamily
, LF_FACESIZE
);
705 lf
.lfCharSet
= DEFAULT_CHARSET
;
706 lf
.lfPitchAndFamily
= 0;
711 return EnumFontFamiliesExA( hDC
, plf
, efproc
, lpData
, 0 );
714 /***********************************************************************
715 * EnumFontFamiliesW (GDI32.@)
717 INT WINAPI
EnumFontFamiliesW( HDC hDC
, LPCWSTR lpFamily
,
718 FONTENUMPROCW efproc
, LPARAM lpData
)
724 if (!*lpFamily
) return 1;
725 lstrcpynW( lf
.lfFaceName
, lpFamily
, LF_FACESIZE
);
726 lf
.lfCharSet
= DEFAULT_CHARSET
;
727 lf
.lfPitchAndFamily
= 0;
732 return EnumFontFamiliesExW( hDC
, plf
, efproc
, lpData
, 0 );
735 /***********************************************************************
736 * EnumFontsA (GDI32.@)
738 INT WINAPI
EnumFontsA( HDC hDC
, LPCSTR lpName
, FONTENUMPROCA efproc
,
741 return EnumFontFamiliesA( hDC
, lpName
, efproc
, lpData
);
744 /***********************************************************************
745 * EnumFontsW (GDI32.@)
747 INT WINAPI
EnumFontsW( HDC hDC
, LPCWSTR lpName
, FONTENUMPROCW efproc
,
750 return EnumFontFamiliesW( hDC
, lpName
, efproc
, lpData
);
754 /***********************************************************************
755 * GetTextCharacterExtra (GDI32.@)
757 INT WINAPI
GetTextCharacterExtra( HDC hdc
)
760 DC
*dc
= get_dc_ptr( hdc
);
761 if (!dc
) return 0x80000000;
763 release_dc_ptr( dc
);
768 /***********************************************************************
769 * SetTextCharacterExtra (GDI32.@)
771 INT WINAPI
SetTextCharacterExtra( HDC hdc
, INT extra
)
773 INT ret
= 0x80000000;
774 DC
* dc
= get_dc_ptr( hdc
);
778 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetTextCharacterExtra
);
779 extra
= physdev
->funcs
->pSetTextCharacterExtra( physdev
, extra
);
780 if (extra
!= 0x80000000)
783 dc
->charExtra
= extra
;
785 release_dc_ptr( dc
);
791 /***********************************************************************
792 * SetTextJustification (GDI32.@)
794 BOOL WINAPI
SetTextJustification( HDC hdc
, INT extra
, INT breaks
)
798 DC
* dc
= get_dc_ptr( hdc
);
800 if (!dc
) return FALSE
;
802 physdev
= GET_DC_PHYSDEV( dc
, pSetTextJustification
);
803 ret
= physdev
->funcs
->pSetTextJustification( physdev
, extra
, breaks
);
806 extra
= abs((extra
* dc
->vportExtX
+ dc
->wndExtX
/ 2) / dc
->wndExtX
);
807 if (!extra
) breaks
= 0;
810 dc
->breakExtra
= extra
/ breaks
;
811 dc
->breakRem
= extra
- (breaks
* dc
->breakExtra
);
819 release_dc_ptr( dc
);
824 /***********************************************************************
825 * GetTextFaceA (GDI32.@)
827 INT WINAPI
GetTextFaceA( HDC hdc
, INT count
, LPSTR name
)
829 INT res
= GetTextFaceW(hdc
, 0, NULL
);
830 LPWSTR nameW
= HeapAlloc( GetProcessHeap(), 0, res
* 2 );
831 GetTextFaceW( hdc
, res
, nameW
);
837 res
= WideCharToMultiByte(CP_ACP
, 0, nameW
, -1, name
, count
, NULL
, NULL
);
841 /* GetTextFaceA does NOT include the nul byte in the return count. */
848 res
= WideCharToMultiByte( CP_ACP
, 0, nameW
, -1, NULL
, 0, NULL
, NULL
);
849 HeapFree( GetProcessHeap(), 0, nameW
);
853 /***********************************************************************
854 * GetTextFaceW (GDI32.@)
856 INT WINAPI
GetTextFaceW( HDC hdc
, INT count
, LPWSTR name
)
861 DC
* dc
= get_dc_ptr( hdc
);
865 ret
= WineEngGetTextFace(dc
->gdiFont
, count
, name
);
866 else if ((font
= GDI_GetObjPtr( dc
->hFont
, OBJ_FONT
)))
868 INT n
= strlenW(font
->logfont
.lfFaceName
) + 1;
871 lstrcpynW( name
, font
->logfont
.lfFaceName
, count
);
875 GDI_ReleaseObj( dc
->hFont
);
877 release_dc_ptr( dc
);
882 /***********************************************************************
883 * GetTextExtentPoint32A (GDI32.@)
885 * See GetTextExtentPoint32W.
887 BOOL WINAPI
GetTextExtentPoint32A( HDC hdc
, LPCSTR str
, INT count
,
894 if (count
< 0) return FALSE
;
896 p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
900 ret
= GetTextExtentPoint32W( hdc
, p
, wlen
, size
);
901 HeapFree( GetProcessHeap(), 0, p
);
904 TRACE("(%p %s %d %p): returning %d x %d\n",
905 hdc
, debugstr_an (str
, count
), count
, size
, size
->cx
, size
->cy
);
910 /***********************************************************************
911 * GetTextExtentPoint32W [GDI32.@]
913 * Computes width/height for a string.
915 * Computes width and height of the specified string.
921 BOOL WINAPI
GetTextExtentPoint32W(
922 HDC hdc
, /* [in] Handle of device context */
923 LPCWSTR str
, /* [in] Address of text string */
924 INT count
, /* [in] Number of characters in string */
925 LPSIZE size
) /* [out] Address of structure for string size */
927 return GetTextExtentExPointW(hdc
, str
, count
, 0, NULL
, NULL
, size
);
930 /***********************************************************************
931 * GetTextExtentExPointI [GDI32.@]
933 * Computes width and height of the array of glyph indices.
936 * hdc [I] Handle of device context.
937 * indices [I] Glyph index array.
938 * count [I] Number of glyphs in array.
939 * max_ext [I] Maximum width in glyphs.
940 * nfit [O] Maximum number of characters.
941 * dxs [O] Partial string widths.
942 * size [O] Returned string size.
948 BOOL WINAPI
GetTextExtentExPointI( HDC hdc
, const WORD
*indices
, INT count
, INT max_ext
,
949 LPINT nfit
, LPINT dxs
, LPSIZE size
)
954 if (count
< 0) return FALSE
;
956 dc
= get_dc_ptr( hdc
);
957 if (!dc
) return FALSE
;
961 ret
= WineEngGetTextExtentExPointI(dc
->gdiFont
, indices
, count
, max_ext
, nfit
, dxs
, size
);
962 size
->cx
= abs(INTERNAL_XDSTOWS(dc
, size
->cx
));
963 size
->cy
= abs(INTERNAL_YDSTOWS(dc
, size
->cy
));
964 size
->cx
+= count
* dc
->charExtra
;
968 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pGetTextExtentExPoint
);
969 FIXME("calling GetTextExtentExPoint\n");
970 ret
= physdev
->funcs
->pGetTextExtentExPoint( physdev
, indices
, count
, max_ext
, nfit
, dxs
, size
);
973 release_dc_ptr( dc
);
975 TRACE("(%p %p %d %p): returning %d x %d\n",
976 hdc
, indices
, count
, size
, size
->cx
, size
->cy
);
980 /***********************************************************************
981 * GetTextExtentPointI [GDI32.@]
983 * Computes width and height of the array of glyph indices.
986 * hdc [I] Handle of device context.
987 * indices [I] Glyph index array.
988 * count [I] Number of glyphs in array.
989 * size [O] Returned string size.
995 BOOL WINAPI
GetTextExtentPointI( HDC hdc
, const WORD
*indices
, INT count
, LPSIZE size
)
997 return GetTextExtentExPointI( hdc
, indices
, count
, 0, NULL
, NULL
, size
);
1001 /***********************************************************************
1002 * GetTextExtentPointA (GDI32.@)
1004 BOOL WINAPI
GetTextExtentPointA( HDC hdc
, LPCSTR str
, INT count
,
1007 TRACE("not bug compatible.\n");
1008 return GetTextExtentPoint32A( hdc
, str
, count
, size
);
1011 /***********************************************************************
1012 * GetTextExtentPointW (GDI32.@)
1014 BOOL WINAPI
GetTextExtentPointW( HDC hdc
, LPCWSTR str
, INT count
,
1017 TRACE("not bug compatible.\n");
1018 return GetTextExtentPoint32W( hdc
, str
, count
, size
);
1022 /***********************************************************************
1023 * GetTextExtentExPointA (GDI32.@)
1025 BOOL WINAPI
GetTextExtentExPointA( HDC hdc
, LPCSTR str
, INT count
,
1026 INT maxExt
, LPINT lpnFit
,
1027 LPINT alpDx
, LPSIZE size
)
1034 if (count
< 0) return FALSE
;
1038 walpDx
= HeapAlloc( GetProcessHeap(), 0, count
* sizeof(INT
) );
1039 if (!walpDx
) return FALSE
;
1042 p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
1043 ret
= GetTextExtentExPointW( hdc
, p
, wlen
, maxExt
, lpnFit
, walpDx
, size
);
1046 INT n
= lpnFit
? *lpnFit
: wlen
;
1048 for(i
= 0, j
= 0; i
< n
; i
++, j
++)
1050 alpDx
[j
] = walpDx
[i
];
1051 if (IsDBCSLeadByte(str
[j
])) alpDx
[++j
] = walpDx
[i
];
1054 if (lpnFit
) *lpnFit
= WideCharToMultiByte(CP_ACP
,0,p
,*lpnFit
,NULL
,0,NULL
,NULL
);
1055 HeapFree( GetProcessHeap(), 0, p
);
1056 HeapFree( GetProcessHeap(), 0, walpDx
);
1061 /***********************************************************************
1062 * GetTextExtentExPointW (GDI32.@)
1064 * Return the size of the string as it would be if it was output properly by
1067 * This should include
1068 * - Intercharacter spacing
1069 * - justification spacing (not yet done)
1070 * - kerning? see below
1072 * Kerning. Since kerning would be carried out by the rendering code it should
1073 * be done by the driver. However they don't support it yet. Also I am not
1074 * yet persuaded that (certainly under Win95) any kerning is actually done.
1076 * str: According to MSDN this should be null-terminated. That is not true; a
1077 * null will not terminate it early.
1078 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1079 * than count. I have seen it be either the size of the full string or
1080 * 1 less than the size of the full string. I have not seen it bear any
1081 * resemblance to the portion that would fit.
1082 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1083 * trailing intercharacter spacing and any trailing justification.
1086 * Currently we do this by measuring each character etc. We should do it by
1087 * passing the request to the driver, perhaps by extending the
1088 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1089 * thinking about kerning issues and rounding issues in the justification.
1092 BOOL WINAPI
GetTextExtentExPointW( HDC hdc
, LPCWSTR str
, INT count
,
1093 INT maxExt
, LPINT lpnFit
,
1094 LPINT alpDx
, LPSIZE size
)
1103 TRACE("(%p, %s, %d)\n",hdc
,debugstr_wn(str
,count
),maxExt
);
1105 if (count
< 0) return FALSE
;
1107 dc
= get_dc_ptr(hdc
);
1108 if (!dc
) return FALSE
;
1110 GetTextMetricsW(hdc
, &tm
);
1112 /* If we need to calculate nFit, then we need the partial extents even if
1113 the user hasn't provided us with an array. */
1116 dxs
= alpDx
? alpDx
: HeapAlloc(GetProcessHeap(), 0, count
* sizeof alpDx
[0]);
1120 SetLastError(ERROR_OUTOFMEMORY
);
1127 dev
= GET_DC_PHYSDEV( dc
, pGetTextExtentExPoint
);
1128 ret
= dev
->funcs
->pGetTextExtentExPoint(dev
, str
, count
, 0, NULL
, dxs
, size
);
1130 /* Perform device size to world size transformations. */
1133 INT extra
= dc
->charExtra
,
1134 breakExtra
= dc
->breakExtra
,
1135 breakRem
= dc
->breakRem
,
1140 for (i
= 0; i
< count
; ++i
)
1142 dxs
[i
] = abs(INTERNAL_XDSTOWS(dc
, dxs
[i
]));
1143 dxs
[i
] += (i
+1) * extra
;
1144 if (count
> 1 && (breakExtra
|| breakRem
) && str
[i
] == tm
.tmBreakChar
)
1146 dxs
[i
] += breakExtra
;
1153 if (dxs
[i
] <= maxExt
)
1156 breakRem
= dc
->breakRem
;
1158 size
->cx
= abs(INTERNAL_XDSTOWS(dc
, size
->cx
));
1159 size
->cy
= abs(INTERNAL_YDSTOWS(dc
, size
->cy
));
1161 if (!dxs
&& count
> 1 && (breakExtra
|| breakRem
))
1163 for (i
= 0; i
< count
; i
++)
1165 if (str
[i
] == tm
.tmBreakChar
)
1167 size
->cx
+= breakExtra
;
1182 HeapFree(GetProcessHeap(), 0, dxs
);
1184 release_dc_ptr( dc
);
1186 TRACE("returning %d %d x %d\n",nFit
,size
->cx
,size
->cy
);
1190 /***********************************************************************
1191 * GetTextMetricsA (GDI32.@)
1193 BOOL WINAPI
GetTextMetricsA( HDC hdc
, TEXTMETRICA
*metrics
)
1197 if (!GetTextMetricsW( hdc
, &tm32
)) return FALSE
;
1198 FONT_TextMetricWToA( &tm32
, metrics
);
1202 /***********************************************************************
1203 * GetTextMetricsW (GDI32.@)
1205 BOOL WINAPI
GetTextMetricsW( HDC hdc
, TEXTMETRICW
*metrics
)
1209 DC
* dc
= get_dc_ptr( hdc
);
1210 if (!dc
) return FALSE
;
1212 physdev
= GET_DC_PHYSDEV( dc
, pGetTextMetrics
);
1213 ret
= physdev
->funcs
->pGetTextMetrics( physdev
, metrics
);
1217 /* device layer returns values in device units
1218 * therefore we have to convert them to logical */
1220 metrics
->tmDigitizedAspectX
= GetDeviceCaps(hdc
, LOGPIXELSX
);
1221 metrics
->tmDigitizedAspectY
= GetDeviceCaps(hdc
, LOGPIXELSY
);
1223 #define WDPTOLP(x) ((x<0)? \
1224 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1225 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1226 #define HDPTOLP(y) ((y<0)? \
1227 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1228 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1230 metrics
->tmHeight
= HDPTOLP(metrics
->tmHeight
);
1231 metrics
->tmAscent
= HDPTOLP(metrics
->tmAscent
);
1232 metrics
->tmDescent
= HDPTOLP(metrics
->tmDescent
);
1233 metrics
->tmInternalLeading
= HDPTOLP(metrics
->tmInternalLeading
);
1234 metrics
->tmExternalLeading
= HDPTOLP(metrics
->tmExternalLeading
);
1235 metrics
->tmAveCharWidth
= WDPTOLP(metrics
->tmAveCharWidth
);
1236 metrics
->tmMaxCharWidth
= WDPTOLP(metrics
->tmMaxCharWidth
);
1237 metrics
->tmOverhang
= WDPTOLP(metrics
->tmOverhang
);
1241 TRACE("text metrics:\n"
1242 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1243 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1244 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1245 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1246 " PitchAndFamily = %02x\n"
1247 " --------------------\n"
1248 " InternalLeading = %i\n"
1252 metrics
->tmWeight
, metrics
->tmFirstChar
, metrics
->tmAveCharWidth
,
1253 metrics
->tmItalic
, metrics
->tmLastChar
, metrics
->tmMaxCharWidth
,
1254 metrics
->tmUnderlined
, metrics
->tmDefaultChar
, metrics
->tmOverhang
,
1255 metrics
->tmStruckOut
, metrics
->tmBreakChar
, metrics
->tmCharSet
,
1256 metrics
->tmPitchAndFamily
,
1257 metrics
->tmInternalLeading
,
1260 metrics
->tmHeight
);
1262 release_dc_ptr( dc
);
1267 /***********************************************************************
1268 * GetOutlineTextMetricsA (GDI32.@)
1269 * Gets metrics for TrueType fonts.
1272 * If the supplied buffer isn't big enough Windows partially fills it up to
1273 * its given length and returns that length.
1276 * Success: Non-zero or size of required buffer
1279 UINT WINAPI
GetOutlineTextMetricsA(
1280 HDC hdc
, /* [in] Handle of device context */
1281 UINT cbData
, /* [in] Size of metric data array */
1282 LPOUTLINETEXTMETRICA lpOTM
) /* [out] Address of metric data array */
1284 char buf
[512], *ptr
;
1286 OUTLINETEXTMETRICW
*lpOTMW
= (OUTLINETEXTMETRICW
*)buf
;
1287 OUTLINETEXTMETRICA
*output
= lpOTM
;
1290 if((ret
= GetOutlineTextMetricsW(hdc
, 0, NULL
)) == 0)
1292 if(ret
> sizeof(buf
))
1293 lpOTMW
= HeapAlloc(GetProcessHeap(), 0, ret
);
1294 GetOutlineTextMetricsW(hdc
, ret
, lpOTMW
);
1296 needed
= sizeof(OUTLINETEXTMETRICA
);
1297 if(lpOTMW
->otmpFamilyName
)
1298 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1299 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFamilyName
), -1,
1300 NULL
, 0, NULL
, NULL
);
1301 if(lpOTMW
->otmpFaceName
)
1302 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1303 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFaceName
), -1,
1304 NULL
, 0, NULL
, NULL
);
1305 if(lpOTMW
->otmpStyleName
)
1306 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1307 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpStyleName
), -1,
1308 NULL
, 0, NULL
, NULL
);
1309 if(lpOTMW
->otmpFullName
)
1310 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1311 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFullName
), -1,
1312 NULL
, 0, NULL
, NULL
);
1319 TRACE("needed = %d\n", needed
);
1321 /* Since the supplied buffer isn't big enough, we'll alloc one
1322 that is and memcpy the first cbData bytes into the lpOTM at
1324 output
= HeapAlloc(GetProcessHeap(), 0, needed
);
1326 ret
= output
->otmSize
= min(needed
, cbData
);
1327 FONT_TextMetricWToA( &lpOTMW
->otmTextMetrics
, &output
->otmTextMetrics
);
1328 output
->otmFiller
= 0;
1329 output
->otmPanoseNumber
= lpOTMW
->otmPanoseNumber
;
1330 output
->otmfsSelection
= lpOTMW
->otmfsSelection
;
1331 output
->otmfsType
= lpOTMW
->otmfsType
;
1332 output
->otmsCharSlopeRise
= lpOTMW
->otmsCharSlopeRise
;
1333 output
->otmsCharSlopeRun
= lpOTMW
->otmsCharSlopeRun
;
1334 output
->otmItalicAngle
= lpOTMW
->otmItalicAngle
;
1335 output
->otmEMSquare
= lpOTMW
->otmEMSquare
;
1336 output
->otmAscent
= lpOTMW
->otmAscent
;
1337 output
->otmDescent
= lpOTMW
->otmDescent
;
1338 output
->otmLineGap
= lpOTMW
->otmLineGap
;
1339 output
->otmsCapEmHeight
= lpOTMW
->otmsCapEmHeight
;
1340 output
->otmsXHeight
= lpOTMW
->otmsXHeight
;
1341 output
->otmrcFontBox
= lpOTMW
->otmrcFontBox
;
1342 output
->otmMacAscent
= lpOTMW
->otmMacAscent
;
1343 output
->otmMacDescent
= lpOTMW
->otmMacDescent
;
1344 output
->otmMacLineGap
= lpOTMW
->otmMacLineGap
;
1345 output
->otmusMinimumPPEM
= lpOTMW
->otmusMinimumPPEM
;
1346 output
->otmptSubscriptSize
= lpOTMW
->otmptSubscriptSize
;
1347 output
->otmptSubscriptOffset
= lpOTMW
->otmptSubscriptOffset
;
1348 output
->otmptSuperscriptSize
= lpOTMW
->otmptSuperscriptSize
;
1349 output
->otmptSuperscriptOffset
= lpOTMW
->otmptSuperscriptOffset
;
1350 output
->otmsStrikeoutSize
= lpOTMW
->otmsStrikeoutSize
;
1351 output
->otmsStrikeoutPosition
= lpOTMW
->otmsStrikeoutPosition
;
1352 output
->otmsUnderscoreSize
= lpOTMW
->otmsUnderscoreSize
;
1353 output
->otmsUnderscorePosition
= lpOTMW
->otmsUnderscorePosition
;
1356 ptr
= (char*)(output
+ 1);
1357 left
= needed
- sizeof(*output
);
1359 if(lpOTMW
->otmpFamilyName
) {
1360 output
->otmpFamilyName
= (LPSTR
)(ptr
- (char*)output
);
1361 len
= WideCharToMultiByte(CP_ACP
, 0,
1362 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFamilyName
), -1,
1363 ptr
, left
, NULL
, NULL
);
1367 output
->otmpFamilyName
= 0;
1369 if(lpOTMW
->otmpFaceName
) {
1370 output
->otmpFaceName
= (LPSTR
)(ptr
- (char*)output
);
1371 len
= WideCharToMultiByte(CP_ACP
, 0,
1372 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFaceName
), -1,
1373 ptr
, left
, NULL
, NULL
);
1377 output
->otmpFaceName
= 0;
1379 if(lpOTMW
->otmpStyleName
) {
1380 output
->otmpStyleName
= (LPSTR
)(ptr
- (char*)output
);
1381 len
= WideCharToMultiByte(CP_ACP
, 0,
1382 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpStyleName
), -1,
1383 ptr
, left
, NULL
, NULL
);
1387 output
->otmpStyleName
= 0;
1389 if(lpOTMW
->otmpFullName
) {
1390 output
->otmpFullName
= (LPSTR
)(ptr
- (char*)output
);
1391 len
= WideCharToMultiByte(CP_ACP
, 0,
1392 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFullName
), -1,
1393 ptr
, left
, NULL
, NULL
);
1396 output
->otmpFullName
= 0;
1400 if(output
!= lpOTM
) {
1401 memcpy(lpOTM
, output
, cbData
);
1402 HeapFree(GetProcessHeap(), 0, output
);
1404 /* check if the string offsets really fit into the provided size */
1405 /* FIXME: should we check string length as well? */
1406 /* make sure that we don't read/write beyond the provided buffer */
1407 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFamilyName
) + sizeof(LPSTR
))
1409 if ((UINT_PTR
)lpOTM
->otmpFamilyName
>= lpOTM
->otmSize
)
1410 lpOTM
->otmpFamilyName
= 0; /* doesn't fit */
1413 /* make sure that we don't read/write beyond the provided buffer */
1414 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFaceName
) + sizeof(LPSTR
))
1416 if ((UINT_PTR
)lpOTM
->otmpFaceName
>= lpOTM
->otmSize
)
1417 lpOTM
->otmpFaceName
= 0; /* doesn't fit */
1420 /* make sure that we don't read/write beyond the provided buffer */
1421 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpStyleName
) + sizeof(LPSTR
))
1423 if ((UINT_PTR
)lpOTM
->otmpStyleName
>= lpOTM
->otmSize
)
1424 lpOTM
->otmpStyleName
= 0; /* doesn't fit */
1427 /* make sure that we don't read/write beyond the provided buffer */
1428 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFullName
) + sizeof(LPSTR
))
1430 if ((UINT_PTR
)lpOTM
->otmpFullName
>= lpOTM
->otmSize
)
1431 lpOTM
->otmpFullName
= 0; /* doesn't fit */
1436 if(lpOTMW
!= (OUTLINETEXTMETRICW
*)buf
)
1437 HeapFree(GetProcessHeap(), 0, lpOTMW
);
1443 /***********************************************************************
1444 * GetOutlineTextMetricsW [GDI32.@]
1446 UINT WINAPI
GetOutlineTextMetricsW(
1447 HDC hdc
, /* [in] Handle of device context */
1448 UINT cbData
, /* [in] Size of metric data array */
1449 LPOUTLINETEXTMETRICW lpOTM
) /* [out] Address of metric data array */
1451 DC
*dc
= get_dc_ptr( hdc
);
1452 OUTLINETEXTMETRICW
*output
= lpOTM
;
1455 TRACE("(%p,%d,%p)\n", hdc
, cbData
, lpOTM
);
1459 ret
= WineEngGetOutlineTextMetrics(dc
->gdiFont
, cbData
, output
);
1462 output
= HeapAlloc(GetProcessHeap(), 0, ret
);
1463 WineEngGetOutlineTextMetrics(dc
->gdiFont
, ret
, output
);
1466 output
->otmTextMetrics
.tmDigitizedAspectX
= GetDeviceCaps(hdc
, LOGPIXELSX
);
1467 output
->otmTextMetrics
.tmDigitizedAspectY
= GetDeviceCaps(hdc
, LOGPIXELSY
);
1469 #define WDPTOLP(x) ((x<0)? \
1470 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1471 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1472 #define HDPTOLP(y) ((y<0)? \
1473 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1474 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1476 output
->otmTextMetrics
.tmHeight
= HDPTOLP(output
->otmTextMetrics
.tmHeight
);
1477 output
->otmTextMetrics
.tmAscent
= HDPTOLP(output
->otmTextMetrics
.tmAscent
);
1478 output
->otmTextMetrics
.tmDescent
= HDPTOLP(output
->otmTextMetrics
.tmDescent
);
1479 output
->otmTextMetrics
.tmInternalLeading
= HDPTOLP(output
->otmTextMetrics
.tmInternalLeading
);
1480 output
->otmTextMetrics
.tmExternalLeading
= HDPTOLP(output
->otmTextMetrics
.tmExternalLeading
);
1481 output
->otmTextMetrics
.tmAveCharWidth
= WDPTOLP(output
->otmTextMetrics
.tmAveCharWidth
);
1482 output
->otmTextMetrics
.tmMaxCharWidth
= WDPTOLP(output
->otmTextMetrics
.tmMaxCharWidth
);
1483 output
->otmTextMetrics
.tmOverhang
= WDPTOLP(output
->otmTextMetrics
.tmOverhang
);
1484 output
->otmAscent
= HDPTOLP(output
->otmAscent
);
1485 output
->otmDescent
= HDPTOLP(output
->otmDescent
);
1486 output
->otmLineGap
= abs(INTERNAL_YDSTOWS(dc
,output
->otmLineGap
));
1487 output
->otmsCapEmHeight
= abs(INTERNAL_YDSTOWS(dc
,output
->otmsCapEmHeight
));
1488 output
->otmsXHeight
= abs(INTERNAL_YDSTOWS(dc
,output
->otmsXHeight
));
1489 output
->otmrcFontBox
.top
= HDPTOLP(output
->otmrcFontBox
.top
);
1490 output
->otmrcFontBox
.bottom
= HDPTOLP(output
->otmrcFontBox
.bottom
);
1491 output
->otmrcFontBox
.left
= WDPTOLP(output
->otmrcFontBox
.left
);
1492 output
->otmrcFontBox
.right
= WDPTOLP(output
->otmrcFontBox
.right
);
1493 output
->otmMacAscent
= HDPTOLP(output
->otmMacAscent
);
1494 output
->otmMacDescent
= HDPTOLP(output
->otmMacDescent
);
1495 output
->otmMacLineGap
= abs(INTERNAL_YDSTOWS(dc
,output
->otmMacLineGap
));
1496 output
->otmptSubscriptSize
.x
= WDPTOLP(output
->otmptSubscriptSize
.x
);
1497 output
->otmptSubscriptSize
.y
= HDPTOLP(output
->otmptSubscriptSize
.y
);
1498 output
->otmptSubscriptOffset
.x
= WDPTOLP(output
->otmptSubscriptOffset
.x
);
1499 output
->otmptSubscriptOffset
.y
= HDPTOLP(output
->otmptSubscriptOffset
.y
);
1500 output
->otmptSuperscriptSize
.x
= WDPTOLP(output
->otmptSuperscriptSize
.x
);
1501 output
->otmptSuperscriptSize
.y
= HDPTOLP(output
->otmptSuperscriptSize
.y
);
1502 output
->otmptSuperscriptOffset
.x
= WDPTOLP(output
->otmptSuperscriptOffset
.x
);
1503 output
->otmptSuperscriptOffset
.y
= HDPTOLP(output
->otmptSuperscriptOffset
.y
);
1504 output
->otmsStrikeoutSize
= abs(INTERNAL_YDSTOWS(dc
,output
->otmsStrikeoutSize
));
1505 output
->otmsStrikeoutPosition
= HDPTOLP(output
->otmsStrikeoutPosition
);
1506 output
->otmsUnderscoreSize
= HDPTOLP(output
->otmsUnderscoreSize
);
1507 output
->otmsUnderscorePosition
= HDPTOLP(output
->otmsUnderscorePosition
);
1510 if(output
!= lpOTM
) {
1511 memcpy(lpOTM
, output
, cbData
);
1512 HeapFree(GetProcessHeap(), 0, output
);
1518 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1519 but really this should just be a return 0. */
1521 ret
= sizeof(*lpOTM
);
1526 memset(lpOTM
, 0, ret
);
1527 lpOTM
->otmSize
= sizeof(*lpOTM
);
1528 GetTextMetricsW(hdc
, &lpOTM
->otmTextMetrics
);
1530 Further fill of the structure not implemented,
1531 Needs real values for the structure members
1540 static LPSTR
FONT_GetCharsByRangeA(HDC hdc
, UINT firstChar
, UINT lastChar
, PINT pByteLen
)
1542 INT i
, count
= lastChar
- firstChar
+ 1;
1549 switch (GdiGetCodePage(hdc
))
1556 if (lastChar
> 0xffff)
1558 if ((firstChar
^ lastChar
) > 0xff)
1562 if (lastChar
> 0xff)
1567 str
= HeapAlloc(GetProcessHeap(), 0, count
* 2 + 1);
1571 for(i
= 0, c
= firstChar
; c
<= lastChar
; i
++, c
++)
1574 str
[i
++] = (BYTE
)(c
>> 8);
1584 /***********************************************************************
1585 * GetCharWidthW (GDI32.@)
1586 * GetCharWidth32W (GDI32.@)
1588 BOOL WINAPI
GetCharWidth32W( HDC hdc
, UINT firstChar
, UINT lastChar
,
1594 DC
* dc
= get_dc_ptr( hdc
);
1596 if (!dc
) return FALSE
;
1598 dev
= GET_DC_PHYSDEV( dc
, pGetCharWidth
);
1599 ret
= dev
->funcs
->pGetCharWidth( dev
, firstChar
, lastChar
, buffer
);
1603 /* convert device units to logical */
1604 for( i
= firstChar
; i
<= lastChar
; i
++, buffer
++ )
1605 *buffer
= INTERNAL_XDSTOWS(dc
, *buffer
);
1607 release_dc_ptr( dc
);
1612 /***********************************************************************
1613 * GetCharWidthA (GDI32.@)
1614 * GetCharWidth32A (GDI32.@)
1616 BOOL WINAPI
GetCharWidth32A( HDC hdc
, UINT firstChar
, UINT lastChar
,
1624 str
= FONT_GetCharsByRangeA(hdc
, firstChar
, lastChar
, &i
);
1628 wstr
= FONT_mbtowc(hdc
, str
, i
, &wlen
, NULL
);
1630 for(i
= 0; i
< wlen
; i
++)
1632 if(!GetCharWidth32W(hdc
, wstr
[i
], wstr
[i
], buffer
))
1640 HeapFree(GetProcessHeap(), 0, str
);
1641 HeapFree(GetProcessHeap(), 0, wstr
);
1647 /***********************************************************************
1648 * ExtTextOutA (GDI32.@)
1652 BOOL WINAPI
ExtTextOutA( HDC hdc
, INT x
, INT y
, UINT flags
,
1653 const RECT
*lprect
, LPCSTR str
, UINT count
, const INT
*lpDx
)
1661 if (flags
& ETO_GLYPH_INDEX
)
1662 return ExtTextOutW( hdc
, x
, y
, flags
, lprect
, (LPCWSTR
)str
, count
, lpDx
);
1664 p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, &codepage
);
1667 unsigned int i
= 0, j
= 0;
1669 /* allocate enough for a ETO_PDY */
1670 lpDxW
= HeapAlloc( GetProcessHeap(), 0, 2*wlen
*sizeof(INT
));
1672 if(IsDBCSLeadByteEx(codepage
, str
[i
]))
1676 lpDxW
[j
++] = lpDx
[i
* 2] + lpDx
[(i
+ 1) * 2];
1677 lpDxW
[j
++] = lpDx
[i
* 2 + 1] + lpDx
[(i
+ 1) * 2 + 1];
1680 lpDxW
[j
++] = lpDx
[i
] + lpDx
[i
+ 1];
1687 lpDxW
[j
++] = lpDx
[i
* 2];
1688 lpDxW
[j
++] = lpDx
[i
* 2 + 1];
1691 lpDxW
[j
++] = lpDx
[i
];
1697 ret
= ExtTextOutW( hdc
, x
, y
, flags
, lprect
, p
, wlen
, lpDxW
);
1699 HeapFree( GetProcessHeap(), 0, p
);
1700 HeapFree( GetProcessHeap(), 0, lpDxW
);
1705 /***********************************************************************
1706 * ExtTextOutW (GDI32.@)
1708 * Draws text using the currently selected font, background color, and text color.
1712 * x,y [I] coordinates of string
1714 * ETO_GRAYED - undocumented on MSDN
1715 * ETO_OPAQUE - use background color for fill the rectangle
1716 * ETO_CLIPPED - clipping text to the rectangle
1717 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1718 * than encoded characters. Implies ETO_IGNORELANGUAGE
1719 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1720 * Affects BiDi ordering
1721 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1722 * ETO_PDY - unimplemented
1723 * ETO_NUMERICSLATIN - unimplemented always assumed -
1724 * do not translate numbers into locale representations
1725 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1726 * lprect [I] dimensions for clipping or/and opaquing
1727 * str [I] text string
1728 * count [I] number of symbols in string
1729 * lpDx [I] optional parameter with distance between drawing characters
1735 BOOL WINAPI
ExtTextOutW( HDC hdc
, INT x
, INT y
, UINT flags
,
1736 const RECT
*lprect
, LPCWSTR str
, UINT count
, const INT
*lpDx
)
1739 LPWSTR reordered_str
= (LPWSTR
)str
;
1740 WORD
*glyphs
= NULL
;
1741 UINT align
= GetTextAlign( hdc
);
1742 DWORD layout
= GetLayout( hdc
);
1746 double cosEsc
, sinEsc
;
1750 BOOL done_extents
= FALSE
;
1751 POINT
*deltas
= NULL
, width
= {0, 0};
1753 DC
* dc
= get_dc_ptr( hdc
);
1756 static int quietfixme
= 0;
1758 if (!dc
) return FALSE
;
1760 breakRem
= dc
->breakRem
;
1762 if (quietfixme
== 0 && flags
& (ETO_NUMERICSLOCAL
| ETO_NUMERICSLATIN
))
1764 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN unimplemented\n");
1769 physdev
= GET_DC_PHYSDEV( dc
, pExtTextOut
);
1770 type
= GetObjectType(hdc
);
1771 if(type
== OBJ_METADC
|| type
== OBJ_ENHMETADC
)
1773 ret
= physdev
->funcs
->pExtTextOut( physdev
, x
, y
, flags
, lprect
, str
, count
, lpDx
);
1774 release_dc_ptr( dc
);
1779 flags
&= ~ETO_CLIPPED
;
1781 if (flags
& ETO_RTLREADING
) align
|= TA_RTLREADING
;
1782 if (layout
& LAYOUT_RTL
)
1784 if ((align
& TA_CENTER
) != TA_CENTER
) align
^= TA_RIGHT
;
1785 align
^= TA_RTLREADING
;
1788 if( !(flags
& (ETO_GLYPH_INDEX
| ETO_IGNORELANGUAGE
)) && count
> 0 )
1791 reordered_str
= HeapAlloc(GetProcessHeap(), 0, count
*sizeof(WCHAR
));
1793 BIDI_Reorder( hdc
, str
, count
, GCP_REORDER
,
1794 (align
& TA_RTLREADING
) ? WINE_GCPW_FORCE_RTL
: WINE_GCPW_FORCE_LTR
,
1795 reordered_str
, count
, NULL
, &glyphs
, &cGlyphs
);
1797 flags
|= ETO_IGNORELANGUAGE
;
1800 flags
|= ETO_GLYPH_INDEX
;
1801 if (cGlyphs
!= count
)
1805 else if(flags
& ETO_GLYPH_INDEX
)
1806 glyphs
= reordered_str
;
1808 TRACE("%p, %d, %d, %08x, %s, %s, %d, %p)\n", hdc
, x
, y
, flags
,
1809 wine_dbgstr_rect(lprect
), debugstr_wn(str
, count
), count
, lpDx
);
1810 TRACE("align = %x bkmode = %x mapmode = %x\n", align
, GetBkMode(hdc
), GetMapMode(hdc
));
1812 if(align
& TA_UPDATECP
)
1814 GetCurrentPositionEx( hdc
, &pt
);
1819 GetTextMetricsW(hdc
, &tm
);
1820 GetObjectW(GetCurrentObject(hdc
, OBJ_FONT
), sizeof(lf
), &lf
);
1822 if(!(tm
.tmPitchAndFamily
& TMPF_VECTOR
)) /* Non-scalable fonts shouldn't be rotated */
1823 lf
.lfEscapement
= 0;
1825 if(lf
.lfEscapement
!= 0)
1827 cosEsc
= cos(lf
.lfEscapement
* M_PI
/ 1800);
1828 sinEsc
= sin(lf
.lfEscapement
* M_PI
/ 1800);
1836 if(flags
& (ETO_CLIPPED
| ETO_OPAQUE
))
1840 if(flags
& ETO_GLYPH_INDEX
)
1841 GetTextExtentPointI(hdc
, glyphs
, count
, &sz
);
1843 GetTextExtentPointW(hdc
, reordered_str
, count
, &sz
);
1845 done_extents
= TRUE
;
1848 rc
.right
= x
+ sz
.cx
;
1849 rc
.bottom
= y
+ sz
.cy
;
1856 LPtoDP(hdc
, (POINT
*)&rc
, 2);
1858 if(rc
.left
> rc
.right
) {INT tmp
= rc
.left
; rc
.left
= rc
.right
; rc
.right
= tmp
;}
1859 if(rc
.top
> rc
.bottom
) {INT tmp
= rc
.top
; rc
.top
= rc
.bottom
; rc
.bottom
= tmp
;}
1862 if ((flags
& ETO_OPAQUE
) && !PATH_IsPathOpen(dc
->path
))
1863 physdev
->funcs
->pExtTextOut( physdev
, 0, 0, ETO_OPAQUE
, &rc
, NULL
, 0, NULL
);
1873 LPtoDP(hdc
, &pt
, 1);
1877 char_extra
= GetTextCharacterExtra(hdc
);
1878 if(char_extra
|| dc
->breakExtra
|| breakRem
|| lpDx
|| lf
.lfEscapement
!= 0)
1882 POINT total
= {0, 0}, desired
[2];
1884 deltas
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(*deltas
));
1885 for(i
= 0; i
< count
; i
++)
1891 deltas
[i
].x
= lpDx
[i
* 2] + char_extra
;
1892 deltas
[i
].y
= -lpDx
[i
* 2 + 1];
1896 deltas
[i
].x
= lpDx
[i
] + char_extra
;
1903 if(flags
& ETO_GLYPH_INDEX
)
1904 GetTextExtentPointI(hdc
, glyphs
+ i
, 1, &tmpsz
);
1906 GetTextExtentPointW(hdc
, reordered_str
+ i
, 1, &tmpsz
);
1908 deltas
[i
].x
= tmpsz
.cx
;
1912 if (!(flags
& ETO_GLYPH_INDEX
) && (dc
->breakExtra
|| breakRem
) && reordered_str
[i
] == tm
.tmBreakChar
)
1914 deltas
[i
].x
= deltas
[i
].x
+ dc
->breakExtra
;
1921 total
.x
+= deltas
[i
].x
;
1922 total
.y
+= deltas
[i
].y
;
1924 desired
[0].x
= desired
[0].y
= 0;
1926 desired
[1].x
= cosEsc
* total
.x
+ sinEsc
* total
.y
;
1927 desired
[1].y
= -sinEsc
* total
.x
+ cosEsc
* total
.y
;
1929 LPtoDP(hdc
, desired
, 2);
1930 desired
[1].x
-= desired
[0].x
;
1931 desired
[1].y
-= desired
[0].y
;
1932 if (layout
& LAYOUT_RTL
) desired
[1].x
= -desired
[1].x
;
1934 deltas
[i
].x
= desired
[1].x
- width
.x
;
1935 deltas
[i
].y
= desired
[1].y
- width
.y
;
1945 if(flags
& ETO_GLYPH_INDEX
)
1946 GetTextExtentPointI(hdc
, glyphs
, count
, &sz
);
1948 GetTextExtentPointW(hdc
, reordered_str
, count
, &sz
);
1949 done_extents
= TRUE
;
1951 width
.x
= abs(INTERNAL_XWSTODS(dc
, sz
.cx
));
1955 tm
.tmAscent
= abs(INTERNAL_YWSTODS(dc
, tm
.tmAscent
));
1956 tm
.tmDescent
= abs(INTERNAL_YWSTODS(dc
, tm
.tmDescent
));
1957 switch( align
& (TA_LEFT
| TA_RIGHT
| TA_CENTER
) )
1960 if (align
& TA_UPDATECP
)
1964 DPtoLP(hdc
, &pt
, 1);
1965 MoveToEx(hdc
, pt
.x
, pt
.y
, NULL
);
1977 if (align
& TA_UPDATECP
)
1981 DPtoLP(hdc
, &pt
, 1);
1982 MoveToEx(hdc
, pt
.x
, pt
.y
, NULL
);
1987 switch( align
& (TA_TOP
| TA_BOTTOM
| TA_BASELINE
) )
1990 y
+= tm
.tmAscent
* cosEsc
;
1991 x
+= tm
.tmAscent
* sinEsc
;
1995 y
-= tm
.tmDescent
* cosEsc
;
1996 x
-= tm
.tmDescent
* sinEsc
;
2003 if (GetBkMode(hdc
) != TRANSPARENT
&& !PATH_IsPathOpen(dc
->path
))
2005 if(!((flags
& ETO_CLIPPED
) && (flags
& ETO_OPAQUE
)))
2007 if(!(flags
& ETO_OPAQUE
) || x
< rc
.left
|| x
+ width
.x
>= rc
.right
||
2008 y
- tm
.tmAscent
< rc
.top
|| y
+ tm
.tmDescent
>= rc
.bottom
)
2012 rc
.right
= x
+ width
.x
;
2013 rc
.top
= y
- tm
.tmAscent
;
2014 rc
.bottom
= y
+ tm
.tmDescent
;
2016 if(flags
& ETO_CLIPPED
)
2018 rc
.left
= max(lprect
->left
, rc
.left
);
2019 rc
.right
= min(lprect
->right
, rc
.right
);
2020 rc
.top
= max(lprect
->top
, rc
.top
);
2021 rc
.bottom
= min(lprect
->bottom
, rc
.bottom
);
2023 if(rc
.left
< rc
.right
&& rc
.top
< rc
.bottom
)
2024 physdev
->funcs
->pExtTextOut( physdev
, 0, 0, ETO_OPAQUE
, &rc
, NULL
, 0, NULL
);
2029 if(FontIsLinked(hdc
) && !(flags
& ETO_GLYPH_INDEX
))
2031 HFONT orig_font
= dc
->hFont
, cur_font
;
2034 POINT
*offsets
= NULL
;
2037 glyphs
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(WORD
));
2038 for(i
= 0; i
< count
; i
++)
2040 WineEngGetLinkedHFont(dc
, reordered_str
[i
], &cur_font
, &glyph
);
2041 if(cur_font
!= dc
->hFont
)
2046 offsets
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(*deltas
));
2047 offsets
[0].x
= offsets
[0].y
= 0;
2052 for(j
= 1; j
< count
; j
++)
2054 GetTextExtentPointW(hdc
, reordered_str
+ j
- 1, 1, &tmpsz
);
2055 offsets
[j
].x
= offsets
[j
- 1].x
+ abs(INTERNAL_XWSTODS(dc
, tmpsz
.cx
));
2061 for(j
= 1; j
< count
; j
++)
2063 offsets
[j
].x
= offsets
[j
- 1].x
+ deltas
[j
].x
;
2064 offsets
[j
].y
= offsets
[j
- 1].y
+ deltas
[j
].y
;
2070 if (PATH_IsPathOpen(dc
->path
))
2071 ret
= PATH_ExtTextOut(dc
, x
+ offsets
[i
- span
].x
, y
+ offsets
[i
- span
].y
,
2072 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
,
2073 glyphs
, span
, deltas
? (INT
*)(deltas
+ (i
- span
)) : NULL
);
2075 physdev
->funcs
->pExtTextOut( physdev
, x
+ offsets
[i
- span
].x
,
2076 y
+ offsets
[i
- span
].y
,
2077 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
, glyphs
,
2078 span
, deltas
? (INT
*)(deltas
+ (i
- span
)) : NULL
);
2081 SelectObject(hdc
, cur_font
);
2083 glyphs
[span
++] = glyph
;
2087 if (PATH_IsPathOpen(dc
->path
))
2088 ret
= PATH_ExtTextOut(dc
, x
+ (offsets
? offsets
[count
- span
].x
: 0),
2089 y
+ (offsets
? offsets
[count
- span
].y
: 0),
2090 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
,
2091 glyphs
, span
, deltas
? (INT
*)(deltas
+ (count
- span
)) : NULL
);
2093 ret
= physdev
->funcs
->pExtTextOut(physdev
, x
+ (offsets
? offsets
[count
- span
].x
: 0),
2094 y
+ (offsets
? offsets
[count
- span
].y
: 0),
2095 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
, glyphs
,
2096 span
, deltas
? (INT
*)(deltas
+ (count
- span
)) : NULL
);
2097 SelectObject(hdc
, orig_font
);
2098 HeapFree(GetProcessHeap(), 0, offsets
);
2104 if(!(flags
& ETO_GLYPH_INDEX
) && dc
->gdiFont
)
2106 glyphs
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(WORD
));
2107 GetGlyphIndicesW(hdc
, reordered_str
, count
, glyphs
, 0);
2108 flags
|= ETO_GLYPH_INDEX
;
2111 if (PATH_IsPathOpen(dc
->path
))
2112 ret
= PATH_ExtTextOut(dc
, x
, y
, (flags
& ~ETO_OPAQUE
), &rc
,
2113 glyphs
? glyphs
: reordered_str
, count
, (INT
*)deltas
);
2115 ret
= physdev
->funcs
->pExtTextOut( physdev
, x
, y
, (flags
& ~ETO_OPAQUE
), &rc
,
2116 glyphs
? glyphs
: reordered_str
, count
, (INT
*)deltas
);
2120 HeapFree(GetProcessHeap(), 0, deltas
);
2121 if(glyphs
!= reordered_str
)
2122 HeapFree(GetProcessHeap(), 0, glyphs
);
2123 if(reordered_str
!= str
)
2124 HeapFree(GetProcessHeap(), 0, reordered_str
);
2126 release_dc_ptr( dc
);
2128 if (ret
&& (lf
.lfUnderline
|| lf
.lfStrikeOut
))
2130 int underlinePos
, strikeoutPos
;
2131 int underlineWidth
, strikeoutWidth
;
2132 UINT size
= GetOutlineTextMetricsW(hdc
, 0, NULL
);
2133 OUTLINETEXTMETRICW
* otm
= NULL
;
2138 underlineWidth
= tm
.tmAscent
/ 20 + 1;
2139 strikeoutPos
= tm
.tmAscent
/ 2;
2140 strikeoutWidth
= underlineWidth
;
2144 otm
= HeapAlloc(GetProcessHeap(), 0, size
);
2145 GetOutlineTextMetricsW(hdc
, size
, otm
);
2146 underlinePos
= otm
->otmsUnderscorePosition
;
2147 underlineWidth
= otm
->otmsUnderscoreSize
;
2148 strikeoutPos
= otm
->otmsStrikeoutPosition
;
2149 strikeoutWidth
= otm
->otmsStrikeoutSize
;
2150 HeapFree(GetProcessHeap(), 0, otm
);
2153 if (PATH_IsPathOpen(dc
->path
))
2157 HBRUSH hbrush
= CreateSolidBrush(GetTextColor(hdc
));
2159 hbrush
= SelectObject(hdc
, hbrush
);
2160 hpen
= SelectObject(hdc
, GetStockObject(NULL_PEN
));
2164 pts
[0].x
= x
- underlinePos
* sinEsc
;
2165 pts
[0].y
= y
- underlinePos
* cosEsc
;
2166 pts
[1].x
= x
+ width
.x
- underlinePos
* sinEsc
;
2167 pts
[1].y
= y
+ width
.y
- underlinePos
* cosEsc
;
2168 pts
[2].x
= pts
[1].x
+ underlineWidth
* sinEsc
;
2169 pts
[2].y
= pts
[1].y
+ underlineWidth
* cosEsc
;
2170 pts
[3].x
= pts
[0].x
+ underlineWidth
* sinEsc
;
2171 pts
[3].y
= pts
[0].y
+ underlineWidth
* cosEsc
;
2172 pts
[4].x
= pts
[0].x
;
2173 pts
[4].y
= pts
[0].y
;
2174 DPtoLP(hdc
, pts
, 5);
2175 Polygon(hdc
, pts
, 5);
2180 pts
[0].x
= x
- strikeoutPos
* sinEsc
;
2181 pts
[0].y
= y
- strikeoutPos
* cosEsc
;
2182 pts
[1].x
= x
+ width
.x
- strikeoutPos
* sinEsc
;
2183 pts
[1].y
= y
+ width
.y
- strikeoutPos
* cosEsc
;
2184 pts
[2].x
= pts
[1].x
+ strikeoutWidth
* sinEsc
;
2185 pts
[2].y
= pts
[1].y
+ strikeoutWidth
* cosEsc
;
2186 pts
[3].x
= pts
[0].x
+ strikeoutWidth
* sinEsc
;
2187 pts
[3].y
= pts
[0].y
+ strikeoutWidth
* cosEsc
;
2188 pts
[4].x
= pts
[0].x
;
2189 pts
[4].y
= pts
[0].y
;
2190 DPtoLP(hdc
, pts
, 5);
2191 Polygon(hdc
, pts
, 5);
2194 SelectObject(hdc
, hpen
);
2195 hbrush
= SelectObject(hdc
, hbrush
);
2196 DeleteObject(hbrush
);
2200 POINT pts
[2], oldpt
;
2205 hpen
= CreatePen(PS_SOLID
, underlineWidth
, GetTextColor(hdc
));
2206 hpen
= SelectObject(hdc
, hpen
);
2209 pts
[1].x
= x
+ width
.x
;
2210 pts
[1].y
= y
+ width
.y
;
2211 DPtoLP(hdc
, pts
, 2);
2212 MoveToEx(hdc
, pts
[0].x
- underlinePos
* sinEsc
, pts
[0].y
- underlinePos
* cosEsc
, &oldpt
);
2213 LineTo(hdc
, pts
[1].x
- underlinePos
* sinEsc
, pts
[1].y
- underlinePos
* cosEsc
);
2214 MoveToEx(hdc
, oldpt
.x
, oldpt
.y
, NULL
);
2215 DeleteObject(SelectObject(hdc
, hpen
));
2220 hpen
= CreatePen(PS_SOLID
, strikeoutWidth
, GetTextColor(hdc
));
2221 hpen
= SelectObject(hdc
, hpen
);
2224 pts
[1].x
= x
+ width
.x
;
2225 pts
[1].y
= y
+ width
.y
;
2226 DPtoLP(hdc
, pts
, 2);
2227 MoveToEx(hdc
, pts
[0].x
- strikeoutPos
* sinEsc
, pts
[0].y
- strikeoutPos
* cosEsc
, &oldpt
);
2228 LineTo(hdc
, pts
[1].x
- strikeoutPos
* sinEsc
, pts
[1].y
- strikeoutPos
* cosEsc
);
2229 MoveToEx(hdc
, oldpt
.x
, oldpt
.y
, NULL
);
2230 DeleteObject(SelectObject(hdc
, hpen
));
2239 /***********************************************************************
2240 * TextOutA (GDI32.@)
2242 BOOL WINAPI
TextOutA( HDC hdc
, INT x
, INT y
, LPCSTR str
, INT count
)
2244 return ExtTextOutA( hdc
, x
, y
, 0, NULL
, str
, count
, NULL
);
2248 /***********************************************************************
2249 * TextOutW (GDI32.@)
2251 BOOL WINAPI
TextOutW(HDC hdc
, INT x
, INT y
, LPCWSTR str
, INT count
)
2253 return ExtTextOutW( hdc
, x
, y
, 0, NULL
, str
, count
, NULL
);
2257 /***********************************************************************
2258 * PolyTextOutA (GDI32.@)
2262 BOOL WINAPI
PolyTextOutA( HDC hdc
, const POLYTEXTA
*pptxt
, INT cStrings
)
2264 for (; cStrings
>0; cStrings
--, pptxt
++)
2265 if (!ExtTextOutA( hdc
, pptxt
->x
, pptxt
->y
, pptxt
->uiFlags
, &pptxt
->rcl
, pptxt
->lpstr
, pptxt
->n
, pptxt
->pdx
))
2272 /***********************************************************************
2273 * PolyTextOutW (GDI32.@)
2275 * Draw several Strings
2281 BOOL WINAPI
PolyTextOutW( HDC hdc
, const POLYTEXTW
*pptxt
, INT cStrings
)
2283 for (; cStrings
>0; cStrings
--, pptxt
++)
2284 if (!ExtTextOutW( hdc
, pptxt
->x
, pptxt
->y
, pptxt
->uiFlags
, &pptxt
->rcl
, pptxt
->lpstr
, pptxt
->n
, pptxt
->pdx
))
2290 /***********************************************************************
2291 * SetMapperFlags (GDI32.@)
2293 DWORD WINAPI
SetMapperFlags( HDC hdc
, DWORD flags
)
2295 DC
*dc
= get_dc_ptr( hdc
);
2296 DWORD ret
= GDI_ERROR
;
2300 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetMapperFlags
);
2301 flags
= physdev
->funcs
->pSetMapperFlags( physdev
, flags
);
2302 if (flags
!= GDI_ERROR
)
2304 ret
= dc
->mapperFlags
;
2305 dc
->mapperFlags
= flags
;
2307 release_dc_ptr( dc
);
2312 /***********************************************************************
2313 * GetAspectRatioFilterEx (GDI32.@)
2315 BOOL WINAPI
GetAspectRatioFilterEx( HDC hdc
, LPSIZE pAspectRatio
)
2317 FIXME("(%p, %p): -- Empty Stub !\n", hdc
, pAspectRatio
);
2322 /***********************************************************************
2323 * GetCharABCWidthsA (GDI32.@)
2325 * See GetCharABCWidthsW.
2327 BOOL WINAPI
GetCharABCWidthsA(HDC hdc
, UINT firstChar
, UINT lastChar
,
2335 str
= FONT_GetCharsByRangeA(hdc
, firstChar
, lastChar
, &i
);
2339 wstr
= FONT_mbtowc(hdc
, str
, i
, &wlen
, NULL
);
2342 HeapFree(GetProcessHeap(), 0, str
);
2346 for(i
= 0; i
< wlen
; i
++)
2348 if(!GetCharABCWidthsW(hdc
, wstr
[i
], wstr
[i
], abc
))
2356 HeapFree(GetProcessHeap(), 0, str
);
2357 HeapFree(GetProcessHeap(), 0, wstr
);
2363 /******************************************************************************
2364 * GetCharABCWidthsW [GDI32.@]
2366 * Retrieves widths of characters in range.
2369 * hdc [I] Handle of device context
2370 * firstChar [I] First character in range to query
2371 * lastChar [I] Last character in range to query
2372 * abc [O] Address of character-width structure
2375 * Only works with TrueType fonts
2381 BOOL WINAPI
GetCharABCWidthsW( HDC hdc
, UINT firstChar
, UINT lastChar
,
2384 DC
*dc
= get_dc_ptr(hdc
);
2389 if (!dc
) return FALSE
;
2393 release_dc_ptr( dc
);
2397 dev
= GET_DC_PHYSDEV( dc
, pGetCharABCWidths
);
2398 ret
= dev
->funcs
->pGetCharABCWidths( dev
, firstChar
, lastChar
, abc
);
2401 /* convert device units to logical */
2402 for( i
= firstChar
; i
<= lastChar
; 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
);
2409 release_dc_ptr( dc
);
2414 /******************************************************************************
2415 * GetCharABCWidthsI [GDI32.@]
2417 * Retrieves widths of characters in range.
2420 * hdc [I] Handle of device context
2421 * firstChar [I] First glyphs in range to query
2422 * count [I] Last glyphs in range to query
2423 * pgi [i] Array of glyphs to query
2424 * abc [O] Address of character-width structure
2427 * Only works with TrueType fonts
2433 BOOL WINAPI
GetCharABCWidthsI( HDC hdc
, UINT firstChar
, UINT count
,
2434 LPWORD pgi
, LPABC abc
)
2436 DC
*dc
= get_dc_ptr(hdc
);
2440 if (!dc
) return FALSE
;
2444 release_dc_ptr( dc
);
2449 ret
= WineEngGetCharABCWidthsI( dc
->gdiFont
, firstChar
, count
, pgi
, abc
);
2455 /* convert device units to logical */
2456 for( i
= 0; i
< count
; i
++, abc
++ ) {
2457 abc
->abcA
= INTERNAL_XDSTOWS(dc
, abc
->abcA
);
2458 abc
->abcB
= INTERNAL_XDSTOWS(dc
, abc
->abcB
);
2459 abc
->abcC
= INTERNAL_XDSTOWS(dc
, abc
->abcC
);
2464 release_dc_ptr( dc
);
2469 /***********************************************************************
2470 * GetGlyphOutlineA (GDI32.@)
2472 DWORD WINAPI
GetGlyphOutlineA( HDC hdc
, UINT uChar
, UINT fuFormat
,
2473 LPGLYPHMETRICS lpgm
, DWORD cbBuffer
,
2474 LPVOID lpBuffer
, const MAT2
*lpmat2
)
2476 if (!lpmat2
) return GDI_ERROR
;
2478 if(!(fuFormat
& GGO_GLYPH_INDEX
)) {
2483 cp
= GdiGetCodePage(hdc
);
2484 if (IsDBCSLeadByteEx(cp
, uChar
>> 8)) {
2486 mbchs
[0] = (uChar
& 0xff00) >> 8;
2487 mbchs
[1] = (uChar
& 0xff);
2490 mbchs
[0] = (uChar
& 0xff);
2493 MultiByteToWideChar(cp
, 0, mbchs
, len
, (LPWSTR
)&uChar
, 1);
2496 return GetGlyphOutlineW(hdc
, uChar
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
,
2500 /***********************************************************************
2501 * GetGlyphOutlineW (GDI32.@)
2503 DWORD WINAPI
GetGlyphOutlineW( HDC hdc
, UINT uChar
, UINT fuFormat
,
2504 LPGLYPHMETRICS lpgm
, DWORD cbBuffer
,
2505 LPVOID lpBuffer
, const MAT2
*lpmat2
)
2510 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2511 hdc
, uChar
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
, lpmat2
);
2513 if (!lpmat2
) return GDI_ERROR
;
2515 dc
= get_dc_ptr(hdc
);
2516 if(!dc
) return GDI_ERROR
;
2519 ret
= WineEngGetGlyphOutline(dc
->gdiFont
, uChar
, fuFormat
, lpgm
,
2520 cbBuffer
, lpBuffer
, lpmat2
);
2524 release_dc_ptr( dc
);
2529 /***********************************************************************
2530 * CreateScalableFontResourceA (GDI32.@)
2532 BOOL WINAPI
CreateScalableFontResourceA( DWORD fHidden
,
2533 LPCSTR lpszResourceFile
,
2534 LPCSTR lpszFontFile
,
2535 LPCSTR lpszCurrentPath
)
2537 LPWSTR lpszResourceFileW
= NULL
;
2538 LPWSTR lpszFontFileW
= NULL
;
2539 LPWSTR lpszCurrentPathW
= NULL
;
2543 if (lpszResourceFile
)
2545 len
= MultiByteToWideChar(CP_ACP
, 0, lpszResourceFile
, -1, NULL
, 0);
2546 lpszResourceFileW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2547 MultiByteToWideChar(CP_ACP
, 0, lpszResourceFile
, -1, lpszResourceFileW
, len
);
2552 len
= MultiByteToWideChar(CP_ACP
, 0, lpszFontFile
, -1, NULL
, 0);
2553 lpszFontFileW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2554 MultiByteToWideChar(CP_ACP
, 0, lpszFontFile
, -1, lpszFontFileW
, len
);
2557 if (lpszCurrentPath
)
2559 len
= MultiByteToWideChar(CP_ACP
, 0, lpszCurrentPath
, -1, NULL
, 0);
2560 lpszCurrentPathW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2561 MultiByteToWideChar(CP_ACP
, 0, lpszCurrentPath
, -1, lpszCurrentPathW
, len
);
2564 ret
= CreateScalableFontResourceW(fHidden
, lpszResourceFileW
,
2565 lpszFontFileW
, lpszCurrentPathW
);
2567 HeapFree(GetProcessHeap(), 0, lpszResourceFileW
);
2568 HeapFree(GetProcessHeap(), 0, lpszFontFileW
);
2569 HeapFree(GetProcessHeap(), 0, lpszCurrentPathW
);
2574 /***********************************************************************
2575 * CreateScalableFontResourceW (GDI32.@)
2577 BOOL WINAPI
CreateScalableFontResourceW( DWORD fHidden
,
2578 LPCWSTR lpszResourceFile
,
2579 LPCWSTR lpszFontFile
,
2580 LPCWSTR lpszCurrentPath
)
2583 FIXME("(%d,%s,%s,%s): stub\n",
2584 fHidden
, debugstr_w(lpszResourceFile
), debugstr_w(lpszFontFile
),
2585 debugstr_w(lpszCurrentPath
) );
2587 /* fHidden=1 - only visible for the calling app, read-only, not
2588 * enumerated with EnumFonts/EnumFontFamilies
2589 * lpszCurrentPath can be NULL
2592 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2593 if ((f
= CreateFileW(lpszResourceFile
, 0, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, 0)) != INVALID_HANDLE_VALUE
) {
2595 SetLastError(ERROR_FILE_EXISTS
);
2598 return FALSE
; /* create failed */
2601 /*************************************************************************
2602 * GetKerningPairsA (GDI32.@)
2604 DWORD WINAPI
GetKerningPairsA( HDC hDC
, DWORD cPairs
,
2605 LPKERNINGPAIR kern_pairA
)
2609 DWORD i
, total_kern_pairs
, kern_pairs_copied
= 0;
2610 KERNINGPAIR
*kern_pairW
;
2612 if (!cPairs
&& kern_pairA
)
2614 SetLastError(ERROR_INVALID_PARAMETER
);
2618 cp
= GdiGetCodePage(hDC
);
2620 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2621 * to fail on an invalid character for CP_SYMBOL.
2623 cpi
.DefaultChar
[0] = 0;
2624 if (cp
!= CP_SYMBOL
&& !GetCPInfo(cp
, &cpi
))
2626 FIXME("Can't find codepage %u info\n", cp
);
2630 total_kern_pairs
= GetKerningPairsW(hDC
, 0, NULL
);
2631 if (!total_kern_pairs
) return 0;
2633 kern_pairW
= HeapAlloc(GetProcessHeap(), 0, total_kern_pairs
* sizeof(*kern_pairW
));
2634 GetKerningPairsW(hDC
, total_kern_pairs
, kern_pairW
);
2636 for (i
= 0; i
< total_kern_pairs
; i
++)
2640 if (!WideCharToMultiByte(cp
, 0, &kern_pairW
[i
].wFirst
, 1, &first
, 1, NULL
, NULL
))
2643 if (!WideCharToMultiByte(cp
, 0, &kern_pairW
[i
].wSecond
, 1, &second
, 1, NULL
, NULL
))
2646 if (first
== cpi
.DefaultChar
[0] || second
== cpi
.DefaultChar
[0])
2651 if (kern_pairs_copied
>= cPairs
) break;
2653 kern_pairA
->wFirst
= (BYTE
)first
;
2654 kern_pairA
->wSecond
= (BYTE
)second
;
2655 kern_pairA
->iKernAmount
= kern_pairW
[i
].iKernAmount
;
2658 kern_pairs_copied
++;
2661 HeapFree(GetProcessHeap(), 0, kern_pairW
);
2663 return kern_pairs_copied
;
2666 /*************************************************************************
2667 * GetKerningPairsW (GDI32.@)
2669 DWORD WINAPI
GetKerningPairsW( HDC hDC
, DWORD cPairs
,
2670 LPKERNINGPAIR lpKerningPairs
)
2675 TRACE("(%p,%d,%p)\n", hDC
, cPairs
, lpKerningPairs
);
2677 if (!cPairs
&& lpKerningPairs
)
2679 SetLastError(ERROR_INVALID_PARAMETER
);
2683 dc
= get_dc_ptr(hDC
);
2687 ret
= WineEngGetKerningPairs(dc
->gdiFont
, cPairs
, lpKerningPairs
);
2689 release_dc_ptr( dc
);
2693 /*************************************************************************
2694 * TranslateCharsetInfo [GDI32.@]
2696 * Fills a CHARSETINFO structure for a character set, code page, or
2697 * font. This allows making the correspondence between different labels
2698 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2699 * of the same encoding.
2701 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2702 * only one codepage should be set in *lpSrc.
2705 * TRUE on success, FALSE on failure.
2708 BOOL WINAPI
TranslateCharsetInfo(
2709 LPDWORD lpSrc
, /* [in]
2710 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2711 if flags == TCI_SRCCHARSET: a character set value
2712 if flags == TCI_SRCCODEPAGE: a code page value
2714 LPCHARSETINFO lpCs
, /* [out] structure to receive charset information */
2715 DWORD flags
/* [in] determines interpretation of lpSrc */)
2719 case TCI_SRCFONTSIG
:
2720 while (index
< MAXTCIINDEX
&& !(*lpSrc
>>index
& 0x0001)) index
++;
2722 case TCI_SRCCODEPAGE
:
2723 while (index
< MAXTCIINDEX
&& PtrToUlong(lpSrc
) != FONT_tci
[index
].ciACP
) index
++;
2725 case TCI_SRCCHARSET
:
2726 while (index
< MAXTCIINDEX
&& PtrToUlong(lpSrc
) != FONT_tci
[index
].ciCharset
) index
++;
2731 if (index
>= MAXTCIINDEX
|| FONT_tci
[index
].ciCharset
== DEFAULT_CHARSET
) return FALSE
;
2732 *lpCs
= FONT_tci
[index
];
2736 /*************************************************************************
2737 * GetFontLanguageInfo (GDI32.@)
2739 DWORD WINAPI
GetFontLanguageInfo(HDC hdc
)
2741 FONTSIGNATURE fontsig
;
2742 static const DWORD GCP_DBCS_MASK
=0x003F0000,
2743 GCP_DIACRITIC_MASK
=0x00000000,
2744 FLI_GLYPHS_MASK
=0x00000000,
2745 GCP_GLYPHSHAPE_MASK
=0x00000040,
2746 GCP_KASHIDA_MASK
=0x00000000,
2747 GCP_LIGATE_MASK
=0x00000000,
2748 GCP_USEKERNING_MASK
=0x00000000,
2749 GCP_REORDER_MASK
=0x00000060;
2753 GetTextCharsetInfo( hdc
, &fontsig
, 0 );
2754 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2756 if( (fontsig
.fsCsb
[0]&GCP_DBCS_MASK
)!=0 )
2759 if( (fontsig
.fsCsb
[0]&GCP_DIACRITIC_MASK
)!=0 )
2760 result
|=GCP_DIACRITIC
;
2762 if( (fontsig
.fsCsb
[0]&FLI_GLYPHS_MASK
)!=0 )
2765 if( (fontsig
.fsCsb
[0]&GCP_GLYPHSHAPE_MASK
)!=0 )
2766 result
|=GCP_GLYPHSHAPE
;
2768 if( (fontsig
.fsCsb
[0]&GCP_KASHIDA_MASK
)!=0 )
2769 result
|=GCP_KASHIDA
;
2771 if( (fontsig
.fsCsb
[0]&GCP_LIGATE_MASK
)!=0 )
2774 if( (fontsig
.fsCsb
[0]&GCP_USEKERNING_MASK
)!=0 )
2775 result
|=GCP_USEKERNING
;
2777 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2778 if( GetTextAlign( hdc
) & TA_RTLREADING
)
2779 if( (fontsig
.fsCsb
[0]&GCP_REORDER_MASK
)!=0 )
2780 result
|=GCP_REORDER
;
2786 /*************************************************************************
2787 * GetFontData [GDI32.@]
2789 * Retrieve data for TrueType font.
2793 * success: Number of bytes returned
2794 * failure: GDI_ERROR
2798 * Calls SetLastError()
2801 DWORD WINAPI
GetFontData(HDC hdc
, DWORD table
, DWORD offset
,
2802 LPVOID buffer
, DWORD length
)
2804 DC
*dc
= get_dc_ptr(hdc
);
2805 DWORD ret
= GDI_ERROR
;
2807 if(!dc
) return GDI_ERROR
;
2810 ret
= WineEngGetFontData(dc
->gdiFont
, table
, offset
, buffer
, length
);
2812 release_dc_ptr( dc
);
2816 /*************************************************************************
2817 * GetGlyphIndicesA [GDI32.@]
2819 DWORD WINAPI
GetGlyphIndicesA(HDC hdc
, LPCSTR lpstr
, INT count
,
2820 LPWORD pgi
, DWORD flags
)
2826 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2827 hdc
, debugstr_an(lpstr
, count
), count
, pgi
, flags
);
2829 lpstrW
= FONT_mbtowc(hdc
, lpstr
, count
, &countW
, NULL
);
2830 ret
= GetGlyphIndicesW(hdc
, lpstrW
, countW
, pgi
, flags
);
2831 HeapFree(GetProcessHeap(), 0, lpstrW
);
2836 /*************************************************************************
2837 * GetGlyphIndicesW [GDI32.@]
2839 DWORD WINAPI
GetGlyphIndicesW(HDC hdc
, LPCWSTR lpstr
, INT count
,
2840 LPWORD pgi
, DWORD flags
)
2842 DC
*dc
= get_dc_ptr(hdc
);
2843 DWORD ret
= GDI_ERROR
;
2845 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2846 hdc
, debugstr_wn(lpstr
, count
), count
, pgi
, flags
);
2848 if(!dc
) return GDI_ERROR
;
2851 ret
= WineEngGetGlyphIndices(dc
->gdiFont
, lpstr
, count
, pgi
, flags
);
2853 release_dc_ptr( dc
);
2857 /*************************************************************************
2858 * GetCharacterPlacementA [GDI32.@]
2860 * See GetCharacterPlacementW.
2863 * the web browser control of ie4 calls this with dwFlags=0
2866 GetCharacterPlacementA(HDC hdc
, LPCSTR lpString
, INT uCount
,
2867 INT nMaxExtent
, GCP_RESULTSA
*lpResults
,
2872 GCP_RESULTSW resultsW
;
2876 TRACE("%s, %d, %d, 0x%08x\n",
2877 debugstr_an(lpString
, uCount
), uCount
, nMaxExtent
, dwFlags
);
2879 /* both structs are equal in size */
2880 memcpy(&resultsW
, lpResults
, sizeof(resultsW
));
2882 lpStringW
= FONT_mbtowc(hdc
, lpString
, uCount
, &uCountW
, &font_cp
);
2883 if(lpResults
->lpOutString
)
2884 resultsW
.lpOutString
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*uCountW
);
2886 ret
= GetCharacterPlacementW(hdc
, lpStringW
, uCountW
, nMaxExtent
, &resultsW
, dwFlags
);
2888 lpResults
->nGlyphs
= resultsW
.nGlyphs
;
2889 lpResults
->nMaxFit
= resultsW
.nMaxFit
;
2891 if(lpResults
->lpOutString
) {
2892 WideCharToMultiByte(font_cp
, 0, resultsW
.lpOutString
, uCountW
,
2893 lpResults
->lpOutString
, uCount
, NULL
, NULL
);
2896 HeapFree(GetProcessHeap(), 0, lpStringW
);
2897 HeapFree(GetProcessHeap(), 0, resultsW
.lpOutString
);
2902 /*************************************************************************
2903 * GetCharacterPlacementW [GDI32.@]
2905 * Retrieve information about a string. This includes the width, reordering,
2906 * Glyphing and so on.
2910 * The width and height of the string if successful, 0 if failed.
2914 * All flags except GCP_REORDER are not yet implemented.
2915 * Reordering is not 100% compliant to the Windows BiDi method.
2916 * Caret positioning is not yet implemented for BiDi.
2917 * Classes are not yet implemented.
2921 GetCharacterPlacementW(
2922 HDC hdc
, /* [in] Device context for which the rendering is to be done */
2923 LPCWSTR lpString
, /* [in] The string for which information is to be returned */
2924 INT uCount
, /* [in] Number of WORDS in string. */
2925 INT nMaxExtent
, /* [in] Maximum extent the string is to take (in HDC logical units) */
2926 GCP_RESULTSW
*lpResults
,/* [in/out] A pointer to a GCP_RESULTSW struct */
2927 DWORD dwFlags
/* [in] Flags specifying how to process the string */
2934 TRACE("%s, %d, %d, 0x%08x\n",
2935 debugstr_wn(lpString
, uCount
), uCount
, nMaxExtent
, dwFlags
);
2937 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2938 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2939 lpResults
->lStructSize
, lpResults
->lpOutString
, lpResults
->lpOrder
,
2940 lpResults
->lpDx
, lpResults
->lpCaretPos
, lpResults
->lpClass
,
2941 lpResults
->lpGlyphs
, lpResults
->nGlyphs
, lpResults
->nMaxFit
);
2943 if(dwFlags
&(~GCP_REORDER
)) FIXME("flags 0x%08x ignored\n", dwFlags
);
2944 if(lpResults
->lpClass
) FIXME("classes not implemented\n");
2945 if (lpResults
->lpCaretPos
&& (dwFlags
& GCP_REORDER
))
2946 FIXME("Caret positions for complex scripts not implemented\n");
2948 nSet
= (UINT
)uCount
;
2949 if(nSet
> lpResults
->nGlyphs
)
2950 nSet
= lpResults
->nGlyphs
;
2952 /* return number of initialized fields */
2953 lpResults
->nGlyphs
= nSet
;
2955 if((dwFlags
&GCP_REORDER
)==0 )
2957 /* Treat the case where no special handling was requested in a fastpath way */
2958 /* copy will do if the GCP_REORDER flag is not set */
2959 if(lpResults
->lpOutString
)
2960 memcpy( lpResults
->lpOutString
, lpString
, nSet
* sizeof(WCHAR
));
2962 if(lpResults
->lpOrder
)
2964 for(i
= 0; i
< nSet
; i
++)
2965 lpResults
->lpOrder
[i
] = i
;
2969 BIDI_Reorder(NULL
, lpString
, uCount
, dwFlags
, WINE_GCPW_FORCE_LTR
, lpResults
->lpOutString
,
2970 nSet
, lpResults
->lpOrder
, NULL
, NULL
);
2973 /* FIXME: Will use the placement chars */
2974 if (lpResults
->lpDx
)
2977 for (i
= 0; i
< nSet
; i
++)
2979 if (GetCharWidth32W(hdc
, lpString
[i
], lpString
[i
], &c
))
2980 lpResults
->lpDx
[i
]= c
;
2984 if (lpResults
->lpCaretPos
&& !(dwFlags
& GCP_REORDER
))
2988 lpResults
->lpCaretPos
[0] = 0;
2989 for (i
= 1; i
< nSet
; i
++)
2990 if (GetTextExtentPoint32W(hdc
, &(lpString
[i
- 1]), 1, &size
))
2991 lpResults
->lpCaretPos
[i
] = (pos
+= size
.cx
);
2994 if(lpResults
->lpGlyphs
)
2995 GetGlyphIndicesW(hdc
, lpString
, nSet
, lpResults
->lpGlyphs
, 0);
2997 if (GetTextExtentPoint32W(hdc
, lpString
, uCount
, &size
))
2998 ret
= MAKELONG(size
.cx
, size
.cy
);
3003 /*************************************************************************
3004 * GetCharABCWidthsFloatA [GDI32.@]
3006 * See GetCharABCWidthsFloatW.
3008 BOOL WINAPI
GetCharABCWidthsFloatA( HDC hdc
, UINT first
, UINT last
, LPABCFLOAT abcf
)
3015 str
= FONT_GetCharsByRangeA(hdc
, first
, last
, &i
);
3019 wstr
= FONT_mbtowc( hdc
, str
, i
, &wlen
, NULL
);
3021 for (i
= 0; i
< wlen
; i
++)
3023 if (!GetCharABCWidthsFloatW( hdc
, wstr
[i
], wstr
[i
], abcf
))
3031 HeapFree( GetProcessHeap(), 0, str
);
3032 HeapFree( GetProcessHeap(), 0, wstr
);
3037 /*************************************************************************
3038 * GetCharABCWidthsFloatW [GDI32.@]
3040 * Retrieves widths of a range of characters.
3043 * hdc [I] Handle to device context.
3044 * first [I] First character in range to query.
3045 * last [I] Last character in range to query.
3046 * abcf [O] Array of LPABCFLOAT structures.
3052 BOOL WINAPI
GetCharABCWidthsFloatW( HDC hdc
, UINT first
, UINT last
, LPABCFLOAT abcf
)
3056 DC
*dc
= get_dc_ptr( hdc
);
3058 TRACE("%p, %d, %d, %p\n", hdc
, first
, last
, abcf
);
3060 if (!dc
) return FALSE
;
3064 release_dc_ptr( dc
);
3069 ret
= WineEngGetCharABCWidthsFloat( dc
->gdiFont
, first
, last
, abcf
);
3075 /* convert device units to logical */
3076 for (i
= first
; i
<= last
; i
++, abcf
++)
3078 abcf
->abcfA
= abcf
->abcfA
* dc
->xformVport2World
.eM11
;
3079 abcf
->abcfB
= abcf
->abcfB
* dc
->xformVport2World
.eM11
;
3080 abcf
->abcfC
= abcf
->abcfC
* dc
->xformVport2World
.eM11
;
3084 release_dc_ptr( dc
);
3088 /*************************************************************************
3089 * GetCharWidthFloatA [GDI32.@]
3091 BOOL WINAPI
GetCharWidthFloatA(HDC hdc
, UINT iFirstChar
,
3092 UINT iLastChar
, PFLOAT pxBuffer
)
3094 FIXME("%p, %u, %u, %p: stub!\n", hdc
, iFirstChar
, iLastChar
, pxBuffer
);
3098 /*************************************************************************
3099 * GetCharWidthFloatW [GDI32.@]
3101 BOOL WINAPI
GetCharWidthFloatW(HDC hdc
, UINT iFirstChar
,
3102 UINT iLastChar
, PFLOAT pxBuffer
)
3104 FIXME("%p, %u, %u, %p: stub!\n", hdc
, iFirstChar
, iLastChar
, pxBuffer
);
3109 /***********************************************************************
3111 * Font Resource API *
3113 ***********************************************************************/
3115 /***********************************************************************
3116 * AddFontResourceA (GDI32.@)
3118 INT WINAPI
AddFontResourceA( LPCSTR str
)
3120 return AddFontResourceExA( str
, 0, NULL
);
3123 /***********************************************************************
3124 * AddFontResourceW (GDI32.@)
3126 INT WINAPI
AddFontResourceW( LPCWSTR str
)
3128 return AddFontResourceExW(str
, 0, NULL
);
3132 /***********************************************************************
3133 * AddFontResourceExA (GDI32.@)
3135 INT WINAPI
AddFontResourceExA( LPCSTR str
, DWORD fl
, PVOID pdv
)
3137 DWORD len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
3138 LPWSTR strW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3141 MultiByteToWideChar(CP_ACP
, 0, str
, -1, strW
, len
);
3142 ret
= AddFontResourceExW(strW
, fl
, pdv
);
3143 HeapFree(GetProcessHeap(), 0, strW
);
3147 static BOOL CALLBACK
load_enumed_resource(HMODULE hModule
, LPCWSTR type
, LPWSTR name
, LONG_PTR lParam
)
3149 HRSRC rsrc
= FindResourceW(hModule
, name
, type
);
3150 HGLOBAL hMem
= LoadResource(hModule
, rsrc
);
3151 LPVOID
*pMem
= LockResource(hMem
);
3152 int *num_total
= (int *)lParam
;
3155 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type
));
3156 if (!AddFontMemResourceEx(pMem
, SizeofResource(hModule
, rsrc
), NULL
, &num_in_res
))
3158 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule
, hMem
);
3162 *num_total
+= num_in_res
;
3166 /***********************************************************************
3167 * AddFontResourceExW (GDI32.@)
3169 INT WINAPI
AddFontResourceExW( LPCWSTR str
, DWORD fl
, PVOID pdv
)
3171 int ret
= WineEngAddFontResourceEx(str
, fl
, pdv
);
3174 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3175 HMODULE hModule
= LoadLibraryExW(str
, NULL
, LOAD_LIBRARY_AS_DATAFILE
);
3176 if (hModule
!= NULL
)
3178 int num_resources
= 0;
3179 LPWSTR rt_font
= (LPWSTR
)((ULONG_PTR
)8); /* we don't want to include winuser.h */
3181 TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3182 wine_dbgstr_w(str
));
3183 if (EnumResourceNamesW(hModule
, rt_font
, load_enumed_resource
, (LONG_PTR
)&num_resources
))
3184 ret
= num_resources
;
3185 FreeLibrary(hModule
);
3191 /***********************************************************************
3192 * RemoveFontResourceA (GDI32.@)
3194 BOOL WINAPI
RemoveFontResourceA( LPCSTR str
)
3196 return RemoveFontResourceExA(str
, 0, 0);
3199 /***********************************************************************
3200 * RemoveFontResourceW (GDI32.@)
3202 BOOL WINAPI
RemoveFontResourceW( LPCWSTR str
)
3204 return RemoveFontResourceExW(str
, 0, 0);
3207 /***********************************************************************
3208 * AddFontMemResourceEx (GDI32.@)
3210 HANDLE WINAPI
AddFontMemResourceEx( PVOID pbFont
, DWORD cbFont
, PVOID pdv
, DWORD
*pcFonts
)
3215 if (!pbFont
|| !cbFont
|| !pcFonts
)
3217 SetLastError(ERROR_INVALID_PARAMETER
);
3221 ret
= WineEngAddFontMemResourceEx(pbFont
, cbFont
, pdv
, &num_fonts
);
3226 *pcFonts
= num_fonts
;
3230 WARN("page fault while writing to *pcFonts (%p)\n", pcFonts
);
3231 RemoveFontMemResourceEx(ret
);
3239 /***********************************************************************
3240 * RemoveFontMemResourceEx (GDI32.@)
3242 BOOL WINAPI
RemoveFontMemResourceEx( HANDLE fh
)
3244 FIXME("(%p) stub\n", fh
);
3248 /***********************************************************************
3249 * RemoveFontResourceExA (GDI32.@)
3251 BOOL WINAPI
RemoveFontResourceExA( LPCSTR str
, DWORD fl
, PVOID pdv
)
3253 DWORD len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
3254 LPWSTR strW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3257 MultiByteToWideChar(CP_ACP
, 0, str
, -1, strW
, len
);
3258 ret
= RemoveFontResourceExW(strW
, fl
, pdv
);
3259 HeapFree(GetProcessHeap(), 0, strW
);
3263 /***********************************************************************
3264 * RemoveFontResourceExW (GDI32.@)
3266 BOOL WINAPI
RemoveFontResourceExW( LPCWSTR str
, DWORD fl
, PVOID pdv
)
3268 return WineEngRemoveFontResourceEx(str
, fl
, pdv
);
3271 /***********************************************************************
3272 * GetTextCharset (GDI32.@)
3274 UINT WINAPI
GetTextCharset(HDC hdc
)
3276 /* MSDN docs say this is equivalent */
3277 return GetTextCharsetInfo(hdc
, NULL
, 0);
3280 /***********************************************************************
3281 * GetTextCharsetInfo (GDI32.@)
3283 UINT WINAPI
GetTextCharsetInfo(HDC hdc
, LPFONTSIGNATURE fs
, DWORD flags
)
3285 UINT ret
= DEFAULT_CHARSET
;
3286 DC
*dc
= get_dc_ptr(hdc
);
3291 ret
= WineEngGetTextCharsetInfo(dc
->gdiFont
, fs
, flags
);
3293 release_dc_ptr( dc
);
3296 if (ret
== DEFAULT_CHARSET
&& fs
)
3297 memset(fs
, 0, sizeof(FONTSIGNATURE
));
3301 /***********************************************************************
3302 * GdiGetCharDimensions (GDI32.@)
3304 * Gets the average width of the characters in the English alphabet.
3307 * hdc [I] Handle to the device context to measure on.
3308 * lptm [O] Pointer to memory to store the text metrics into.
3309 * height [O] On exit, the maximum height of characters in the English alphabet.
3312 * The average width of characters in the English alphabet.
3315 * This function is used by the dialog manager to get the size of a dialog
3316 * unit. It should also be used by other pieces of code that need to know
3317 * the size of a dialog unit in logical units without having access to the
3318 * window handle of the dialog.
3319 * Windows caches the font metrics from this function, but we don't and
3320 * there doesn't appear to be an immediate advantage to do so.
3323 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3325 LONG WINAPI
GdiGetCharDimensions(HDC hdc
, LPTEXTMETRICW lptm
, LONG
*height
)
3328 static const WCHAR alphabet
[] = {
3329 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3330 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3331 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3333 if(lptm
&& !GetTextMetricsW(hdc
, lptm
)) return 0;
3335 if(!GetTextExtentPointW(hdc
, alphabet
, 52, &sz
)) return 0;
3337 if (height
) *height
= sz
.cy
;
3338 return (sz
.cx
/ 26 + 1) / 2;
3341 BOOL WINAPI
EnableEUDC(BOOL fEnableEUDC
)
3343 FIXME("(%d): stub\n", fEnableEUDC
);
3347 /***********************************************************************
3348 * GetCharWidthI (GDI32.@)
3350 * Retrieve widths of characters.
3353 * hdc [I] Handle to a device context.
3354 * first [I] First glyph in range to query.
3355 * count [I] Number of glyph indices to query.
3356 * glyphs [I] Array of glyphs to query.
3357 * buffer [O] Buffer to receive character widths.
3360 * Only works with TrueType fonts.
3366 BOOL WINAPI
GetCharWidthI(HDC hdc
, UINT first
, UINT count
, LPWORD glyphs
, LPINT buffer
)
3371 TRACE("(%p, %d, %d, %p, %p)\n", hdc
, first
, count
, glyphs
, buffer
);
3373 if (!(abc
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(ABC
))))
3376 if (!GetCharABCWidthsI(hdc
, first
, count
, glyphs
, abc
))
3378 HeapFree(GetProcessHeap(), 0, abc
);
3382 for (i
= 0; i
< count
; i
++)
3383 buffer
[i
] = abc
->abcA
+ abc
->abcB
+ abc
->abcC
;
3385 HeapFree(GetProcessHeap(), 0, abc
);
3389 /***********************************************************************
3390 * GetFontUnicodeRanges (GDI32.@)
3392 * Retrieve a list of supported Unicode characters in a font.
3395 * hdc [I] Handle to a device context.
3396 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3399 * Success: Number of bytes written to the buffer pointed to by lpgs.
3403 DWORD WINAPI
GetFontUnicodeRanges(HDC hdc
, LPGLYPHSET lpgs
)
3406 DC
*dc
= get_dc_ptr(hdc
);
3408 TRACE("(%p, %p)\n", hdc
, lpgs
);
3412 if (dc
->gdiFont
) ret
= WineEngGetFontUnicodeRanges(dc
->gdiFont
, lpgs
);
3418 /*************************************************************
3419 * FontIsLinked (GDI32.@)
3421 BOOL WINAPI
FontIsLinked(HDC hdc
)
3423 DC
*dc
= get_dc_ptr(hdc
);
3426 if (!dc
) return FALSE
;
3427 if (dc
->gdiFont
) ret
= WineEngFontIsLinked(dc
->gdiFont
);
3429 TRACE("returning %d\n", ret
);
3433 /*************************************************************
3434 * GdiRealizationInfo (GDI32.@)
3436 * Returns a structure that contains some font information.
3438 BOOL WINAPI
GdiRealizationInfo(HDC hdc
, realization_info_t
*info
)
3440 DC
*dc
= get_dc_ptr(hdc
);
3443 if (!dc
) return FALSE
;
3444 if (dc
->gdiFont
) ret
= WineEngRealizationInfo(dc
->gdiFont
, info
);