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
;
1456 TRACE("(%p,%d,%p)\n", hdc
, cbData
, lpOTM
);
1459 dev
= GET_DC_PHYSDEV( dc
, pGetOutlineTextMetrics
);
1460 ret
= dev
->funcs
->pGetOutlineTextMetrics( dev
, cbData
, output
);
1462 if (lpOTM
&& ret
> cbData
)
1464 output
= HeapAlloc(GetProcessHeap(), 0, ret
);
1465 ret
= dev
->funcs
->pGetOutlineTextMetrics( dev
, ret
, output
);
1470 output
->otmTextMetrics
.tmDigitizedAspectX
= GetDeviceCaps(hdc
, LOGPIXELSX
);
1471 output
->otmTextMetrics
.tmDigitizedAspectY
= GetDeviceCaps(hdc
, LOGPIXELSY
);
1473 #define WDPTOLP(x) ((x<0)? \
1474 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1475 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1476 #define HDPTOLP(y) ((y<0)? \
1477 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1478 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1480 output
->otmTextMetrics
.tmHeight
= HDPTOLP(output
->otmTextMetrics
.tmHeight
);
1481 output
->otmTextMetrics
.tmAscent
= HDPTOLP(output
->otmTextMetrics
.tmAscent
);
1482 output
->otmTextMetrics
.tmDescent
= HDPTOLP(output
->otmTextMetrics
.tmDescent
);
1483 output
->otmTextMetrics
.tmInternalLeading
= HDPTOLP(output
->otmTextMetrics
.tmInternalLeading
);
1484 output
->otmTextMetrics
.tmExternalLeading
= HDPTOLP(output
->otmTextMetrics
.tmExternalLeading
);
1485 output
->otmTextMetrics
.tmAveCharWidth
= WDPTOLP(output
->otmTextMetrics
.tmAveCharWidth
);
1486 output
->otmTextMetrics
.tmMaxCharWidth
= WDPTOLP(output
->otmTextMetrics
.tmMaxCharWidth
);
1487 output
->otmTextMetrics
.tmOverhang
= WDPTOLP(output
->otmTextMetrics
.tmOverhang
);
1488 output
->otmAscent
= HDPTOLP(output
->otmAscent
);
1489 output
->otmDescent
= HDPTOLP(output
->otmDescent
);
1490 output
->otmLineGap
= abs(INTERNAL_YDSTOWS(dc
,output
->otmLineGap
));
1491 output
->otmsCapEmHeight
= abs(INTERNAL_YDSTOWS(dc
,output
->otmsCapEmHeight
));
1492 output
->otmsXHeight
= abs(INTERNAL_YDSTOWS(dc
,output
->otmsXHeight
));
1493 output
->otmrcFontBox
.top
= HDPTOLP(output
->otmrcFontBox
.top
);
1494 output
->otmrcFontBox
.bottom
= HDPTOLP(output
->otmrcFontBox
.bottom
);
1495 output
->otmrcFontBox
.left
= WDPTOLP(output
->otmrcFontBox
.left
);
1496 output
->otmrcFontBox
.right
= WDPTOLP(output
->otmrcFontBox
.right
);
1497 output
->otmMacAscent
= HDPTOLP(output
->otmMacAscent
);
1498 output
->otmMacDescent
= HDPTOLP(output
->otmMacDescent
);
1499 output
->otmMacLineGap
= abs(INTERNAL_YDSTOWS(dc
,output
->otmMacLineGap
));
1500 output
->otmptSubscriptSize
.x
= WDPTOLP(output
->otmptSubscriptSize
.x
);
1501 output
->otmptSubscriptSize
.y
= HDPTOLP(output
->otmptSubscriptSize
.y
);
1502 output
->otmptSubscriptOffset
.x
= WDPTOLP(output
->otmptSubscriptOffset
.x
);
1503 output
->otmptSubscriptOffset
.y
= HDPTOLP(output
->otmptSubscriptOffset
.y
);
1504 output
->otmptSuperscriptSize
.x
= WDPTOLP(output
->otmptSuperscriptSize
.x
);
1505 output
->otmptSuperscriptSize
.y
= HDPTOLP(output
->otmptSuperscriptSize
.y
);
1506 output
->otmptSuperscriptOffset
.x
= WDPTOLP(output
->otmptSuperscriptOffset
.x
);
1507 output
->otmptSuperscriptOffset
.y
= HDPTOLP(output
->otmptSuperscriptOffset
.y
);
1508 output
->otmsStrikeoutSize
= abs(INTERNAL_YDSTOWS(dc
,output
->otmsStrikeoutSize
));
1509 output
->otmsStrikeoutPosition
= HDPTOLP(output
->otmsStrikeoutPosition
);
1510 output
->otmsUnderscoreSize
= HDPTOLP(output
->otmsUnderscoreSize
);
1511 output
->otmsUnderscorePosition
= HDPTOLP(output
->otmsUnderscorePosition
);
1516 memcpy(lpOTM
, output
, cbData
);
1517 HeapFree(GetProcessHeap(), 0, output
);
1525 static LPSTR
FONT_GetCharsByRangeA(HDC hdc
, UINT firstChar
, UINT lastChar
, PINT pByteLen
)
1527 INT i
, count
= lastChar
- firstChar
+ 1;
1534 switch (GdiGetCodePage(hdc
))
1541 if (lastChar
> 0xffff)
1543 if ((firstChar
^ lastChar
) > 0xff)
1547 if (lastChar
> 0xff)
1552 str
= HeapAlloc(GetProcessHeap(), 0, count
* 2 + 1);
1556 for(i
= 0, c
= firstChar
; c
<= lastChar
; i
++, c
++)
1559 str
[i
++] = (BYTE
)(c
>> 8);
1569 /***********************************************************************
1570 * GetCharWidthW (GDI32.@)
1571 * GetCharWidth32W (GDI32.@)
1573 BOOL WINAPI
GetCharWidth32W( HDC hdc
, UINT firstChar
, UINT lastChar
,
1579 DC
* dc
= get_dc_ptr( hdc
);
1581 if (!dc
) return FALSE
;
1583 dev
= GET_DC_PHYSDEV( dc
, pGetCharWidth
);
1584 ret
= dev
->funcs
->pGetCharWidth( dev
, firstChar
, lastChar
, buffer
);
1588 /* convert device units to logical */
1589 for( i
= firstChar
; i
<= lastChar
; i
++, buffer
++ )
1590 *buffer
= INTERNAL_XDSTOWS(dc
, *buffer
);
1592 release_dc_ptr( dc
);
1597 /***********************************************************************
1598 * GetCharWidthA (GDI32.@)
1599 * GetCharWidth32A (GDI32.@)
1601 BOOL WINAPI
GetCharWidth32A( HDC hdc
, UINT firstChar
, UINT lastChar
,
1609 str
= FONT_GetCharsByRangeA(hdc
, firstChar
, lastChar
, &i
);
1613 wstr
= FONT_mbtowc(hdc
, str
, i
, &wlen
, NULL
);
1615 for(i
= 0; i
< wlen
; i
++)
1617 if(!GetCharWidth32W(hdc
, wstr
[i
], wstr
[i
], buffer
))
1625 HeapFree(GetProcessHeap(), 0, str
);
1626 HeapFree(GetProcessHeap(), 0, wstr
);
1632 /***********************************************************************
1633 * ExtTextOutA (GDI32.@)
1637 BOOL WINAPI
ExtTextOutA( HDC hdc
, INT x
, INT y
, UINT flags
,
1638 const RECT
*lprect
, LPCSTR str
, UINT count
, const INT
*lpDx
)
1646 if (flags
& ETO_GLYPH_INDEX
)
1647 return ExtTextOutW( hdc
, x
, y
, flags
, lprect
, (LPCWSTR
)str
, count
, lpDx
);
1649 p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, &codepage
);
1652 unsigned int i
= 0, j
= 0;
1654 /* allocate enough for a ETO_PDY */
1655 lpDxW
= HeapAlloc( GetProcessHeap(), 0, 2*wlen
*sizeof(INT
));
1657 if(IsDBCSLeadByteEx(codepage
, str
[i
]))
1661 lpDxW
[j
++] = lpDx
[i
* 2] + lpDx
[(i
+ 1) * 2];
1662 lpDxW
[j
++] = lpDx
[i
* 2 + 1] + lpDx
[(i
+ 1) * 2 + 1];
1665 lpDxW
[j
++] = lpDx
[i
] + lpDx
[i
+ 1];
1672 lpDxW
[j
++] = lpDx
[i
* 2];
1673 lpDxW
[j
++] = lpDx
[i
* 2 + 1];
1676 lpDxW
[j
++] = lpDx
[i
];
1682 ret
= ExtTextOutW( hdc
, x
, y
, flags
, lprect
, p
, wlen
, lpDxW
);
1684 HeapFree( GetProcessHeap(), 0, p
);
1685 HeapFree( GetProcessHeap(), 0, lpDxW
);
1690 /***********************************************************************
1691 * ExtTextOutW (GDI32.@)
1693 * Draws text using the currently selected font, background color, and text color.
1697 * x,y [I] coordinates of string
1699 * ETO_GRAYED - undocumented on MSDN
1700 * ETO_OPAQUE - use background color for fill the rectangle
1701 * ETO_CLIPPED - clipping text to the rectangle
1702 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1703 * than encoded characters. Implies ETO_IGNORELANGUAGE
1704 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1705 * Affects BiDi ordering
1706 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1707 * ETO_PDY - unimplemented
1708 * ETO_NUMERICSLATIN - unimplemented always assumed -
1709 * do not translate numbers into locale representations
1710 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1711 * lprect [I] dimensions for clipping or/and opaquing
1712 * str [I] text string
1713 * count [I] number of symbols in string
1714 * lpDx [I] optional parameter with distance between drawing characters
1720 BOOL WINAPI
ExtTextOutW( HDC hdc
, INT x
, INT y
, UINT flags
,
1721 const RECT
*lprect
, LPCWSTR str
, UINT count
, const INT
*lpDx
)
1724 LPWSTR reordered_str
= (LPWSTR
)str
;
1725 WORD
*glyphs
= NULL
;
1726 UINT align
= GetTextAlign( hdc
);
1727 DWORD layout
= GetLayout( hdc
);
1731 double cosEsc
, sinEsc
;
1735 BOOL done_extents
= FALSE
;
1736 POINT
*deltas
= NULL
, width
= {0, 0};
1738 DC
* dc
= get_dc_ptr( hdc
);
1741 static int quietfixme
= 0;
1743 if (!dc
) return FALSE
;
1745 breakRem
= dc
->breakRem
;
1747 if (quietfixme
== 0 && flags
& (ETO_NUMERICSLOCAL
| ETO_NUMERICSLATIN
))
1749 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN unimplemented\n");
1754 physdev
= GET_DC_PHYSDEV( dc
, pExtTextOut
);
1755 type
= GetObjectType(hdc
);
1756 if(type
== OBJ_METADC
|| type
== OBJ_ENHMETADC
)
1758 ret
= physdev
->funcs
->pExtTextOut( physdev
, x
, y
, flags
, lprect
, str
, count
, lpDx
);
1759 release_dc_ptr( dc
);
1764 flags
&= ~ETO_CLIPPED
;
1766 if (flags
& ETO_RTLREADING
) align
|= TA_RTLREADING
;
1767 if (layout
& LAYOUT_RTL
)
1769 if ((align
& TA_CENTER
) != TA_CENTER
) align
^= TA_RIGHT
;
1770 align
^= TA_RTLREADING
;
1773 if( !(flags
& (ETO_GLYPH_INDEX
| ETO_IGNORELANGUAGE
)) && count
> 0 )
1776 reordered_str
= HeapAlloc(GetProcessHeap(), 0, count
*sizeof(WCHAR
));
1778 BIDI_Reorder( hdc
, str
, count
, GCP_REORDER
,
1779 (align
& TA_RTLREADING
) ? WINE_GCPW_FORCE_RTL
: WINE_GCPW_FORCE_LTR
,
1780 reordered_str
, count
, NULL
, &glyphs
, &cGlyphs
);
1782 flags
|= ETO_IGNORELANGUAGE
;
1785 flags
|= ETO_GLYPH_INDEX
;
1786 if (cGlyphs
!= count
)
1790 else if(flags
& ETO_GLYPH_INDEX
)
1791 glyphs
= reordered_str
;
1793 TRACE("%p, %d, %d, %08x, %s, %s, %d, %p)\n", hdc
, x
, y
, flags
,
1794 wine_dbgstr_rect(lprect
), debugstr_wn(str
, count
), count
, lpDx
);
1795 TRACE("align = %x bkmode = %x mapmode = %x\n", align
, GetBkMode(hdc
), GetMapMode(hdc
));
1797 if(align
& TA_UPDATECP
)
1799 GetCurrentPositionEx( hdc
, &pt
);
1804 GetTextMetricsW(hdc
, &tm
);
1805 GetObjectW(GetCurrentObject(hdc
, OBJ_FONT
), sizeof(lf
), &lf
);
1807 if(!(tm
.tmPitchAndFamily
& TMPF_VECTOR
)) /* Non-scalable fonts shouldn't be rotated */
1808 lf
.lfEscapement
= 0;
1810 if(lf
.lfEscapement
!= 0)
1812 cosEsc
= cos(lf
.lfEscapement
* M_PI
/ 1800);
1813 sinEsc
= sin(lf
.lfEscapement
* M_PI
/ 1800);
1821 if(flags
& (ETO_CLIPPED
| ETO_OPAQUE
))
1825 if(flags
& ETO_GLYPH_INDEX
)
1826 GetTextExtentPointI(hdc
, glyphs
, count
, &sz
);
1828 GetTextExtentPointW(hdc
, reordered_str
, count
, &sz
);
1830 done_extents
= TRUE
;
1833 rc
.right
= x
+ sz
.cx
;
1834 rc
.bottom
= y
+ sz
.cy
;
1841 LPtoDP(hdc
, (POINT
*)&rc
, 2);
1843 if(rc
.left
> rc
.right
) {INT tmp
= rc
.left
; rc
.left
= rc
.right
; rc
.right
= tmp
;}
1844 if(rc
.top
> rc
.bottom
) {INT tmp
= rc
.top
; rc
.top
= rc
.bottom
; rc
.bottom
= tmp
;}
1847 if ((flags
& ETO_OPAQUE
) && !PATH_IsPathOpen(dc
->path
))
1848 physdev
->funcs
->pExtTextOut( physdev
, 0, 0, ETO_OPAQUE
, &rc
, NULL
, 0, NULL
);
1858 LPtoDP(hdc
, &pt
, 1);
1862 char_extra
= GetTextCharacterExtra(hdc
);
1863 if(char_extra
|| dc
->breakExtra
|| breakRem
|| lpDx
|| lf
.lfEscapement
!= 0)
1867 POINT total
= {0, 0}, desired
[2];
1869 deltas
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(*deltas
));
1870 for(i
= 0; i
< count
; i
++)
1876 deltas
[i
].x
= lpDx
[i
* 2] + char_extra
;
1877 deltas
[i
].y
= -lpDx
[i
* 2 + 1];
1881 deltas
[i
].x
= lpDx
[i
] + char_extra
;
1888 if(flags
& ETO_GLYPH_INDEX
)
1889 GetTextExtentPointI(hdc
, glyphs
+ i
, 1, &tmpsz
);
1891 GetTextExtentPointW(hdc
, reordered_str
+ i
, 1, &tmpsz
);
1893 deltas
[i
].x
= tmpsz
.cx
;
1897 if (!(flags
& ETO_GLYPH_INDEX
) && (dc
->breakExtra
|| breakRem
) && reordered_str
[i
] == tm
.tmBreakChar
)
1899 deltas
[i
].x
= deltas
[i
].x
+ dc
->breakExtra
;
1906 total
.x
+= deltas
[i
].x
;
1907 total
.y
+= deltas
[i
].y
;
1909 desired
[0].x
= desired
[0].y
= 0;
1911 desired
[1].x
= cosEsc
* total
.x
+ sinEsc
* total
.y
;
1912 desired
[1].y
= -sinEsc
* total
.x
+ cosEsc
* total
.y
;
1914 LPtoDP(hdc
, desired
, 2);
1915 desired
[1].x
-= desired
[0].x
;
1916 desired
[1].y
-= desired
[0].y
;
1917 if (layout
& LAYOUT_RTL
) desired
[1].x
= -desired
[1].x
;
1919 deltas
[i
].x
= desired
[1].x
- width
.x
;
1920 deltas
[i
].y
= desired
[1].y
- width
.y
;
1930 if(flags
& ETO_GLYPH_INDEX
)
1931 GetTextExtentPointI(hdc
, glyphs
, count
, &sz
);
1933 GetTextExtentPointW(hdc
, reordered_str
, count
, &sz
);
1934 done_extents
= TRUE
;
1936 width
.x
= abs(INTERNAL_XWSTODS(dc
, sz
.cx
));
1940 tm
.tmAscent
= abs(INTERNAL_YWSTODS(dc
, tm
.tmAscent
));
1941 tm
.tmDescent
= abs(INTERNAL_YWSTODS(dc
, tm
.tmDescent
));
1942 switch( align
& (TA_LEFT
| TA_RIGHT
| TA_CENTER
) )
1945 if (align
& TA_UPDATECP
)
1949 DPtoLP(hdc
, &pt
, 1);
1950 MoveToEx(hdc
, pt
.x
, pt
.y
, NULL
);
1962 if (align
& TA_UPDATECP
)
1966 DPtoLP(hdc
, &pt
, 1);
1967 MoveToEx(hdc
, pt
.x
, pt
.y
, NULL
);
1972 switch( align
& (TA_TOP
| TA_BOTTOM
| TA_BASELINE
) )
1975 y
+= tm
.tmAscent
* cosEsc
;
1976 x
+= tm
.tmAscent
* sinEsc
;
1980 y
-= tm
.tmDescent
* cosEsc
;
1981 x
-= tm
.tmDescent
* sinEsc
;
1988 if (GetBkMode(hdc
) != TRANSPARENT
&& !PATH_IsPathOpen(dc
->path
))
1990 if(!((flags
& ETO_CLIPPED
) && (flags
& ETO_OPAQUE
)))
1992 if(!(flags
& ETO_OPAQUE
) || x
< rc
.left
|| x
+ width
.x
>= rc
.right
||
1993 y
- tm
.tmAscent
< rc
.top
|| y
+ tm
.tmDescent
>= rc
.bottom
)
1997 rc
.right
= x
+ width
.x
;
1998 rc
.top
= y
- tm
.tmAscent
;
1999 rc
.bottom
= y
+ tm
.tmDescent
;
2001 if(flags
& ETO_CLIPPED
)
2003 rc
.left
= max(lprect
->left
, rc
.left
);
2004 rc
.right
= min(lprect
->right
, rc
.right
);
2005 rc
.top
= max(lprect
->top
, rc
.top
);
2006 rc
.bottom
= min(lprect
->bottom
, rc
.bottom
);
2008 if(rc
.left
< rc
.right
&& rc
.top
< rc
.bottom
)
2009 physdev
->funcs
->pExtTextOut( physdev
, 0, 0, ETO_OPAQUE
, &rc
, NULL
, 0, NULL
);
2014 if(FontIsLinked(hdc
) && !(flags
& ETO_GLYPH_INDEX
))
2016 HFONT orig_font
= dc
->hFont
, cur_font
;
2019 POINT
*offsets
= NULL
;
2022 glyphs
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(WORD
));
2023 for(i
= 0; i
< count
; i
++)
2025 WineEngGetLinkedHFont(dc
, reordered_str
[i
], &cur_font
, &glyph
);
2026 if(cur_font
!= dc
->hFont
)
2031 offsets
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(*deltas
));
2032 offsets
[0].x
= offsets
[0].y
= 0;
2037 for(j
= 1; j
< count
; j
++)
2039 GetTextExtentPointW(hdc
, reordered_str
+ j
- 1, 1, &tmpsz
);
2040 offsets
[j
].x
= offsets
[j
- 1].x
+ abs(INTERNAL_XWSTODS(dc
, tmpsz
.cx
));
2046 for(j
= 1; j
< count
; j
++)
2048 offsets
[j
].x
= offsets
[j
- 1].x
+ deltas
[j
].x
;
2049 offsets
[j
].y
= offsets
[j
- 1].y
+ deltas
[j
].y
;
2055 if (PATH_IsPathOpen(dc
->path
))
2056 ret
= PATH_ExtTextOut(dc
, x
+ offsets
[i
- span
].x
, y
+ offsets
[i
- span
].y
,
2057 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
,
2058 glyphs
, span
, deltas
? (INT
*)(deltas
+ (i
- span
)) : NULL
);
2060 physdev
->funcs
->pExtTextOut( physdev
, x
+ offsets
[i
- span
].x
,
2061 y
+ offsets
[i
- span
].y
,
2062 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
, glyphs
,
2063 span
, deltas
? (INT
*)(deltas
+ (i
- span
)) : NULL
);
2066 SelectObject(hdc
, cur_font
);
2068 glyphs
[span
++] = glyph
;
2072 if (PATH_IsPathOpen(dc
->path
))
2073 ret
= PATH_ExtTextOut(dc
, x
+ (offsets
? offsets
[count
- span
].x
: 0),
2074 y
+ (offsets
? offsets
[count
- span
].y
: 0),
2075 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
,
2076 glyphs
, span
, deltas
? (INT
*)(deltas
+ (count
- span
)) : NULL
);
2078 ret
= physdev
->funcs
->pExtTextOut(physdev
, x
+ (offsets
? offsets
[count
- span
].x
: 0),
2079 y
+ (offsets
? offsets
[count
- span
].y
: 0),
2080 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
, glyphs
,
2081 span
, deltas
? (INT
*)(deltas
+ (count
- span
)) : NULL
);
2082 SelectObject(hdc
, orig_font
);
2083 HeapFree(GetProcessHeap(), 0, offsets
);
2089 if(!(flags
& ETO_GLYPH_INDEX
) && dc
->gdiFont
)
2091 glyphs
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(WORD
));
2092 GetGlyphIndicesW(hdc
, reordered_str
, count
, glyphs
, 0);
2093 flags
|= ETO_GLYPH_INDEX
;
2096 if (PATH_IsPathOpen(dc
->path
))
2097 ret
= PATH_ExtTextOut(dc
, x
, y
, (flags
& ~ETO_OPAQUE
), &rc
,
2098 glyphs
? glyphs
: reordered_str
, count
, (INT
*)deltas
);
2100 ret
= physdev
->funcs
->pExtTextOut( physdev
, x
, y
, (flags
& ~ETO_OPAQUE
), &rc
,
2101 glyphs
? glyphs
: reordered_str
, count
, (INT
*)deltas
);
2105 HeapFree(GetProcessHeap(), 0, deltas
);
2106 if(glyphs
!= reordered_str
)
2107 HeapFree(GetProcessHeap(), 0, glyphs
);
2108 if(reordered_str
!= str
)
2109 HeapFree(GetProcessHeap(), 0, reordered_str
);
2111 release_dc_ptr( dc
);
2113 if (ret
&& (lf
.lfUnderline
|| lf
.lfStrikeOut
))
2115 int underlinePos
, strikeoutPos
;
2116 int underlineWidth
, strikeoutWidth
;
2117 UINT size
= GetOutlineTextMetricsW(hdc
, 0, NULL
);
2118 OUTLINETEXTMETRICW
* otm
= NULL
;
2123 underlineWidth
= tm
.tmAscent
/ 20 + 1;
2124 strikeoutPos
= tm
.tmAscent
/ 2;
2125 strikeoutWidth
= underlineWidth
;
2129 otm
= HeapAlloc(GetProcessHeap(), 0, size
);
2130 GetOutlineTextMetricsW(hdc
, size
, otm
);
2131 underlinePos
= otm
->otmsUnderscorePosition
;
2132 underlineWidth
= otm
->otmsUnderscoreSize
;
2133 strikeoutPos
= otm
->otmsStrikeoutPosition
;
2134 strikeoutWidth
= otm
->otmsStrikeoutSize
;
2135 HeapFree(GetProcessHeap(), 0, otm
);
2138 if (PATH_IsPathOpen(dc
->path
))
2142 HBRUSH hbrush
= CreateSolidBrush(GetTextColor(hdc
));
2144 hbrush
= SelectObject(hdc
, hbrush
);
2145 hpen
= SelectObject(hdc
, GetStockObject(NULL_PEN
));
2149 pts
[0].x
= x
- underlinePos
* sinEsc
;
2150 pts
[0].y
= y
- underlinePos
* cosEsc
;
2151 pts
[1].x
= x
+ width
.x
- underlinePos
* sinEsc
;
2152 pts
[1].y
= y
+ width
.y
- underlinePos
* cosEsc
;
2153 pts
[2].x
= pts
[1].x
+ underlineWidth
* sinEsc
;
2154 pts
[2].y
= pts
[1].y
+ underlineWidth
* cosEsc
;
2155 pts
[3].x
= pts
[0].x
+ underlineWidth
* sinEsc
;
2156 pts
[3].y
= pts
[0].y
+ underlineWidth
* cosEsc
;
2157 pts
[4].x
= pts
[0].x
;
2158 pts
[4].y
= pts
[0].y
;
2159 DPtoLP(hdc
, pts
, 5);
2160 Polygon(hdc
, pts
, 5);
2165 pts
[0].x
= x
- strikeoutPos
* sinEsc
;
2166 pts
[0].y
= y
- strikeoutPos
* cosEsc
;
2167 pts
[1].x
= x
+ width
.x
- strikeoutPos
* sinEsc
;
2168 pts
[1].y
= y
+ width
.y
- strikeoutPos
* cosEsc
;
2169 pts
[2].x
= pts
[1].x
+ strikeoutWidth
* sinEsc
;
2170 pts
[2].y
= pts
[1].y
+ strikeoutWidth
* cosEsc
;
2171 pts
[3].x
= pts
[0].x
+ strikeoutWidth
* sinEsc
;
2172 pts
[3].y
= pts
[0].y
+ strikeoutWidth
* cosEsc
;
2173 pts
[4].x
= pts
[0].x
;
2174 pts
[4].y
= pts
[0].y
;
2175 DPtoLP(hdc
, pts
, 5);
2176 Polygon(hdc
, pts
, 5);
2179 SelectObject(hdc
, hpen
);
2180 hbrush
= SelectObject(hdc
, hbrush
);
2181 DeleteObject(hbrush
);
2185 POINT pts
[2], oldpt
;
2190 hpen
= CreatePen(PS_SOLID
, underlineWidth
, GetTextColor(hdc
));
2191 hpen
= SelectObject(hdc
, hpen
);
2194 pts
[1].x
= x
+ width
.x
;
2195 pts
[1].y
= y
+ width
.y
;
2196 DPtoLP(hdc
, pts
, 2);
2197 MoveToEx(hdc
, pts
[0].x
- underlinePos
* sinEsc
, pts
[0].y
- underlinePos
* cosEsc
, &oldpt
);
2198 LineTo(hdc
, pts
[1].x
- underlinePos
* sinEsc
, pts
[1].y
- underlinePos
* cosEsc
);
2199 MoveToEx(hdc
, oldpt
.x
, oldpt
.y
, NULL
);
2200 DeleteObject(SelectObject(hdc
, hpen
));
2205 hpen
= CreatePen(PS_SOLID
, strikeoutWidth
, 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
- strikeoutPos
* sinEsc
, pts
[0].y
- strikeoutPos
* cosEsc
, &oldpt
);
2213 LineTo(hdc
, pts
[1].x
- strikeoutPos
* sinEsc
, pts
[1].y
- strikeoutPos
* cosEsc
);
2214 MoveToEx(hdc
, oldpt
.x
, oldpt
.y
, NULL
);
2215 DeleteObject(SelectObject(hdc
, hpen
));
2224 /***********************************************************************
2225 * TextOutA (GDI32.@)
2227 BOOL WINAPI
TextOutA( HDC hdc
, INT x
, INT y
, LPCSTR str
, INT count
)
2229 return ExtTextOutA( hdc
, x
, y
, 0, NULL
, str
, count
, NULL
);
2233 /***********************************************************************
2234 * TextOutW (GDI32.@)
2236 BOOL WINAPI
TextOutW(HDC hdc
, INT x
, INT y
, LPCWSTR str
, INT count
)
2238 return ExtTextOutW( hdc
, x
, y
, 0, NULL
, str
, count
, NULL
);
2242 /***********************************************************************
2243 * PolyTextOutA (GDI32.@)
2247 BOOL WINAPI
PolyTextOutA( HDC hdc
, const POLYTEXTA
*pptxt
, INT cStrings
)
2249 for (; cStrings
>0; cStrings
--, pptxt
++)
2250 if (!ExtTextOutA( hdc
, pptxt
->x
, pptxt
->y
, pptxt
->uiFlags
, &pptxt
->rcl
, pptxt
->lpstr
, pptxt
->n
, pptxt
->pdx
))
2257 /***********************************************************************
2258 * PolyTextOutW (GDI32.@)
2260 * Draw several Strings
2266 BOOL WINAPI
PolyTextOutW( HDC hdc
, const POLYTEXTW
*pptxt
, INT cStrings
)
2268 for (; cStrings
>0; cStrings
--, pptxt
++)
2269 if (!ExtTextOutW( hdc
, pptxt
->x
, pptxt
->y
, pptxt
->uiFlags
, &pptxt
->rcl
, pptxt
->lpstr
, pptxt
->n
, pptxt
->pdx
))
2275 /***********************************************************************
2276 * SetMapperFlags (GDI32.@)
2278 DWORD WINAPI
SetMapperFlags( HDC hdc
, DWORD flags
)
2280 DC
*dc
= get_dc_ptr( hdc
);
2281 DWORD ret
= GDI_ERROR
;
2285 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetMapperFlags
);
2286 flags
= physdev
->funcs
->pSetMapperFlags( physdev
, flags
);
2287 if (flags
!= GDI_ERROR
)
2289 ret
= dc
->mapperFlags
;
2290 dc
->mapperFlags
= flags
;
2292 release_dc_ptr( dc
);
2297 /***********************************************************************
2298 * GetAspectRatioFilterEx (GDI32.@)
2300 BOOL WINAPI
GetAspectRatioFilterEx( HDC hdc
, LPSIZE pAspectRatio
)
2302 FIXME("(%p, %p): -- Empty Stub !\n", hdc
, pAspectRatio
);
2307 /***********************************************************************
2308 * GetCharABCWidthsA (GDI32.@)
2310 * See GetCharABCWidthsW.
2312 BOOL WINAPI
GetCharABCWidthsA(HDC hdc
, UINT firstChar
, UINT lastChar
,
2320 str
= FONT_GetCharsByRangeA(hdc
, firstChar
, lastChar
, &i
);
2324 wstr
= FONT_mbtowc(hdc
, str
, i
, &wlen
, NULL
);
2327 HeapFree(GetProcessHeap(), 0, str
);
2331 for(i
= 0; i
< wlen
; i
++)
2333 if(!GetCharABCWidthsW(hdc
, wstr
[i
], wstr
[i
], abc
))
2341 HeapFree(GetProcessHeap(), 0, str
);
2342 HeapFree(GetProcessHeap(), 0, wstr
);
2348 /******************************************************************************
2349 * GetCharABCWidthsW [GDI32.@]
2351 * Retrieves widths of characters in range.
2354 * hdc [I] Handle of device context
2355 * firstChar [I] First character in range to query
2356 * lastChar [I] Last character in range to query
2357 * abc [O] Address of character-width structure
2360 * Only works with TrueType fonts
2366 BOOL WINAPI
GetCharABCWidthsW( HDC hdc
, UINT firstChar
, UINT lastChar
,
2369 DC
*dc
= get_dc_ptr(hdc
);
2374 if (!dc
) return FALSE
;
2378 release_dc_ptr( dc
);
2382 dev
= GET_DC_PHYSDEV( dc
, pGetCharABCWidths
);
2383 ret
= dev
->funcs
->pGetCharABCWidths( dev
, firstChar
, lastChar
, abc
);
2386 /* convert device units to logical */
2387 for( i
= firstChar
; i
<= lastChar
; i
++, abc
++ ) {
2388 abc
->abcA
= INTERNAL_XDSTOWS(dc
, abc
->abcA
);
2389 abc
->abcB
= INTERNAL_XDSTOWS(dc
, abc
->abcB
);
2390 abc
->abcC
= INTERNAL_XDSTOWS(dc
, abc
->abcC
);
2394 release_dc_ptr( dc
);
2399 /******************************************************************************
2400 * GetCharABCWidthsI [GDI32.@]
2402 * Retrieves widths of characters in range.
2405 * hdc [I] Handle of device context
2406 * firstChar [I] First glyphs in range to query
2407 * count [I] Last glyphs in range to query
2408 * pgi [i] Array of glyphs to query
2409 * abc [O] Address of character-width structure
2412 * Only works with TrueType fonts
2418 BOOL WINAPI
GetCharABCWidthsI( HDC hdc
, UINT firstChar
, UINT count
,
2419 LPWORD pgi
, LPABC abc
)
2421 DC
*dc
= get_dc_ptr(hdc
);
2426 if (!dc
) return FALSE
;
2430 release_dc_ptr( dc
);
2434 dev
= GET_DC_PHYSDEV( dc
, pGetCharABCWidthsI
);
2435 ret
= dev
->funcs
->pGetCharABCWidthsI( dev
, firstChar
, count
, pgi
, abc
);
2438 /* convert device units to logical */
2439 for( i
= 0; i
< count
; i
++, abc
++ ) {
2440 abc
->abcA
= INTERNAL_XDSTOWS(dc
, abc
->abcA
);
2441 abc
->abcB
= INTERNAL_XDSTOWS(dc
, abc
->abcB
);
2442 abc
->abcC
= INTERNAL_XDSTOWS(dc
, abc
->abcC
);
2446 release_dc_ptr( dc
);
2451 /***********************************************************************
2452 * GetGlyphOutlineA (GDI32.@)
2454 DWORD WINAPI
GetGlyphOutlineA( HDC hdc
, UINT uChar
, UINT fuFormat
,
2455 LPGLYPHMETRICS lpgm
, DWORD cbBuffer
,
2456 LPVOID lpBuffer
, const MAT2
*lpmat2
)
2458 if (!lpmat2
) return GDI_ERROR
;
2460 if(!(fuFormat
& GGO_GLYPH_INDEX
)) {
2465 cp
= GdiGetCodePage(hdc
);
2466 if (IsDBCSLeadByteEx(cp
, uChar
>> 8)) {
2468 mbchs
[0] = (uChar
& 0xff00) >> 8;
2469 mbchs
[1] = (uChar
& 0xff);
2472 mbchs
[0] = (uChar
& 0xff);
2475 MultiByteToWideChar(cp
, 0, mbchs
, len
, (LPWSTR
)&uChar
, 1);
2478 return GetGlyphOutlineW(hdc
, uChar
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
,
2482 /***********************************************************************
2483 * GetGlyphOutlineW (GDI32.@)
2485 DWORD WINAPI
GetGlyphOutlineW( HDC hdc
, UINT uChar
, UINT fuFormat
,
2486 LPGLYPHMETRICS lpgm
, DWORD cbBuffer
,
2487 LPVOID lpBuffer
, const MAT2
*lpmat2
)
2493 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2494 hdc
, uChar
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
, lpmat2
);
2496 if (!lpmat2
) return GDI_ERROR
;
2498 dc
= get_dc_ptr(hdc
);
2499 if(!dc
) return GDI_ERROR
;
2501 dev
= GET_DC_PHYSDEV( dc
, pGetGlyphOutline
);
2502 ret
= dev
->funcs
->pGetGlyphOutline( dev
, uChar
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
, lpmat2
);
2503 release_dc_ptr( dc
);
2508 /***********************************************************************
2509 * CreateScalableFontResourceA (GDI32.@)
2511 BOOL WINAPI
CreateScalableFontResourceA( DWORD fHidden
,
2512 LPCSTR lpszResourceFile
,
2513 LPCSTR lpszFontFile
,
2514 LPCSTR lpszCurrentPath
)
2516 LPWSTR lpszResourceFileW
= NULL
;
2517 LPWSTR lpszFontFileW
= NULL
;
2518 LPWSTR lpszCurrentPathW
= NULL
;
2522 if (lpszResourceFile
)
2524 len
= MultiByteToWideChar(CP_ACP
, 0, lpszResourceFile
, -1, NULL
, 0);
2525 lpszResourceFileW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2526 MultiByteToWideChar(CP_ACP
, 0, lpszResourceFile
, -1, lpszResourceFileW
, len
);
2531 len
= MultiByteToWideChar(CP_ACP
, 0, lpszFontFile
, -1, NULL
, 0);
2532 lpszFontFileW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2533 MultiByteToWideChar(CP_ACP
, 0, lpszFontFile
, -1, lpszFontFileW
, len
);
2536 if (lpszCurrentPath
)
2538 len
= MultiByteToWideChar(CP_ACP
, 0, lpszCurrentPath
, -1, NULL
, 0);
2539 lpszCurrentPathW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2540 MultiByteToWideChar(CP_ACP
, 0, lpszCurrentPath
, -1, lpszCurrentPathW
, len
);
2543 ret
= CreateScalableFontResourceW(fHidden
, lpszResourceFileW
,
2544 lpszFontFileW
, lpszCurrentPathW
);
2546 HeapFree(GetProcessHeap(), 0, lpszResourceFileW
);
2547 HeapFree(GetProcessHeap(), 0, lpszFontFileW
);
2548 HeapFree(GetProcessHeap(), 0, lpszCurrentPathW
);
2553 /***********************************************************************
2554 * CreateScalableFontResourceW (GDI32.@)
2556 BOOL WINAPI
CreateScalableFontResourceW( DWORD fHidden
,
2557 LPCWSTR lpszResourceFile
,
2558 LPCWSTR lpszFontFile
,
2559 LPCWSTR lpszCurrentPath
)
2562 FIXME("(%d,%s,%s,%s): stub\n",
2563 fHidden
, debugstr_w(lpszResourceFile
), debugstr_w(lpszFontFile
),
2564 debugstr_w(lpszCurrentPath
) );
2566 /* fHidden=1 - only visible for the calling app, read-only, not
2567 * enumerated with EnumFonts/EnumFontFamilies
2568 * lpszCurrentPath can be NULL
2571 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2572 if ((f
= CreateFileW(lpszResourceFile
, 0, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, 0)) != INVALID_HANDLE_VALUE
) {
2574 SetLastError(ERROR_FILE_EXISTS
);
2577 return FALSE
; /* create failed */
2580 /*************************************************************************
2581 * GetKerningPairsA (GDI32.@)
2583 DWORD WINAPI
GetKerningPairsA( HDC hDC
, DWORD cPairs
,
2584 LPKERNINGPAIR kern_pairA
)
2588 DWORD i
, total_kern_pairs
, kern_pairs_copied
= 0;
2589 KERNINGPAIR
*kern_pairW
;
2591 if (!cPairs
&& kern_pairA
)
2593 SetLastError(ERROR_INVALID_PARAMETER
);
2597 cp
= GdiGetCodePage(hDC
);
2599 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2600 * to fail on an invalid character for CP_SYMBOL.
2602 cpi
.DefaultChar
[0] = 0;
2603 if (cp
!= CP_SYMBOL
&& !GetCPInfo(cp
, &cpi
))
2605 FIXME("Can't find codepage %u info\n", cp
);
2609 total_kern_pairs
= GetKerningPairsW(hDC
, 0, NULL
);
2610 if (!total_kern_pairs
) return 0;
2612 kern_pairW
= HeapAlloc(GetProcessHeap(), 0, total_kern_pairs
* sizeof(*kern_pairW
));
2613 GetKerningPairsW(hDC
, total_kern_pairs
, kern_pairW
);
2615 for (i
= 0; i
< total_kern_pairs
; i
++)
2619 if (!WideCharToMultiByte(cp
, 0, &kern_pairW
[i
].wFirst
, 1, &first
, 1, NULL
, NULL
))
2622 if (!WideCharToMultiByte(cp
, 0, &kern_pairW
[i
].wSecond
, 1, &second
, 1, NULL
, NULL
))
2625 if (first
== cpi
.DefaultChar
[0] || second
== cpi
.DefaultChar
[0])
2630 if (kern_pairs_copied
>= cPairs
) break;
2632 kern_pairA
->wFirst
= (BYTE
)first
;
2633 kern_pairA
->wSecond
= (BYTE
)second
;
2634 kern_pairA
->iKernAmount
= kern_pairW
[i
].iKernAmount
;
2637 kern_pairs_copied
++;
2640 HeapFree(GetProcessHeap(), 0, kern_pairW
);
2642 return kern_pairs_copied
;
2645 /*************************************************************************
2646 * GetKerningPairsW (GDI32.@)
2648 DWORD WINAPI
GetKerningPairsW( HDC hDC
, DWORD cPairs
,
2649 LPKERNINGPAIR lpKerningPairs
)
2655 TRACE("(%p,%d,%p)\n", hDC
, cPairs
, lpKerningPairs
);
2657 if (!cPairs
&& lpKerningPairs
)
2659 SetLastError(ERROR_INVALID_PARAMETER
);
2663 dc
= get_dc_ptr(hDC
);
2666 dev
= GET_DC_PHYSDEV( dc
, pGetKerningPairs
);
2667 ret
= dev
->funcs
->pGetKerningPairs( dev
, cPairs
, lpKerningPairs
);
2668 release_dc_ptr( dc
);
2672 /*************************************************************************
2673 * TranslateCharsetInfo [GDI32.@]
2675 * Fills a CHARSETINFO structure for a character set, code page, or
2676 * font. This allows making the correspondence between different labels
2677 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2678 * of the same encoding.
2680 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2681 * only one codepage should be set in *lpSrc.
2684 * TRUE on success, FALSE on failure.
2687 BOOL WINAPI
TranslateCharsetInfo(
2688 LPDWORD lpSrc
, /* [in]
2689 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2690 if flags == TCI_SRCCHARSET: a character set value
2691 if flags == TCI_SRCCODEPAGE: a code page value
2693 LPCHARSETINFO lpCs
, /* [out] structure to receive charset information */
2694 DWORD flags
/* [in] determines interpretation of lpSrc */)
2698 case TCI_SRCFONTSIG
:
2699 while (index
< MAXTCIINDEX
&& !(*lpSrc
>>index
& 0x0001)) index
++;
2701 case TCI_SRCCODEPAGE
:
2702 while (index
< MAXTCIINDEX
&& PtrToUlong(lpSrc
) != FONT_tci
[index
].ciACP
) index
++;
2704 case TCI_SRCCHARSET
:
2705 while (index
< MAXTCIINDEX
&& PtrToUlong(lpSrc
) != FONT_tci
[index
].ciCharset
) index
++;
2710 if (index
>= MAXTCIINDEX
|| FONT_tci
[index
].ciCharset
== DEFAULT_CHARSET
) return FALSE
;
2711 *lpCs
= FONT_tci
[index
];
2715 /*************************************************************************
2716 * GetFontLanguageInfo (GDI32.@)
2718 DWORD WINAPI
GetFontLanguageInfo(HDC hdc
)
2720 FONTSIGNATURE fontsig
;
2721 static const DWORD GCP_DBCS_MASK
=0x003F0000,
2722 GCP_DIACRITIC_MASK
=0x00000000,
2723 FLI_GLYPHS_MASK
=0x00000000,
2724 GCP_GLYPHSHAPE_MASK
=0x00000040,
2725 GCP_KASHIDA_MASK
=0x00000000,
2726 GCP_LIGATE_MASK
=0x00000000,
2727 GCP_USEKERNING_MASK
=0x00000000,
2728 GCP_REORDER_MASK
=0x00000060;
2732 GetTextCharsetInfo( hdc
, &fontsig
, 0 );
2733 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2735 if( (fontsig
.fsCsb
[0]&GCP_DBCS_MASK
)!=0 )
2738 if( (fontsig
.fsCsb
[0]&GCP_DIACRITIC_MASK
)!=0 )
2739 result
|=GCP_DIACRITIC
;
2741 if( (fontsig
.fsCsb
[0]&FLI_GLYPHS_MASK
)!=0 )
2744 if( (fontsig
.fsCsb
[0]&GCP_GLYPHSHAPE_MASK
)!=0 )
2745 result
|=GCP_GLYPHSHAPE
;
2747 if( (fontsig
.fsCsb
[0]&GCP_KASHIDA_MASK
)!=0 )
2748 result
|=GCP_KASHIDA
;
2750 if( (fontsig
.fsCsb
[0]&GCP_LIGATE_MASK
)!=0 )
2753 if( (fontsig
.fsCsb
[0]&GCP_USEKERNING_MASK
)!=0 )
2754 result
|=GCP_USEKERNING
;
2756 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2757 if( GetTextAlign( hdc
) & TA_RTLREADING
)
2758 if( (fontsig
.fsCsb
[0]&GCP_REORDER_MASK
)!=0 )
2759 result
|=GCP_REORDER
;
2765 /*************************************************************************
2766 * GetFontData [GDI32.@]
2768 * Retrieve data for TrueType font.
2772 * success: Number of bytes returned
2773 * failure: GDI_ERROR
2777 * Calls SetLastError()
2780 DWORD WINAPI
GetFontData(HDC hdc
, DWORD table
, DWORD offset
,
2781 LPVOID buffer
, DWORD length
)
2783 DC
*dc
= get_dc_ptr(hdc
);
2784 DWORD ret
= GDI_ERROR
;
2786 if(!dc
) return GDI_ERROR
;
2789 ret
= WineEngGetFontData(dc
->gdiFont
, table
, offset
, buffer
, length
);
2791 release_dc_ptr( dc
);
2795 /*************************************************************************
2796 * GetGlyphIndicesA [GDI32.@]
2798 DWORD WINAPI
GetGlyphIndicesA(HDC hdc
, LPCSTR lpstr
, INT count
,
2799 LPWORD pgi
, DWORD flags
)
2805 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2806 hdc
, debugstr_an(lpstr
, count
), count
, pgi
, flags
);
2808 lpstrW
= FONT_mbtowc(hdc
, lpstr
, count
, &countW
, NULL
);
2809 ret
= GetGlyphIndicesW(hdc
, lpstrW
, countW
, pgi
, flags
);
2810 HeapFree(GetProcessHeap(), 0, lpstrW
);
2815 /*************************************************************************
2816 * GetGlyphIndicesW [GDI32.@]
2818 DWORD WINAPI
GetGlyphIndicesW(HDC hdc
, LPCWSTR lpstr
, INT count
,
2819 LPWORD pgi
, DWORD flags
)
2821 DC
*dc
= get_dc_ptr(hdc
);
2825 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2826 hdc
, debugstr_wn(lpstr
, count
), count
, pgi
, flags
);
2828 if(!dc
) return GDI_ERROR
;
2830 dev
= GET_DC_PHYSDEV( dc
, pGetGlyphIndices
);
2831 ret
= dev
->funcs
->pGetGlyphIndices( dev
, lpstr
, count
, pgi
, flags
);
2832 release_dc_ptr( dc
);
2836 /*************************************************************************
2837 * GetCharacterPlacementA [GDI32.@]
2839 * See GetCharacterPlacementW.
2842 * the web browser control of ie4 calls this with dwFlags=0
2845 GetCharacterPlacementA(HDC hdc
, LPCSTR lpString
, INT uCount
,
2846 INT nMaxExtent
, GCP_RESULTSA
*lpResults
,
2851 GCP_RESULTSW resultsW
;
2855 TRACE("%s, %d, %d, 0x%08x\n",
2856 debugstr_an(lpString
, uCount
), uCount
, nMaxExtent
, dwFlags
);
2858 /* both structs are equal in size */
2859 memcpy(&resultsW
, lpResults
, sizeof(resultsW
));
2861 lpStringW
= FONT_mbtowc(hdc
, lpString
, uCount
, &uCountW
, &font_cp
);
2862 if(lpResults
->lpOutString
)
2863 resultsW
.lpOutString
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*uCountW
);
2865 ret
= GetCharacterPlacementW(hdc
, lpStringW
, uCountW
, nMaxExtent
, &resultsW
, dwFlags
);
2867 lpResults
->nGlyphs
= resultsW
.nGlyphs
;
2868 lpResults
->nMaxFit
= resultsW
.nMaxFit
;
2870 if(lpResults
->lpOutString
) {
2871 WideCharToMultiByte(font_cp
, 0, resultsW
.lpOutString
, uCountW
,
2872 lpResults
->lpOutString
, uCount
, NULL
, NULL
);
2875 HeapFree(GetProcessHeap(), 0, lpStringW
);
2876 HeapFree(GetProcessHeap(), 0, resultsW
.lpOutString
);
2881 /*************************************************************************
2882 * GetCharacterPlacementW [GDI32.@]
2884 * Retrieve information about a string. This includes the width, reordering,
2885 * Glyphing and so on.
2889 * The width and height of the string if successful, 0 if failed.
2893 * All flags except GCP_REORDER are not yet implemented.
2894 * Reordering is not 100% compliant to the Windows BiDi method.
2895 * Caret positioning is not yet implemented for BiDi.
2896 * Classes are not yet implemented.
2900 GetCharacterPlacementW(
2901 HDC hdc
, /* [in] Device context for which the rendering is to be done */
2902 LPCWSTR lpString
, /* [in] The string for which information is to be returned */
2903 INT uCount
, /* [in] Number of WORDS in string. */
2904 INT nMaxExtent
, /* [in] Maximum extent the string is to take (in HDC logical units) */
2905 GCP_RESULTSW
*lpResults
,/* [in/out] A pointer to a GCP_RESULTSW struct */
2906 DWORD dwFlags
/* [in] Flags specifying how to process the string */
2913 TRACE("%s, %d, %d, 0x%08x\n",
2914 debugstr_wn(lpString
, uCount
), uCount
, nMaxExtent
, dwFlags
);
2916 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2917 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2918 lpResults
->lStructSize
, lpResults
->lpOutString
, lpResults
->lpOrder
,
2919 lpResults
->lpDx
, lpResults
->lpCaretPos
, lpResults
->lpClass
,
2920 lpResults
->lpGlyphs
, lpResults
->nGlyphs
, lpResults
->nMaxFit
);
2922 if(dwFlags
&(~GCP_REORDER
)) FIXME("flags 0x%08x ignored\n", dwFlags
);
2923 if(lpResults
->lpClass
) FIXME("classes not implemented\n");
2924 if (lpResults
->lpCaretPos
&& (dwFlags
& GCP_REORDER
))
2925 FIXME("Caret positions for complex scripts not implemented\n");
2927 nSet
= (UINT
)uCount
;
2928 if(nSet
> lpResults
->nGlyphs
)
2929 nSet
= lpResults
->nGlyphs
;
2931 /* return number of initialized fields */
2932 lpResults
->nGlyphs
= nSet
;
2934 if((dwFlags
&GCP_REORDER
)==0 )
2936 /* Treat the case where no special handling was requested in a fastpath way */
2937 /* copy will do if the GCP_REORDER flag is not set */
2938 if(lpResults
->lpOutString
)
2939 memcpy( lpResults
->lpOutString
, lpString
, nSet
* sizeof(WCHAR
));
2941 if(lpResults
->lpOrder
)
2943 for(i
= 0; i
< nSet
; i
++)
2944 lpResults
->lpOrder
[i
] = i
;
2948 BIDI_Reorder(NULL
, lpString
, uCount
, dwFlags
, WINE_GCPW_FORCE_LTR
, lpResults
->lpOutString
,
2949 nSet
, lpResults
->lpOrder
, NULL
, NULL
);
2952 /* FIXME: Will use the placement chars */
2953 if (lpResults
->lpDx
)
2956 for (i
= 0; i
< nSet
; i
++)
2958 if (GetCharWidth32W(hdc
, lpString
[i
], lpString
[i
], &c
))
2959 lpResults
->lpDx
[i
]= c
;
2963 if (lpResults
->lpCaretPos
&& !(dwFlags
& GCP_REORDER
))
2967 lpResults
->lpCaretPos
[0] = 0;
2968 for (i
= 1; i
< nSet
; i
++)
2969 if (GetTextExtentPoint32W(hdc
, &(lpString
[i
- 1]), 1, &size
))
2970 lpResults
->lpCaretPos
[i
] = (pos
+= size
.cx
);
2973 if(lpResults
->lpGlyphs
)
2974 GetGlyphIndicesW(hdc
, lpString
, nSet
, lpResults
->lpGlyphs
, 0);
2976 if (GetTextExtentPoint32W(hdc
, lpString
, uCount
, &size
))
2977 ret
= MAKELONG(size
.cx
, size
.cy
);
2982 /*************************************************************************
2983 * GetCharABCWidthsFloatA [GDI32.@]
2985 * See GetCharABCWidthsFloatW.
2987 BOOL WINAPI
GetCharABCWidthsFloatA( HDC hdc
, UINT first
, UINT last
, LPABCFLOAT abcf
)
2994 str
= FONT_GetCharsByRangeA(hdc
, first
, last
, &i
);
2998 wstr
= FONT_mbtowc( hdc
, str
, i
, &wlen
, NULL
);
3000 for (i
= 0; i
< wlen
; i
++)
3002 if (!GetCharABCWidthsFloatW( hdc
, wstr
[i
], wstr
[i
], abcf
))
3010 HeapFree( GetProcessHeap(), 0, str
);
3011 HeapFree( GetProcessHeap(), 0, wstr
);
3016 /*************************************************************************
3017 * GetCharABCWidthsFloatW [GDI32.@]
3019 * Retrieves widths of a range of characters.
3022 * hdc [I] Handle to device context.
3023 * first [I] First character in range to query.
3024 * last [I] Last character in range to query.
3025 * abcf [O] Array of LPABCFLOAT structures.
3031 BOOL WINAPI
GetCharABCWidthsFloatW( HDC hdc
, UINT first
, UINT last
, LPABCFLOAT abcf
)
3037 DC
*dc
= get_dc_ptr( hdc
);
3039 TRACE("%p, %d, %d, %p\n", hdc
, first
, last
, abcf
);
3041 if (!dc
) return FALSE
;
3043 if (!abcf
) goto done
;
3044 if (!(abc
= HeapAlloc( GetProcessHeap(), 0, (last
- first
+ 1) * sizeof(*abc
) ))) goto done
;
3046 dev
= GET_DC_PHYSDEV( dc
, pGetCharABCWidths
);
3047 ret
= dev
->funcs
->pGetCharABCWidths( dev
, first
, last
, abc
);
3050 /* convert device units to logical */
3051 for (i
= first
; i
<= last
; i
++, abcf
++)
3053 abcf
->abcfA
= abc
->abcA
* dc
->xformVport2World
.eM11
;
3054 abcf
->abcfB
= abc
->abcB
* dc
->xformVport2World
.eM11
;
3055 abcf
->abcfC
= abc
->abcC
* dc
->xformVport2World
.eM11
;
3058 HeapFree( GetProcessHeap(), 0, abc
);
3061 release_dc_ptr( dc
);
3065 /*************************************************************************
3066 * GetCharWidthFloatA [GDI32.@]
3068 BOOL WINAPI
GetCharWidthFloatA(HDC hdc
, UINT iFirstChar
,
3069 UINT iLastChar
, PFLOAT pxBuffer
)
3071 FIXME("%p, %u, %u, %p: stub!\n", hdc
, iFirstChar
, iLastChar
, pxBuffer
);
3075 /*************************************************************************
3076 * GetCharWidthFloatW [GDI32.@]
3078 BOOL WINAPI
GetCharWidthFloatW(HDC hdc
, UINT iFirstChar
,
3079 UINT iLastChar
, PFLOAT pxBuffer
)
3081 FIXME("%p, %u, %u, %p: stub!\n", hdc
, iFirstChar
, iLastChar
, pxBuffer
);
3086 /***********************************************************************
3088 * Font Resource API *
3090 ***********************************************************************/
3092 /***********************************************************************
3093 * AddFontResourceA (GDI32.@)
3095 INT WINAPI
AddFontResourceA( LPCSTR str
)
3097 return AddFontResourceExA( str
, 0, NULL
);
3100 /***********************************************************************
3101 * AddFontResourceW (GDI32.@)
3103 INT WINAPI
AddFontResourceW( LPCWSTR str
)
3105 return AddFontResourceExW(str
, 0, NULL
);
3109 /***********************************************************************
3110 * AddFontResourceExA (GDI32.@)
3112 INT WINAPI
AddFontResourceExA( LPCSTR str
, DWORD fl
, PVOID pdv
)
3114 DWORD len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
3115 LPWSTR strW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3118 MultiByteToWideChar(CP_ACP
, 0, str
, -1, strW
, len
);
3119 ret
= AddFontResourceExW(strW
, fl
, pdv
);
3120 HeapFree(GetProcessHeap(), 0, strW
);
3124 static BOOL CALLBACK
load_enumed_resource(HMODULE hModule
, LPCWSTR type
, LPWSTR name
, LONG_PTR lParam
)
3126 HRSRC rsrc
= FindResourceW(hModule
, name
, type
);
3127 HGLOBAL hMem
= LoadResource(hModule
, rsrc
);
3128 LPVOID
*pMem
= LockResource(hMem
);
3129 int *num_total
= (int *)lParam
;
3132 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type
));
3133 if (!AddFontMemResourceEx(pMem
, SizeofResource(hModule
, rsrc
), NULL
, &num_in_res
))
3135 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule
, hMem
);
3139 *num_total
+= num_in_res
;
3143 /***********************************************************************
3144 * AddFontResourceExW (GDI32.@)
3146 INT WINAPI
AddFontResourceExW( LPCWSTR str
, DWORD fl
, PVOID pdv
)
3148 int ret
= WineEngAddFontResourceEx(str
, fl
, pdv
);
3151 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3152 HMODULE hModule
= LoadLibraryExW(str
, NULL
, LOAD_LIBRARY_AS_DATAFILE
);
3153 if (hModule
!= NULL
)
3155 int num_resources
= 0;
3156 LPWSTR rt_font
= (LPWSTR
)((ULONG_PTR
)8); /* we don't want to include winuser.h */
3158 TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3159 wine_dbgstr_w(str
));
3160 if (EnumResourceNamesW(hModule
, rt_font
, load_enumed_resource
, (LONG_PTR
)&num_resources
))
3161 ret
= num_resources
;
3162 FreeLibrary(hModule
);
3168 /***********************************************************************
3169 * RemoveFontResourceA (GDI32.@)
3171 BOOL WINAPI
RemoveFontResourceA( LPCSTR str
)
3173 return RemoveFontResourceExA(str
, 0, 0);
3176 /***********************************************************************
3177 * RemoveFontResourceW (GDI32.@)
3179 BOOL WINAPI
RemoveFontResourceW( LPCWSTR str
)
3181 return RemoveFontResourceExW(str
, 0, 0);
3184 /***********************************************************************
3185 * AddFontMemResourceEx (GDI32.@)
3187 HANDLE WINAPI
AddFontMemResourceEx( PVOID pbFont
, DWORD cbFont
, PVOID pdv
, DWORD
*pcFonts
)
3192 if (!pbFont
|| !cbFont
|| !pcFonts
)
3194 SetLastError(ERROR_INVALID_PARAMETER
);
3198 ret
= WineEngAddFontMemResourceEx(pbFont
, cbFont
, pdv
, &num_fonts
);
3203 *pcFonts
= num_fonts
;
3207 WARN("page fault while writing to *pcFonts (%p)\n", pcFonts
);
3208 RemoveFontMemResourceEx(ret
);
3216 /***********************************************************************
3217 * RemoveFontMemResourceEx (GDI32.@)
3219 BOOL WINAPI
RemoveFontMemResourceEx( HANDLE fh
)
3221 FIXME("(%p) stub\n", fh
);
3225 /***********************************************************************
3226 * RemoveFontResourceExA (GDI32.@)
3228 BOOL WINAPI
RemoveFontResourceExA( LPCSTR str
, DWORD fl
, PVOID pdv
)
3230 DWORD len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
3231 LPWSTR strW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3234 MultiByteToWideChar(CP_ACP
, 0, str
, -1, strW
, len
);
3235 ret
= RemoveFontResourceExW(strW
, fl
, pdv
);
3236 HeapFree(GetProcessHeap(), 0, strW
);
3240 /***********************************************************************
3241 * RemoveFontResourceExW (GDI32.@)
3243 BOOL WINAPI
RemoveFontResourceExW( LPCWSTR str
, DWORD fl
, PVOID pdv
)
3245 return WineEngRemoveFontResourceEx(str
, fl
, pdv
);
3248 /***********************************************************************
3249 * GetTextCharset (GDI32.@)
3251 UINT WINAPI
GetTextCharset(HDC hdc
)
3253 /* MSDN docs say this is equivalent */
3254 return GetTextCharsetInfo(hdc
, NULL
, 0);
3257 /***********************************************************************
3258 * GetTextCharsetInfo (GDI32.@)
3260 UINT WINAPI
GetTextCharsetInfo(HDC hdc
, LPFONTSIGNATURE fs
, DWORD flags
)
3262 UINT ret
= DEFAULT_CHARSET
;
3263 DC
*dc
= get_dc_ptr(hdc
);
3268 ret
= WineEngGetTextCharsetInfo(dc
->gdiFont
, fs
, flags
);
3270 release_dc_ptr( dc
);
3273 if (ret
== DEFAULT_CHARSET
&& fs
)
3274 memset(fs
, 0, sizeof(FONTSIGNATURE
));
3278 /***********************************************************************
3279 * GdiGetCharDimensions (GDI32.@)
3281 * Gets the average width of the characters in the English alphabet.
3284 * hdc [I] Handle to the device context to measure on.
3285 * lptm [O] Pointer to memory to store the text metrics into.
3286 * height [O] On exit, the maximum height of characters in the English alphabet.
3289 * The average width of characters in the English alphabet.
3292 * This function is used by the dialog manager to get the size of a dialog
3293 * unit. It should also be used by other pieces of code that need to know
3294 * the size of a dialog unit in logical units without having access to the
3295 * window handle of the dialog.
3296 * Windows caches the font metrics from this function, but we don't and
3297 * there doesn't appear to be an immediate advantage to do so.
3300 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3302 LONG WINAPI
GdiGetCharDimensions(HDC hdc
, LPTEXTMETRICW lptm
, LONG
*height
)
3305 static const WCHAR alphabet
[] = {
3306 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3307 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3308 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3310 if(lptm
&& !GetTextMetricsW(hdc
, lptm
)) return 0;
3312 if(!GetTextExtentPointW(hdc
, alphabet
, 52, &sz
)) return 0;
3314 if (height
) *height
= sz
.cy
;
3315 return (sz
.cx
/ 26 + 1) / 2;
3318 BOOL WINAPI
EnableEUDC(BOOL fEnableEUDC
)
3320 FIXME("(%d): stub\n", fEnableEUDC
);
3324 /***********************************************************************
3325 * GetCharWidthI (GDI32.@)
3327 * Retrieve widths of characters.
3330 * hdc [I] Handle to a device context.
3331 * first [I] First glyph in range to query.
3332 * count [I] Number of glyph indices to query.
3333 * glyphs [I] Array of glyphs to query.
3334 * buffer [O] Buffer to receive character widths.
3337 * Only works with TrueType fonts.
3343 BOOL WINAPI
GetCharWidthI(HDC hdc
, UINT first
, UINT count
, LPWORD glyphs
, LPINT buffer
)
3348 TRACE("(%p, %d, %d, %p, %p)\n", hdc
, first
, count
, glyphs
, buffer
);
3350 if (!(abc
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(ABC
))))
3353 if (!GetCharABCWidthsI(hdc
, first
, count
, glyphs
, abc
))
3355 HeapFree(GetProcessHeap(), 0, abc
);
3359 for (i
= 0; i
< count
; i
++)
3360 buffer
[i
] = abc
->abcA
+ abc
->abcB
+ abc
->abcC
;
3362 HeapFree(GetProcessHeap(), 0, abc
);
3366 /***********************************************************************
3367 * GetFontUnicodeRanges (GDI32.@)
3369 * Retrieve a list of supported Unicode characters in a font.
3372 * hdc [I] Handle to a device context.
3373 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3376 * Success: Number of bytes written to the buffer pointed to by lpgs.
3380 DWORD WINAPI
GetFontUnicodeRanges(HDC hdc
, LPGLYPHSET lpgs
)
3384 DC
*dc
= get_dc_ptr(hdc
);
3386 TRACE("(%p, %p)\n", hdc
, lpgs
);
3390 dev
= GET_DC_PHYSDEV( dc
, pGetFontUnicodeRanges
);
3391 ret
= dev
->funcs
->pGetFontUnicodeRanges( dev
, lpgs
);
3397 /*************************************************************
3398 * FontIsLinked (GDI32.@)
3400 BOOL WINAPI
FontIsLinked(HDC hdc
)
3402 DC
*dc
= get_dc_ptr(hdc
);
3405 if (!dc
) return FALSE
;
3406 if (dc
->gdiFont
) ret
= WineEngFontIsLinked(dc
->gdiFont
);
3408 TRACE("returning %d\n", ret
);
3412 /*************************************************************
3413 * GdiRealizationInfo (GDI32.@)
3415 * Returns a structure that contains some font information.
3417 BOOL WINAPI
GdiRealizationInfo(HDC hdc
, realization_info_t
*info
)
3419 DC
*dc
= get_dc_ptr(hdc
);
3422 if (!dc
) return FALSE
;
3423 if (dc
->gdiFont
) ret
= WineEngRealizationInfo(dc
->gdiFont
, info
);