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
= GetTextCharsetInfo( dc
->hSelf
, NULL
, 0 );
477 /* Hmm, nicely designed api this one! */
478 if (TranslateCharsetInfo( ULongToPtr(charset
), &csi
, TCI_SRCCHARSET
) )
479 dc
->font_code_page
= csi
.ciACP
;
483 dc
->font_code_page
= GetOEMCP();
485 case DEFAULT_CHARSET
:
486 dc
->font_code_page
= GetACP();
496 /* FIXME: These have no place here, but because x11drv
497 enumerates fonts with these (made up) charsets some apps
498 might use them and then the FIXME below would become
499 annoying. Now we could pick the intended codepage for
500 each of these, but since it's broken anyway we'll just
501 use CP_ACP and hope it'll go away...
503 dc
->font_code_page
= CP_ACP
;
507 FIXME("Can't find codepage for charset %d\n", charset
);
508 dc
->font_code_page
= CP_ACP
;
513 TRACE("charset %d => cp %d\n", charset
, dc
->font_code_page
);
516 /***********************************************************************
519 static HGDIOBJ
FONT_SelectObject( HGDIOBJ handle
, HDC hdc
)
522 DC
*dc
= get_dc_ptr( hdc
);
527 if (!GDI_inc_ref_count( handle
))
529 release_dc_ptr( dc
);
533 physdev
= GET_DC_PHYSDEV( dc
, pSelectFont
);
534 if (physdev
->funcs
->pSelectFont( physdev
, handle
))
538 update_font_code_page( dc
);
539 GDI_dec_ref_count( ret
);
541 else GDI_dec_ref_count( handle
);
543 release_dc_ptr( dc
);
548 /***********************************************************************
551 static INT
FONT_GetObjectA( HGDIOBJ handle
, INT count
, LPVOID buffer
)
553 FONTOBJ
*font
= GDI_GetObjPtr( handle
, OBJ_FONT
);
559 FONT_LogFontWToA( &font
->logfont
, &lfA
);
560 if (count
> sizeof(lfA
)) count
= sizeof(lfA
);
561 memcpy( buffer
, &lfA
, count
);
563 else count
= sizeof(lfA
);
564 GDI_ReleaseObj( handle
);
568 /***********************************************************************
571 static INT
FONT_GetObjectW( HGDIOBJ handle
, INT count
, LPVOID buffer
)
573 FONTOBJ
*font
= GDI_GetObjPtr( handle
, OBJ_FONT
);
578 if (count
> sizeof(LOGFONTW
)) count
= sizeof(LOGFONTW
);
579 memcpy( buffer
, &font
->logfont
, count
);
581 else count
= sizeof(LOGFONTW
);
582 GDI_ReleaseObj( handle
);
587 /***********************************************************************
590 static BOOL
FONT_DeleteObject( HGDIOBJ handle
)
594 WineEngDestroyFontInstance( handle
);
596 if (!(obj
= free_gdi_handle( handle
))) return FALSE
;
597 return HeapFree( GetProcessHeap(), 0, obj
);
601 /***********************************************************************
604 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
605 * We have to use other types because of the FONTENUMPROCW definition.
607 static INT CALLBACK
FONT_EnumInstance( const LOGFONTW
*plf
, const TEXTMETRICW
*ptm
,
608 DWORD fType
, LPARAM lp
)
610 struct font_enum
*pfe
= (struct font_enum
*)lp
;
613 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
614 if ((!pfe
->lpLogFontParam
||
615 pfe
->lpLogFontParam
->lfCharSet
== DEFAULT_CHARSET
||
616 pfe
->lpLogFontParam
->lfCharSet
== plf
->lfCharSet
) &&
617 (!(fType
& RASTER_FONTTYPE
) || GetDeviceCaps(pfe
->hdc
, TEXTCAPS
) & TC_RA_ABLE
) )
619 /* convert font metrics */
620 ENUMLOGFONTEXA logfont
;
621 NEWTEXTMETRICEXA tmA
;
625 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW
*)plf
, &logfont
);
626 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW
*)ptm
, &tmA
);
627 plf
= (LOGFONTW
*)&logfont
.elfLogFont
;
628 ptm
= (TEXTMETRICW
*)&tmA
;
630 ret
= pfe
->lpEnumFunc( plf
, ptm
, fType
, pfe
->lpData
);
635 /***********************************************************************
636 * FONT_EnumFontFamiliesEx
638 static INT
FONT_EnumFontFamiliesEx( HDC hDC
, LPLOGFONTW plf
, FONTENUMPROCW efproc
,
639 LPARAM lParam
, BOOL unicode
)
642 DC
*dc
= get_dc_ptr( hDC
);
647 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pEnumFonts
);
649 if (plf
) TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf
->lfFaceName
), plf
->lfCharSet
);
650 fe
.lpLogFontParam
= plf
;
651 fe
.lpEnumFunc
= efproc
;
653 fe
.unicode
= unicode
;
655 ret
= physdev
->funcs
->pEnumFonts( physdev
, plf
, FONT_EnumInstance
, (LPARAM
)&fe
);
656 release_dc_ptr( dc
);
661 /***********************************************************************
662 * EnumFontFamiliesExW (GDI32.@)
664 INT WINAPI
EnumFontFamiliesExW( HDC hDC
, LPLOGFONTW plf
,
665 FONTENUMPROCW efproc
,
666 LPARAM lParam
, DWORD dwFlags
)
668 return FONT_EnumFontFamiliesEx( hDC
, plf
, efproc
, lParam
, TRUE
);
671 /***********************************************************************
672 * EnumFontFamiliesExA (GDI32.@)
674 INT WINAPI
EnumFontFamiliesExA( HDC hDC
, LPLOGFONTA plf
,
675 FONTENUMPROCA efproc
,
676 LPARAM lParam
, DWORD dwFlags
)
682 FONT_LogFontAToW( plf
, &lfW
);
687 return FONT_EnumFontFamiliesEx( hDC
, plfW
, (FONTENUMPROCW
)efproc
, lParam
, FALSE
);
690 /***********************************************************************
691 * EnumFontFamiliesA (GDI32.@)
693 INT WINAPI
EnumFontFamiliesA( HDC hDC
, LPCSTR lpFamily
,
694 FONTENUMPROCA efproc
, LPARAM lpData
)
700 if (!*lpFamily
) return 1;
701 lstrcpynA( lf
.lfFaceName
, lpFamily
, LF_FACESIZE
);
702 lf
.lfCharSet
= DEFAULT_CHARSET
;
703 lf
.lfPitchAndFamily
= 0;
708 return EnumFontFamiliesExA( hDC
, plf
, efproc
, lpData
, 0 );
711 /***********************************************************************
712 * EnumFontFamiliesW (GDI32.@)
714 INT WINAPI
EnumFontFamiliesW( HDC hDC
, LPCWSTR lpFamily
,
715 FONTENUMPROCW efproc
, LPARAM lpData
)
721 if (!*lpFamily
) return 1;
722 lstrcpynW( lf
.lfFaceName
, lpFamily
, LF_FACESIZE
);
723 lf
.lfCharSet
= DEFAULT_CHARSET
;
724 lf
.lfPitchAndFamily
= 0;
729 return EnumFontFamiliesExW( hDC
, plf
, efproc
, lpData
, 0 );
732 /***********************************************************************
733 * EnumFontsA (GDI32.@)
735 INT WINAPI
EnumFontsA( HDC hDC
, LPCSTR lpName
, FONTENUMPROCA efproc
,
738 return EnumFontFamiliesA( hDC
, lpName
, efproc
, lpData
);
741 /***********************************************************************
742 * EnumFontsW (GDI32.@)
744 INT WINAPI
EnumFontsW( HDC hDC
, LPCWSTR lpName
, FONTENUMPROCW efproc
,
747 return EnumFontFamiliesW( hDC
, lpName
, efproc
, lpData
);
751 /***********************************************************************
752 * GetTextCharacterExtra (GDI32.@)
754 INT WINAPI
GetTextCharacterExtra( HDC hdc
)
757 DC
*dc
= get_dc_ptr( hdc
);
758 if (!dc
) return 0x80000000;
760 release_dc_ptr( dc
);
765 /***********************************************************************
766 * SetTextCharacterExtra (GDI32.@)
768 INT WINAPI
SetTextCharacterExtra( HDC hdc
, INT extra
)
770 INT ret
= 0x80000000;
771 DC
* dc
= get_dc_ptr( hdc
);
775 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetTextCharacterExtra
);
776 extra
= physdev
->funcs
->pSetTextCharacterExtra( physdev
, extra
);
777 if (extra
!= 0x80000000)
780 dc
->charExtra
= extra
;
782 release_dc_ptr( dc
);
788 /***********************************************************************
789 * SetTextJustification (GDI32.@)
791 BOOL WINAPI
SetTextJustification( HDC hdc
, INT extra
, INT breaks
)
795 DC
* dc
= get_dc_ptr( hdc
);
797 if (!dc
) return FALSE
;
799 physdev
= GET_DC_PHYSDEV( dc
, pSetTextJustification
);
800 ret
= physdev
->funcs
->pSetTextJustification( physdev
, extra
, breaks
);
803 extra
= abs((extra
* dc
->vportExtX
+ dc
->wndExtX
/ 2) / dc
->wndExtX
);
804 if (!extra
) breaks
= 0;
807 dc
->breakExtra
= extra
/ breaks
;
808 dc
->breakRem
= extra
- (breaks
* dc
->breakExtra
);
816 release_dc_ptr( dc
);
821 /***********************************************************************
822 * GetTextFaceA (GDI32.@)
824 INT WINAPI
GetTextFaceA( HDC hdc
, INT count
, LPSTR name
)
826 INT res
= GetTextFaceW(hdc
, 0, NULL
);
827 LPWSTR nameW
= HeapAlloc( GetProcessHeap(), 0, res
* 2 );
828 GetTextFaceW( hdc
, res
, nameW
);
834 res
= WideCharToMultiByte(CP_ACP
, 0, nameW
, -1, name
, count
, NULL
, NULL
);
838 /* GetTextFaceA does NOT include the nul byte in the return count. */
845 res
= WideCharToMultiByte( CP_ACP
, 0, nameW
, -1, NULL
, 0, NULL
, NULL
);
846 HeapFree( GetProcessHeap(), 0, nameW
);
850 /***********************************************************************
851 * GetTextFaceW (GDI32.@)
853 INT WINAPI
GetTextFaceW( HDC hdc
, INT count
, LPWSTR name
)
858 DC
* dc
= get_dc_ptr( hdc
);
861 dev
= GET_DC_PHYSDEV( dc
, pGetTextFace
);
862 ret
= dev
->funcs
->pGetTextFace( dev
, count
, name
);
863 release_dc_ptr( dc
);
868 /***********************************************************************
869 * GetTextExtentPoint32A (GDI32.@)
871 * See GetTextExtentPoint32W.
873 BOOL WINAPI
GetTextExtentPoint32A( HDC hdc
, LPCSTR str
, INT count
,
880 if (count
< 0) return FALSE
;
882 p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
886 ret
= GetTextExtentPoint32W( hdc
, p
, wlen
, size
);
887 HeapFree( GetProcessHeap(), 0, p
);
890 TRACE("(%p %s %d %p): returning %d x %d\n",
891 hdc
, debugstr_an (str
, count
), count
, size
, size
->cx
, size
->cy
);
896 /***********************************************************************
897 * GetTextExtentPoint32W [GDI32.@]
899 * Computes width/height for a string.
901 * Computes width and height of the specified string.
907 BOOL WINAPI
GetTextExtentPoint32W(
908 HDC hdc
, /* [in] Handle of device context */
909 LPCWSTR str
, /* [in] Address of text string */
910 INT count
, /* [in] Number of characters in string */
911 LPSIZE size
) /* [out] Address of structure for string size */
913 return GetTextExtentExPointW(hdc
, str
, count
, 0, NULL
, NULL
, size
);
916 /***********************************************************************
917 * GetTextExtentExPointI [GDI32.@]
919 * Computes width and height of the array of glyph indices.
922 * hdc [I] Handle of device context.
923 * indices [I] Glyph index array.
924 * count [I] Number of glyphs in array.
925 * max_ext [I] Maximum width in glyphs.
926 * nfit [O] Maximum number of characters.
927 * dxs [O] Partial string widths.
928 * size [O] Returned string size.
934 BOOL WINAPI
GetTextExtentExPointI( HDC hdc
, const WORD
*indices
, INT count
, INT max_ext
,
935 LPINT nfit
, LPINT dxs
, LPSIZE size
)
941 if (count
< 0) return FALSE
;
943 dc
= get_dc_ptr( hdc
);
944 if (!dc
) return FALSE
;
946 dev
= GET_DC_PHYSDEV( dc
, pGetTextExtentExPointI
);
947 ret
= dev
->funcs
->pGetTextExtentExPointI( dev
, indices
, count
, max_ext
, nfit
, dxs
, size
);
948 size
->cx
= abs(INTERNAL_XDSTOWS(dc
, size
->cx
));
949 size
->cy
= abs(INTERNAL_YDSTOWS(dc
, size
->cy
));
950 size
->cx
+= count
* dc
->charExtra
;
951 release_dc_ptr( dc
);
953 TRACE("(%p %p %d %p): returning %d x %d\n",
954 hdc
, indices
, count
, size
, size
->cx
, size
->cy
);
958 /***********************************************************************
959 * GetTextExtentPointI [GDI32.@]
961 * Computes width and height of the array of glyph indices.
964 * hdc [I] Handle of device context.
965 * indices [I] Glyph index array.
966 * count [I] Number of glyphs in array.
967 * size [O] Returned string size.
973 BOOL WINAPI
GetTextExtentPointI( HDC hdc
, const WORD
*indices
, INT count
, LPSIZE size
)
975 return GetTextExtentExPointI( hdc
, indices
, count
, 0, NULL
, NULL
, size
);
979 /***********************************************************************
980 * GetTextExtentPointA (GDI32.@)
982 BOOL WINAPI
GetTextExtentPointA( HDC hdc
, LPCSTR str
, INT count
,
985 TRACE("not bug compatible.\n");
986 return GetTextExtentPoint32A( hdc
, str
, count
, size
);
989 /***********************************************************************
990 * GetTextExtentPointW (GDI32.@)
992 BOOL WINAPI
GetTextExtentPointW( HDC hdc
, LPCWSTR str
, INT count
,
995 TRACE("not bug compatible.\n");
996 return GetTextExtentPoint32W( hdc
, str
, count
, size
);
1000 /***********************************************************************
1001 * GetTextExtentExPointA (GDI32.@)
1003 BOOL WINAPI
GetTextExtentExPointA( HDC hdc
, LPCSTR str
, INT count
,
1004 INT maxExt
, LPINT lpnFit
,
1005 LPINT alpDx
, LPSIZE size
)
1012 if (count
< 0) return FALSE
;
1016 walpDx
= HeapAlloc( GetProcessHeap(), 0, count
* sizeof(INT
) );
1017 if (!walpDx
) return FALSE
;
1020 p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
1021 ret
= GetTextExtentExPointW( hdc
, p
, wlen
, maxExt
, lpnFit
, walpDx
, size
);
1024 INT n
= lpnFit
? *lpnFit
: wlen
;
1026 for(i
= 0, j
= 0; i
< n
; i
++, j
++)
1028 alpDx
[j
] = walpDx
[i
];
1029 if (IsDBCSLeadByte(str
[j
])) alpDx
[++j
] = walpDx
[i
];
1032 if (lpnFit
) *lpnFit
= WideCharToMultiByte(CP_ACP
,0,p
,*lpnFit
,NULL
,0,NULL
,NULL
);
1033 HeapFree( GetProcessHeap(), 0, p
);
1034 HeapFree( GetProcessHeap(), 0, walpDx
);
1039 /***********************************************************************
1040 * GetTextExtentExPointW (GDI32.@)
1042 * Return the size of the string as it would be if it was output properly by
1045 * This should include
1046 * - Intercharacter spacing
1047 * - justification spacing (not yet done)
1048 * - kerning? see below
1050 * Kerning. Since kerning would be carried out by the rendering code it should
1051 * be done by the driver. However they don't support it yet. Also I am not
1052 * yet persuaded that (certainly under Win95) any kerning is actually done.
1054 * str: According to MSDN this should be null-terminated. That is not true; a
1055 * null will not terminate it early.
1056 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1057 * than count. I have seen it be either the size of the full string or
1058 * 1 less than the size of the full string. I have not seen it bear any
1059 * resemblance to the portion that would fit.
1060 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1061 * trailing intercharacter spacing and any trailing justification.
1064 * Currently we do this by measuring each character etc. We should do it by
1065 * passing the request to the driver, perhaps by extending the
1066 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1067 * thinking about kerning issues and rounding issues in the justification.
1070 BOOL WINAPI
GetTextExtentExPointW( HDC hdc
, LPCWSTR str
, INT count
,
1071 INT maxExt
, LPINT lpnFit
,
1072 LPINT alpDx
, LPSIZE size
)
1081 TRACE("(%p, %s, %d)\n",hdc
,debugstr_wn(str
,count
),maxExt
);
1083 if (count
< 0) return FALSE
;
1085 dc
= get_dc_ptr(hdc
);
1086 if (!dc
) return FALSE
;
1088 GetTextMetricsW(hdc
, &tm
);
1090 /* If we need to calculate nFit, then we need the partial extents even if
1091 the user hasn't provided us with an array. */
1094 dxs
= alpDx
? alpDx
: HeapAlloc(GetProcessHeap(), 0, count
* sizeof alpDx
[0]);
1098 SetLastError(ERROR_OUTOFMEMORY
);
1105 dev
= GET_DC_PHYSDEV( dc
, pGetTextExtentExPoint
);
1106 ret
= dev
->funcs
->pGetTextExtentExPoint(dev
, str
, count
, 0, NULL
, dxs
, size
);
1108 /* Perform device size to world size transformations. */
1111 INT extra
= dc
->charExtra
,
1112 breakExtra
= dc
->breakExtra
,
1113 breakRem
= dc
->breakRem
,
1118 for (i
= 0; i
< count
; ++i
)
1120 dxs
[i
] = abs(INTERNAL_XDSTOWS(dc
, dxs
[i
]));
1121 dxs
[i
] += (i
+1) * extra
;
1122 if (count
> 1 && (breakExtra
|| breakRem
) && str
[i
] == tm
.tmBreakChar
)
1124 dxs
[i
] += breakExtra
;
1131 if (dxs
[i
] <= maxExt
)
1134 breakRem
= dc
->breakRem
;
1136 size
->cx
= abs(INTERNAL_XDSTOWS(dc
, size
->cx
));
1137 size
->cy
= abs(INTERNAL_YDSTOWS(dc
, size
->cy
));
1139 if (!dxs
&& count
> 1 && (breakExtra
|| breakRem
))
1141 for (i
= 0; i
< count
; i
++)
1143 if (str
[i
] == tm
.tmBreakChar
)
1145 size
->cx
+= breakExtra
;
1160 HeapFree(GetProcessHeap(), 0, dxs
);
1162 release_dc_ptr( dc
);
1164 TRACE("returning %d %d x %d\n",nFit
,size
->cx
,size
->cy
);
1168 /***********************************************************************
1169 * GetTextMetricsA (GDI32.@)
1171 BOOL WINAPI
GetTextMetricsA( HDC hdc
, TEXTMETRICA
*metrics
)
1175 if (!GetTextMetricsW( hdc
, &tm32
)) return FALSE
;
1176 FONT_TextMetricWToA( &tm32
, metrics
);
1180 /***********************************************************************
1181 * GetTextMetricsW (GDI32.@)
1183 BOOL WINAPI
GetTextMetricsW( HDC hdc
, TEXTMETRICW
*metrics
)
1187 DC
* dc
= get_dc_ptr( hdc
);
1188 if (!dc
) return FALSE
;
1190 physdev
= GET_DC_PHYSDEV( dc
, pGetTextMetrics
);
1191 ret
= physdev
->funcs
->pGetTextMetrics( physdev
, metrics
);
1195 /* device layer returns values in device units
1196 * therefore we have to convert them to logical */
1198 metrics
->tmDigitizedAspectX
= GetDeviceCaps(hdc
, LOGPIXELSX
);
1199 metrics
->tmDigitizedAspectY
= GetDeviceCaps(hdc
, LOGPIXELSY
);
1201 #define WDPTOLP(x) ((x<0)? \
1202 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1203 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1204 #define HDPTOLP(y) ((y<0)? \
1205 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1206 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1208 metrics
->tmHeight
= HDPTOLP(metrics
->tmHeight
);
1209 metrics
->tmAscent
= HDPTOLP(metrics
->tmAscent
);
1210 metrics
->tmDescent
= HDPTOLP(metrics
->tmDescent
);
1211 metrics
->tmInternalLeading
= HDPTOLP(metrics
->tmInternalLeading
);
1212 metrics
->tmExternalLeading
= HDPTOLP(metrics
->tmExternalLeading
);
1213 metrics
->tmAveCharWidth
= WDPTOLP(metrics
->tmAveCharWidth
);
1214 metrics
->tmMaxCharWidth
= WDPTOLP(metrics
->tmMaxCharWidth
);
1215 metrics
->tmOverhang
= WDPTOLP(metrics
->tmOverhang
);
1219 TRACE("text metrics:\n"
1220 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1221 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1222 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1223 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1224 " PitchAndFamily = %02x\n"
1225 " --------------------\n"
1226 " InternalLeading = %i\n"
1230 metrics
->tmWeight
, metrics
->tmFirstChar
, metrics
->tmAveCharWidth
,
1231 metrics
->tmItalic
, metrics
->tmLastChar
, metrics
->tmMaxCharWidth
,
1232 metrics
->tmUnderlined
, metrics
->tmDefaultChar
, metrics
->tmOverhang
,
1233 metrics
->tmStruckOut
, metrics
->tmBreakChar
, metrics
->tmCharSet
,
1234 metrics
->tmPitchAndFamily
,
1235 metrics
->tmInternalLeading
,
1238 metrics
->tmHeight
);
1240 release_dc_ptr( dc
);
1245 /***********************************************************************
1246 * GetOutlineTextMetricsA (GDI32.@)
1247 * Gets metrics for TrueType fonts.
1250 * If the supplied buffer isn't big enough Windows partially fills it up to
1251 * its given length and returns that length.
1254 * Success: Non-zero or size of required buffer
1257 UINT WINAPI
GetOutlineTextMetricsA(
1258 HDC hdc
, /* [in] Handle of device context */
1259 UINT cbData
, /* [in] Size of metric data array */
1260 LPOUTLINETEXTMETRICA lpOTM
) /* [out] Address of metric data array */
1262 char buf
[512], *ptr
;
1264 OUTLINETEXTMETRICW
*lpOTMW
= (OUTLINETEXTMETRICW
*)buf
;
1265 OUTLINETEXTMETRICA
*output
= lpOTM
;
1268 if((ret
= GetOutlineTextMetricsW(hdc
, 0, NULL
)) == 0)
1270 if(ret
> sizeof(buf
))
1271 lpOTMW
= HeapAlloc(GetProcessHeap(), 0, ret
);
1272 GetOutlineTextMetricsW(hdc
, ret
, lpOTMW
);
1274 needed
= sizeof(OUTLINETEXTMETRICA
);
1275 if(lpOTMW
->otmpFamilyName
)
1276 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1277 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFamilyName
), -1,
1278 NULL
, 0, NULL
, NULL
);
1279 if(lpOTMW
->otmpFaceName
)
1280 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1281 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFaceName
), -1,
1282 NULL
, 0, NULL
, NULL
);
1283 if(lpOTMW
->otmpStyleName
)
1284 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1285 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpStyleName
), -1,
1286 NULL
, 0, NULL
, NULL
);
1287 if(lpOTMW
->otmpFullName
)
1288 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1289 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFullName
), -1,
1290 NULL
, 0, NULL
, NULL
);
1297 TRACE("needed = %d\n", needed
);
1299 /* Since the supplied buffer isn't big enough, we'll alloc one
1300 that is and memcpy the first cbData bytes into the lpOTM at
1302 output
= HeapAlloc(GetProcessHeap(), 0, needed
);
1304 ret
= output
->otmSize
= min(needed
, cbData
);
1305 FONT_TextMetricWToA( &lpOTMW
->otmTextMetrics
, &output
->otmTextMetrics
);
1306 output
->otmFiller
= 0;
1307 output
->otmPanoseNumber
= lpOTMW
->otmPanoseNumber
;
1308 output
->otmfsSelection
= lpOTMW
->otmfsSelection
;
1309 output
->otmfsType
= lpOTMW
->otmfsType
;
1310 output
->otmsCharSlopeRise
= lpOTMW
->otmsCharSlopeRise
;
1311 output
->otmsCharSlopeRun
= lpOTMW
->otmsCharSlopeRun
;
1312 output
->otmItalicAngle
= lpOTMW
->otmItalicAngle
;
1313 output
->otmEMSquare
= lpOTMW
->otmEMSquare
;
1314 output
->otmAscent
= lpOTMW
->otmAscent
;
1315 output
->otmDescent
= lpOTMW
->otmDescent
;
1316 output
->otmLineGap
= lpOTMW
->otmLineGap
;
1317 output
->otmsCapEmHeight
= lpOTMW
->otmsCapEmHeight
;
1318 output
->otmsXHeight
= lpOTMW
->otmsXHeight
;
1319 output
->otmrcFontBox
= lpOTMW
->otmrcFontBox
;
1320 output
->otmMacAscent
= lpOTMW
->otmMacAscent
;
1321 output
->otmMacDescent
= lpOTMW
->otmMacDescent
;
1322 output
->otmMacLineGap
= lpOTMW
->otmMacLineGap
;
1323 output
->otmusMinimumPPEM
= lpOTMW
->otmusMinimumPPEM
;
1324 output
->otmptSubscriptSize
= lpOTMW
->otmptSubscriptSize
;
1325 output
->otmptSubscriptOffset
= lpOTMW
->otmptSubscriptOffset
;
1326 output
->otmptSuperscriptSize
= lpOTMW
->otmptSuperscriptSize
;
1327 output
->otmptSuperscriptOffset
= lpOTMW
->otmptSuperscriptOffset
;
1328 output
->otmsStrikeoutSize
= lpOTMW
->otmsStrikeoutSize
;
1329 output
->otmsStrikeoutPosition
= lpOTMW
->otmsStrikeoutPosition
;
1330 output
->otmsUnderscoreSize
= lpOTMW
->otmsUnderscoreSize
;
1331 output
->otmsUnderscorePosition
= lpOTMW
->otmsUnderscorePosition
;
1334 ptr
= (char*)(output
+ 1);
1335 left
= needed
- sizeof(*output
);
1337 if(lpOTMW
->otmpFamilyName
) {
1338 output
->otmpFamilyName
= (LPSTR
)(ptr
- (char*)output
);
1339 len
= WideCharToMultiByte(CP_ACP
, 0,
1340 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFamilyName
), -1,
1341 ptr
, left
, NULL
, NULL
);
1345 output
->otmpFamilyName
= 0;
1347 if(lpOTMW
->otmpFaceName
) {
1348 output
->otmpFaceName
= (LPSTR
)(ptr
- (char*)output
);
1349 len
= WideCharToMultiByte(CP_ACP
, 0,
1350 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFaceName
), -1,
1351 ptr
, left
, NULL
, NULL
);
1355 output
->otmpFaceName
= 0;
1357 if(lpOTMW
->otmpStyleName
) {
1358 output
->otmpStyleName
= (LPSTR
)(ptr
- (char*)output
);
1359 len
= WideCharToMultiByte(CP_ACP
, 0,
1360 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpStyleName
), -1,
1361 ptr
, left
, NULL
, NULL
);
1365 output
->otmpStyleName
= 0;
1367 if(lpOTMW
->otmpFullName
) {
1368 output
->otmpFullName
= (LPSTR
)(ptr
- (char*)output
);
1369 len
= WideCharToMultiByte(CP_ACP
, 0,
1370 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFullName
), -1,
1371 ptr
, left
, NULL
, NULL
);
1374 output
->otmpFullName
= 0;
1378 if(output
!= lpOTM
) {
1379 memcpy(lpOTM
, output
, cbData
);
1380 HeapFree(GetProcessHeap(), 0, output
);
1382 /* check if the string offsets really fit into the provided size */
1383 /* FIXME: should we check string length as well? */
1384 /* make sure that we don't read/write beyond the provided buffer */
1385 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFamilyName
) + sizeof(LPSTR
))
1387 if ((UINT_PTR
)lpOTM
->otmpFamilyName
>= lpOTM
->otmSize
)
1388 lpOTM
->otmpFamilyName
= 0; /* doesn't fit */
1391 /* make sure that we don't read/write beyond the provided buffer */
1392 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFaceName
) + sizeof(LPSTR
))
1394 if ((UINT_PTR
)lpOTM
->otmpFaceName
>= lpOTM
->otmSize
)
1395 lpOTM
->otmpFaceName
= 0; /* doesn't fit */
1398 /* make sure that we don't read/write beyond the provided buffer */
1399 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpStyleName
) + sizeof(LPSTR
))
1401 if ((UINT_PTR
)lpOTM
->otmpStyleName
>= lpOTM
->otmSize
)
1402 lpOTM
->otmpStyleName
= 0; /* doesn't fit */
1405 /* make sure that we don't read/write beyond the provided buffer */
1406 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFullName
) + sizeof(LPSTR
))
1408 if ((UINT_PTR
)lpOTM
->otmpFullName
>= lpOTM
->otmSize
)
1409 lpOTM
->otmpFullName
= 0; /* doesn't fit */
1414 if(lpOTMW
!= (OUTLINETEXTMETRICW
*)buf
)
1415 HeapFree(GetProcessHeap(), 0, lpOTMW
);
1421 /***********************************************************************
1422 * GetOutlineTextMetricsW [GDI32.@]
1424 UINT WINAPI
GetOutlineTextMetricsW(
1425 HDC hdc
, /* [in] Handle of device context */
1426 UINT cbData
, /* [in] Size of metric data array */
1427 LPOUTLINETEXTMETRICW lpOTM
) /* [out] Address of metric data array */
1429 DC
*dc
= get_dc_ptr( hdc
);
1430 OUTLINETEXTMETRICW
*output
= lpOTM
;
1434 TRACE("(%p,%d,%p)\n", hdc
, cbData
, lpOTM
);
1437 dev
= GET_DC_PHYSDEV( dc
, pGetOutlineTextMetrics
);
1438 ret
= dev
->funcs
->pGetOutlineTextMetrics( dev
, cbData
, output
);
1440 if (lpOTM
&& ret
> cbData
)
1442 output
= HeapAlloc(GetProcessHeap(), 0, ret
);
1443 ret
= dev
->funcs
->pGetOutlineTextMetrics( dev
, ret
, output
);
1448 output
->otmTextMetrics
.tmDigitizedAspectX
= GetDeviceCaps(hdc
, LOGPIXELSX
);
1449 output
->otmTextMetrics
.tmDigitizedAspectY
= GetDeviceCaps(hdc
, LOGPIXELSY
);
1451 #define WDPTOLP(x) ((x<0)? \
1452 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1453 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1454 #define HDPTOLP(y) ((y<0)? \
1455 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1456 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1458 output
->otmTextMetrics
.tmHeight
= HDPTOLP(output
->otmTextMetrics
.tmHeight
);
1459 output
->otmTextMetrics
.tmAscent
= HDPTOLP(output
->otmTextMetrics
.tmAscent
);
1460 output
->otmTextMetrics
.tmDescent
= HDPTOLP(output
->otmTextMetrics
.tmDescent
);
1461 output
->otmTextMetrics
.tmInternalLeading
= HDPTOLP(output
->otmTextMetrics
.tmInternalLeading
);
1462 output
->otmTextMetrics
.tmExternalLeading
= HDPTOLP(output
->otmTextMetrics
.tmExternalLeading
);
1463 output
->otmTextMetrics
.tmAveCharWidth
= WDPTOLP(output
->otmTextMetrics
.tmAveCharWidth
);
1464 output
->otmTextMetrics
.tmMaxCharWidth
= WDPTOLP(output
->otmTextMetrics
.tmMaxCharWidth
);
1465 output
->otmTextMetrics
.tmOverhang
= WDPTOLP(output
->otmTextMetrics
.tmOverhang
);
1466 output
->otmAscent
= HDPTOLP(output
->otmAscent
);
1467 output
->otmDescent
= HDPTOLP(output
->otmDescent
);
1468 output
->otmLineGap
= abs(INTERNAL_YDSTOWS(dc
,output
->otmLineGap
));
1469 output
->otmsCapEmHeight
= abs(INTERNAL_YDSTOWS(dc
,output
->otmsCapEmHeight
));
1470 output
->otmsXHeight
= abs(INTERNAL_YDSTOWS(dc
,output
->otmsXHeight
));
1471 output
->otmrcFontBox
.top
= HDPTOLP(output
->otmrcFontBox
.top
);
1472 output
->otmrcFontBox
.bottom
= HDPTOLP(output
->otmrcFontBox
.bottom
);
1473 output
->otmrcFontBox
.left
= WDPTOLP(output
->otmrcFontBox
.left
);
1474 output
->otmrcFontBox
.right
= WDPTOLP(output
->otmrcFontBox
.right
);
1475 output
->otmMacAscent
= HDPTOLP(output
->otmMacAscent
);
1476 output
->otmMacDescent
= HDPTOLP(output
->otmMacDescent
);
1477 output
->otmMacLineGap
= abs(INTERNAL_YDSTOWS(dc
,output
->otmMacLineGap
));
1478 output
->otmptSubscriptSize
.x
= WDPTOLP(output
->otmptSubscriptSize
.x
);
1479 output
->otmptSubscriptSize
.y
= HDPTOLP(output
->otmptSubscriptSize
.y
);
1480 output
->otmptSubscriptOffset
.x
= WDPTOLP(output
->otmptSubscriptOffset
.x
);
1481 output
->otmptSubscriptOffset
.y
= HDPTOLP(output
->otmptSubscriptOffset
.y
);
1482 output
->otmptSuperscriptSize
.x
= WDPTOLP(output
->otmptSuperscriptSize
.x
);
1483 output
->otmptSuperscriptSize
.y
= HDPTOLP(output
->otmptSuperscriptSize
.y
);
1484 output
->otmptSuperscriptOffset
.x
= WDPTOLP(output
->otmptSuperscriptOffset
.x
);
1485 output
->otmptSuperscriptOffset
.y
= HDPTOLP(output
->otmptSuperscriptOffset
.y
);
1486 output
->otmsStrikeoutSize
= abs(INTERNAL_YDSTOWS(dc
,output
->otmsStrikeoutSize
));
1487 output
->otmsStrikeoutPosition
= HDPTOLP(output
->otmsStrikeoutPosition
);
1488 output
->otmsUnderscoreSize
= HDPTOLP(output
->otmsUnderscoreSize
);
1489 output
->otmsUnderscorePosition
= HDPTOLP(output
->otmsUnderscorePosition
);
1494 memcpy(lpOTM
, output
, cbData
);
1495 HeapFree(GetProcessHeap(), 0, output
);
1503 static LPSTR
FONT_GetCharsByRangeA(HDC hdc
, UINT firstChar
, UINT lastChar
, PINT pByteLen
)
1505 INT i
, count
= lastChar
- firstChar
+ 1;
1512 switch (GdiGetCodePage(hdc
))
1519 if (lastChar
> 0xffff)
1521 if ((firstChar
^ lastChar
) > 0xff)
1525 if (lastChar
> 0xff)
1530 str
= HeapAlloc(GetProcessHeap(), 0, count
* 2 + 1);
1534 for(i
= 0, c
= firstChar
; c
<= lastChar
; i
++, c
++)
1537 str
[i
++] = (BYTE
)(c
>> 8);
1547 /***********************************************************************
1548 * GetCharWidthW (GDI32.@)
1549 * GetCharWidth32W (GDI32.@)
1551 BOOL WINAPI
GetCharWidth32W( HDC hdc
, UINT firstChar
, UINT lastChar
,
1557 DC
* dc
= get_dc_ptr( hdc
);
1559 if (!dc
) return FALSE
;
1561 dev
= GET_DC_PHYSDEV( dc
, pGetCharWidth
);
1562 ret
= dev
->funcs
->pGetCharWidth( dev
, firstChar
, lastChar
, buffer
);
1566 /* convert device units to logical */
1567 for( i
= firstChar
; i
<= lastChar
; i
++, buffer
++ )
1568 *buffer
= INTERNAL_XDSTOWS(dc
, *buffer
);
1570 release_dc_ptr( dc
);
1575 /***********************************************************************
1576 * GetCharWidthA (GDI32.@)
1577 * GetCharWidth32A (GDI32.@)
1579 BOOL WINAPI
GetCharWidth32A( HDC hdc
, UINT firstChar
, UINT lastChar
,
1587 str
= FONT_GetCharsByRangeA(hdc
, firstChar
, lastChar
, &i
);
1591 wstr
= FONT_mbtowc(hdc
, str
, i
, &wlen
, NULL
);
1593 for(i
= 0; i
< wlen
; i
++)
1595 if(!GetCharWidth32W(hdc
, wstr
[i
], wstr
[i
], buffer
))
1603 HeapFree(GetProcessHeap(), 0, str
);
1604 HeapFree(GetProcessHeap(), 0, wstr
);
1610 /***********************************************************************
1611 * ExtTextOutA (GDI32.@)
1615 BOOL WINAPI
ExtTextOutA( HDC hdc
, INT x
, INT y
, UINT flags
,
1616 const RECT
*lprect
, LPCSTR str
, UINT count
, const INT
*lpDx
)
1624 if (flags
& ETO_GLYPH_INDEX
)
1625 return ExtTextOutW( hdc
, x
, y
, flags
, lprect
, (LPCWSTR
)str
, count
, lpDx
);
1627 p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, &codepage
);
1630 unsigned int i
= 0, j
= 0;
1632 /* allocate enough for a ETO_PDY */
1633 lpDxW
= HeapAlloc( GetProcessHeap(), 0, 2*wlen
*sizeof(INT
));
1635 if(IsDBCSLeadByteEx(codepage
, str
[i
]))
1639 lpDxW
[j
++] = lpDx
[i
* 2] + lpDx
[(i
+ 1) * 2];
1640 lpDxW
[j
++] = lpDx
[i
* 2 + 1] + lpDx
[(i
+ 1) * 2 + 1];
1643 lpDxW
[j
++] = lpDx
[i
] + lpDx
[i
+ 1];
1650 lpDxW
[j
++] = lpDx
[i
* 2];
1651 lpDxW
[j
++] = lpDx
[i
* 2 + 1];
1654 lpDxW
[j
++] = lpDx
[i
];
1660 ret
= ExtTextOutW( hdc
, x
, y
, flags
, lprect
, p
, wlen
, lpDxW
);
1662 HeapFree( GetProcessHeap(), 0, p
);
1663 HeapFree( GetProcessHeap(), 0, lpDxW
);
1668 /***********************************************************************
1669 * ExtTextOutW (GDI32.@)
1671 * Draws text using the currently selected font, background color, and text color.
1675 * x,y [I] coordinates of string
1677 * ETO_GRAYED - undocumented on MSDN
1678 * ETO_OPAQUE - use background color for fill the rectangle
1679 * ETO_CLIPPED - clipping text to the rectangle
1680 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1681 * than encoded characters. Implies ETO_IGNORELANGUAGE
1682 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1683 * Affects BiDi ordering
1684 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1685 * ETO_PDY - unimplemented
1686 * ETO_NUMERICSLATIN - unimplemented always assumed -
1687 * do not translate numbers into locale representations
1688 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1689 * lprect [I] dimensions for clipping or/and opaquing
1690 * str [I] text string
1691 * count [I] number of symbols in string
1692 * lpDx [I] optional parameter with distance between drawing characters
1698 BOOL WINAPI
ExtTextOutW( HDC hdc
, INT x
, INT y
, UINT flags
,
1699 const RECT
*lprect
, LPCWSTR str
, UINT count
, const INT
*lpDx
)
1702 LPWSTR reordered_str
= (LPWSTR
)str
;
1703 WORD
*glyphs
= NULL
;
1704 UINT align
= GetTextAlign( hdc
);
1705 DWORD layout
= GetLayout( hdc
);
1709 double cosEsc
, sinEsc
;
1713 BOOL done_extents
= FALSE
;
1714 POINT
*deltas
= NULL
, width
= {0, 0};
1716 DC
* dc
= get_dc_ptr( hdc
);
1719 static int quietfixme
= 0;
1721 if (!dc
) return FALSE
;
1723 breakRem
= dc
->breakRem
;
1725 if (quietfixme
== 0 && flags
& (ETO_NUMERICSLOCAL
| ETO_NUMERICSLATIN
))
1727 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN unimplemented\n");
1732 physdev
= GET_DC_PHYSDEV( dc
, pExtTextOut
);
1733 type
= GetObjectType(hdc
);
1734 if(type
== OBJ_METADC
|| type
== OBJ_ENHMETADC
)
1736 ret
= physdev
->funcs
->pExtTextOut( physdev
, x
, y
, flags
, lprect
, str
, count
, lpDx
);
1737 release_dc_ptr( dc
);
1742 flags
&= ~ETO_CLIPPED
;
1744 if (flags
& ETO_RTLREADING
) align
|= TA_RTLREADING
;
1745 if (layout
& LAYOUT_RTL
)
1747 if ((align
& TA_CENTER
) != TA_CENTER
) align
^= TA_RIGHT
;
1748 align
^= TA_RTLREADING
;
1751 if( !(flags
& (ETO_GLYPH_INDEX
| ETO_IGNORELANGUAGE
)) && count
> 0 )
1754 reordered_str
= HeapAlloc(GetProcessHeap(), 0, count
*sizeof(WCHAR
));
1756 BIDI_Reorder( hdc
, str
, count
, GCP_REORDER
,
1757 (align
& TA_RTLREADING
) ? WINE_GCPW_FORCE_RTL
: WINE_GCPW_FORCE_LTR
,
1758 reordered_str
, count
, NULL
, &glyphs
, &cGlyphs
);
1760 flags
|= ETO_IGNORELANGUAGE
;
1763 flags
|= ETO_GLYPH_INDEX
;
1764 if (cGlyphs
!= count
)
1768 else if(flags
& ETO_GLYPH_INDEX
)
1769 glyphs
= reordered_str
;
1771 TRACE("%p, %d, %d, %08x, %s, %s, %d, %p)\n", hdc
, x
, y
, flags
,
1772 wine_dbgstr_rect(lprect
), debugstr_wn(str
, count
), count
, lpDx
);
1773 TRACE("align = %x bkmode = %x mapmode = %x\n", align
, GetBkMode(hdc
), GetMapMode(hdc
));
1775 if(align
& TA_UPDATECP
)
1777 GetCurrentPositionEx( hdc
, &pt
);
1782 GetTextMetricsW(hdc
, &tm
);
1783 GetObjectW(GetCurrentObject(hdc
, OBJ_FONT
), sizeof(lf
), &lf
);
1785 if(!(tm
.tmPitchAndFamily
& TMPF_VECTOR
)) /* Non-scalable fonts shouldn't be rotated */
1786 lf
.lfEscapement
= 0;
1788 if(lf
.lfEscapement
!= 0)
1790 cosEsc
= cos(lf
.lfEscapement
* M_PI
/ 1800);
1791 sinEsc
= sin(lf
.lfEscapement
* M_PI
/ 1800);
1799 if(flags
& (ETO_CLIPPED
| ETO_OPAQUE
))
1803 if(flags
& ETO_GLYPH_INDEX
)
1804 GetTextExtentPointI(hdc
, glyphs
, count
, &sz
);
1806 GetTextExtentPointW(hdc
, reordered_str
, count
, &sz
);
1808 done_extents
= TRUE
;
1811 rc
.right
= x
+ sz
.cx
;
1812 rc
.bottom
= y
+ sz
.cy
;
1819 LPtoDP(hdc
, (POINT
*)&rc
, 2);
1821 if(rc
.left
> rc
.right
) {INT tmp
= rc
.left
; rc
.left
= rc
.right
; rc
.right
= tmp
;}
1822 if(rc
.top
> rc
.bottom
) {INT tmp
= rc
.top
; rc
.top
= rc
.bottom
; rc
.bottom
= tmp
;}
1825 if (flags
& ETO_OPAQUE
)
1826 physdev
->funcs
->pExtTextOut( physdev
, 0, 0, ETO_OPAQUE
, &rc
, NULL
, 0, NULL
);
1836 LPtoDP(hdc
, &pt
, 1);
1840 char_extra
= GetTextCharacterExtra(hdc
);
1841 if(char_extra
|| dc
->breakExtra
|| breakRem
|| lpDx
|| lf
.lfEscapement
!= 0)
1845 POINT total
= {0, 0}, desired
[2];
1847 deltas
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(*deltas
));
1848 for(i
= 0; i
< count
; i
++)
1854 deltas
[i
].x
= lpDx
[i
* 2] + char_extra
;
1855 deltas
[i
].y
= -lpDx
[i
* 2 + 1];
1859 deltas
[i
].x
= lpDx
[i
] + char_extra
;
1866 if(flags
& ETO_GLYPH_INDEX
)
1867 GetTextExtentPointI(hdc
, glyphs
+ i
, 1, &tmpsz
);
1869 GetTextExtentPointW(hdc
, reordered_str
+ i
, 1, &tmpsz
);
1871 deltas
[i
].x
= tmpsz
.cx
;
1875 if (!(flags
& ETO_GLYPH_INDEX
) && (dc
->breakExtra
|| breakRem
) && reordered_str
[i
] == tm
.tmBreakChar
)
1877 deltas
[i
].x
= deltas
[i
].x
+ dc
->breakExtra
;
1884 total
.x
+= deltas
[i
].x
;
1885 total
.y
+= deltas
[i
].y
;
1887 desired
[0].x
= desired
[0].y
= 0;
1889 desired
[1].x
= cosEsc
* total
.x
+ sinEsc
* total
.y
;
1890 desired
[1].y
= -sinEsc
* total
.x
+ cosEsc
* total
.y
;
1892 LPtoDP(hdc
, desired
, 2);
1893 desired
[1].x
-= desired
[0].x
;
1894 desired
[1].y
-= desired
[0].y
;
1895 if (layout
& LAYOUT_RTL
) desired
[1].x
= -desired
[1].x
;
1897 deltas
[i
].x
= desired
[1].x
- width
.x
;
1898 deltas
[i
].y
= desired
[1].y
- width
.y
;
1908 if(flags
& ETO_GLYPH_INDEX
)
1909 GetTextExtentPointI(hdc
, glyphs
, count
, &sz
);
1911 GetTextExtentPointW(hdc
, reordered_str
, count
, &sz
);
1912 done_extents
= TRUE
;
1914 width
.x
= abs(INTERNAL_XWSTODS(dc
, sz
.cx
));
1918 tm
.tmAscent
= abs(INTERNAL_YWSTODS(dc
, tm
.tmAscent
));
1919 tm
.tmDescent
= abs(INTERNAL_YWSTODS(dc
, tm
.tmDescent
));
1920 switch( align
& (TA_LEFT
| TA_RIGHT
| TA_CENTER
) )
1923 if (align
& TA_UPDATECP
)
1927 DPtoLP(hdc
, &pt
, 1);
1928 MoveToEx(hdc
, pt
.x
, pt
.y
, NULL
);
1940 if (align
& TA_UPDATECP
)
1944 DPtoLP(hdc
, &pt
, 1);
1945 MoveToEx(hdc
, pt
.x
, pt
.y
, NULL
);
1950 switch( align
& (TA_TOP
| TA_BOTTOM
| TA_BASELINE
) )
1953 y
+= tm
.tmAscent
* cosEsc
;
1954 x
+= tm
.tmAscent
* sinEsc
;
1958 y
-= tm
.tmDescent
* cosEsc
;
1959 x
-= tm
.tmDescent
* sinEsc
;
1966 if (GetBkMode(hdc
) != TRANSPARENT
)
1968 if(!((flags
& ETO_CLIPPED
) && (flags
& ETO_OPAQUE
)))
1970 if(!(flags
& ETO_OPAQUE
) || x
< rc
.left
|| x
+ width
.x
>= rc
.right
||
1971 y
- tm
.tmAscent
< rc
.top
|| y
+ tm
.tmDescent
>= rc
.bottom
)
1975 rc
.right
= x
+ width
.x
;
1976 rc
.top
= y
- tm
.tmAscent
;
1977 rc
.bottom
= y
+ tm
.tmDescent
;
1979 if(flags
& ETO_CLIPPED
)
1981 rc
.left
= max(lprect
->left
, rc
.left
);
1982 rc
.right
= min(lprect
->right
, rc
.right
);
1983 rc
.top
= max(lprect
->top
, rc
.top
);
1984 rc
.bottom
= min(lprect
->bottom
, rc
.bottom
);
1986 if(rc
.left
< rc
.right
&& rc
.top
< rc
.bottom
)
1987 physdev
->funcs
->pExtTextOut( physdev
, 0, 0, ETO_OPAQUE
, &rc
, NULL
, 0, NULL
);
1992 if(FontIsLinked(hdc
) && !(flags
& ETO_GLYPH_INDEX
))
1994 HFONT orig_font
= dc
->hFont
, cur_font
;
1997 POINT
*offsets
= NULL
;
2000 glyphs
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(WORD
));
2001 for(i
= 0; i
< count
; i
++)
2003 WineEngGetLinkedHFont(dc
, reordered_str
[i
], &cur_font
, &glyph
);
2004 if(cur_font
!= dc
->hFont
)
2009 offsets
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(*deltas
));
2010 offsets
[0].x
= offsets
[0].y
= 0;
2015 for(j
= 1; j
< count
; j
++)
2017 GetTextExtentPointW(hdc
, reordered_str
+ j
- 1, 1, &tmpsz
);
2018 offsets
[j
].x
= offsets
[j
- 1].x
+ abs(INTERNAL_XWSTODS(dc
, tmpsz
.cx
));
2024 for(j
= 1; j
< count
; j
++)
2026 offsets
[j
].x
= offsets
[j
- 1].x
+ deltas
[j
].x
;
2027 offsets
[j
].y
= offsets
[j
- 1].y
+ deltas
[j
].y
;
2033 physdev
->funcs
->pExtTextOut( physdev
, x
+ offsets
[i
- span
].x
,
2034 y
+ offsets
[i
- span
].y
,
2035 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
, glyphs
,
2036 span
, deltas
? (INT
*)(deltas
+ (i
- span
)) : NULL
);
2039 SelectObject(hdc
, cur_font
);
2041 glyphs
[span
++] = glyph
;
2045 ret
= physdev
->funcs
->pExtTextOut(physdev
, x
+ (offsets
? offsets
[count
- span
].x
: 0),
2046 y
+ (offsets
? offsets
[count
- span
].y
: 0),
2047 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
, glyphs
,
2048 span
, deltas
? (INT
*)(deltas
+ (count
- span
)) : NULL
);
2049 SelectObject(hdc
, orig_font
);
2050 HeapFree(GetProcessHeap(), 0, offsets
);
2056 if(!(flags
& ETO_GLYPH_INDEX
) && dc
->gdiFont
)
2058 glyphs
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(WORD
));
2059 GetGlyphIndicesW(hdc
, reordered_str
, count
, glyphs
, 0);
2060 flags
|= ETO_GLYPH_INDEX
;
2062 ret
= physdev
->funcs
->pExtTextOut( physdev
, x
, y
, (flags
& ~ETO_OPAQUE
), &rc
,
2063 glyphs
? glyphs
: reordered_str
, count
, (INT
*)deltas
);
2067 HeapFree(GetProcessHeap(), 0, deltas
);
2068 if(glyphs
!= reordered_str
)
2069 HeapFree(GetProcessHeap(), 0, glyphs
);
2070 if(reordered_str
!= str
)
2071 HeapFree(GetProcessHeap(), 0, reordered_str
);
2073 release_dc_ptr( dc
);
2075 if (ret
&& (lf
.lfUnderline
|| lf
.lfStrikeOut
))
2077 int underlinePos
, strikeoutPos
;
2078 int underlineWidth
, strikeoutWidth
;
2079 UINT size
= GetOutlineTextMetricsW(hdc
, 0, NULL
);
2080 OUTLINETEXTMETRICW
* otm
= NULL
;
2082 HPEN hpen
= SelectObject(hdc
, GetStockObject(NULL_PEN
));
2083 HBRUSH hbrush
= CreateSolidBrush(GetTextColor(hdc
));
2085 hbrush
= SelectObject(hdc
, hbrush
);
2090 underlineWidth
= tm
.tmAscent
/ 20 + 1;
2091 strikeoutPos
= tm
.tmAscent
/ 2;
2092 strikeoutWidth
= underlineWidth
;
2096 otm
= HeapAlloc(GetProcessHeap(), 0, size
);
2097 GetOutlineTextMetricsW(hdc
, size
, otm
);
2098 underlinePos
= abs( INTERNAL_YWSTODS( dc
, otm
->otmsUnderscorePosition
));
2099 if (otm
->otmsUnderscorePosition
< 0) underlinePos
= -underlinePos
;
2100 underlineWidth
= abs( INTERNAL_YWSTODS( dc
, otm
->otmsUnderscoreSize
));
2101 if (otm
->otmsUnderscoreSize
< 0) underlineWidth
= -underlineWidth
;
2102 strikeoutPos
= abs( INTERNAL_YWSTODS( dc
, otm
->otmsStrikeoutPosition
));
2103 if (otm
->otmsStrikeoutPosition
< 0) strikeoutPos
= -strikeoutPos
;
2104 strikeoutWidth
= abs( INTERNAL_YWSTODS( dc
, otm
->otmsStrikeoutSize
));
2105 HeapFree(GetProcessHeap(), 0, otm
);
2111 pts
[0].x
= x
- (underlinePos
+ underlineWidth
/ 2) * sinEsc
;
2112 pts
[0].y
= y
- (underlinePos
+ underlineWidth
/ 2) * cosEsc
;
2113 pts
[1].x
= x
+ width
.x
- (underlinePos
+ underlineWidth
/ 2) * sinEsc
;
2114 pts
[1].y
= y
+ width
.y
- (underlinePos
+ underlineWidth
/ 2) * cosEsc
;
2115 pts
[2].x
= pts
[1].x
+ underlineWidth
* sinEsc
;
2116 pts
[2].y
= pts
[1].y
+ underlineWidth
* cosEsc
;
2117 pts
[3].x
= pts
[0].x
+ underlineWidth
* sinEsc
;
2118 pts
[3].y
= pts
[0].y
+ underlineWidth
* cosEsc
;
2119 pts
[4].x
= pts
[0].x
;
2120 pts
[4].y
= pts
[0].y
;
2121 DPtoLP(hdc
, pts
, 5);
2122 Polygon(hdc
, pts
, 5);
2127 pts
[0].x
= x
- (strikeoutPos
+ strikeoutWidth
/ 2) * sinEsc
;
2128 pts
[0].y
= y
- (strikeoutPos
+ strikeoutWidth
/ 2) * cosEsc
;
2129 pts
[1].x
= x
+ width
.x
- (strikeoutPos
+ strikeoutWidth
/ 2) * sinEsc
;
2130 pts
[1].y
= y
+ width
.y
- (strikeoutPos
+ strikeoutWidth
/ 2) * cosEsc
;
2131 pts
[2].x
= pts
[1].x
+ strikeoutWidth
* sinEsc
;
2132 pts
[2].y
= pts
[1].y
+ strikeoutWidth
* cosEsc
;
2133 pts
[3].x
= pts
[0].x
+ strikeoutWidth
* sinEsc
;
2134 pts
[3].y
= pts
[0].y
+ strikeoutWidth
* cosEsc
;
2135 pts
[4].x
= pts
[0].x
;
2136 pts
[4].y
= pts
[0].y
;
2137 DPtoLP(hdc
, pts
, 5);
2138 Polygon(hdc
, pts
, 5);
2141 SelectObject(hdc
, hpen
);
2142 hbrush
= SelectObject(hdc
, hbrush
);
2143 DeleteObject(hbrush
);
2150 /***********************************************************************
2151 * TextOutA (GDI32.@)
2153 BOOL WINAPI
TextOutA( HDC hdc
, INT x
, INT y
, LPCSTR str
, INT count
)
2155 return ExtTextOutA( hdc
, x
, y
, 0, NULL
, str
, count
, NULL
);
2159 /***********************************************************************
2160 * TextOutW (GDI32.@)
2162 BOOL WINAPI
TextOutW(HDC hdc
, INT x
, INT y
, LPCWSTR str
, INT count
)
2164 return ExtTextOutW( hdc
, x
, y
, 0, NULL
, str
, count
, NULL
);
2168 /***********************************************************************
2169 * PolyTextOutA (GDI32.@)
2173 BOOL WINAPI
PolyTextOutA( HDC hdc
, const POLYTEXTA
*pptxt
, INT cStrings
)
2175 for (; cStrings
>0; cStrings
--, pptxt
++)
2176 if (!ExtTextOutA( hdc
, pptxt
->x
, pptxt
->y
, pptxt
->uiFlags
, &pptxt
->rcl
, pptxt
->lpstr
, pptxt
->n
, pptxt
->pdx
))
2183 /***********************************************************************
2184 * PolyTextOutW (GDI32.@)
2186 * Draw several Strings
2192 BOOL WINAPI
PolyTextOutW( HDC hdc
, const POLYTEXTW
*pptxt
, INT cStrings
)
2194 for (; cStrings
>0; cStrings
--, pptxt
++)
2195 if (!ExtTextOutW( hdc
, pptxt
->x
, pptxt
->y
, pptxt
->uiFlags
, &pptxt
->rcl
, pptxt
->lpstr
, pptxt
->n
, pptxt
->pdx
))
2201 /***********************************************************************
2202 * SetMapperFlags (GDI32.@)
2204 DWORD WINAPI
SetMapperFlags( HDC hdc
, DWORD flags
)
2206 DC
*dc
= get_dc_ptr( hdc
);
2207 DWORD ret
= GDI_ERROR
;
2211 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetMapperFlags
);
2212 flags
= physdev
->funcs
->pSetMapperFlags( physdev
, flags
);
2213 if (flags
!= GDI_ERROR
)
2215 ret
= dc
->mapperFlags
;
2216 dc
->mapperFlags
= flags
;
2218 release_dc_ptr( dc
);
2223 /***********************************************************************
2224 * GetAspectRatioFilterEx (GDI32.@)
2226 BOOL WINAPI
GetAspectRatioFilterEx( HDC hdc
, LPSIZE pAspectRatio
)
2228 FIXME("(%p, %p): -- Empty Stub !\n", hdc
, pAspectRatio
);
2233 /***********************************************************************
2234 * GetCharABCWidthsA (GDI32.@)
2236 * See GetCharABCWidthsW.
2238 BOOL WINAPI
GetCharABCWidthsA(HDC hdc
, UINT firstChar
, UINT lastChar
,
2246 str
= FONT_GetCharsByRangeA(hdc
, firstChar
, lastChar
, &i
);
2250 wstr
= FONT_mbtowc(hdc
, str
, i
, &wlen
, NULL
);
2253 HeapFree(GetProcessHeap(), 0, str
);
2257 for(i
= 0; i
< wlen
; i
++)
2259 if(!GetCharABCWidthsW(hdc
, wstr
[i
], wstr
[i
], abc
))
2267 HeapFree(GetProcessHeap(), 0, str
);
2268 HeapFree(GetProcessHeap(), 0, wstr
);
2274 /******************************************************************************
2275 * GetCharABCWidthsW [GDI32.@]
2277 * Retrieves widths of characters in range.
2280 * hdc [I] Handle of device context
2281 * firstChar [I] First character in range to query
2282 * lastChar [I] Last character in range to query
2283 * abc [O] Address of character-width structure
2286 * Only works with TrueType fonts
2292 BOOL WINAPI
GetCharABCWidthsW( HDC hdc
, UINT firstChar
, UINT lastChar
,
2295 DC
*dc
= get_dc_ptr(hdc
);
2300 if (!dc
) return FALSE
;
2304 release_dc_ptr( dc
);
2308 dev
= GET_DC_PHYSDEV( dc
, pGetCharABCWidths
);
2309 ret
= dev
->funcs
->pGetCharABCWidths( dev
, firstChar
, lastChar
, abc
);
2312 /* convert device units to logical */
2313 for( i
= firstChar
; i
<= lastChar
; i
++, abc
++ ) {
2314 abc
->abcA
= INTERNAL_XDSTOWS(dc
, abc
->abcA
);
2315 abc
->abcB
= INTERNAL_XDSTOWS(dc
, abc
->abcB
);
2316 abc
->abcC
= INTERNAL_XDSTOWS(dc
, abc
->abcC
);
2320 release_dc_ptr( dc
);
2325 /******************************************************************************
2326 * GetCharABCWidthsI [GDI32.@]
2328 * Retrieves widths of characters in range.
2331 * hdc [I] Handle of device context
2332 * firstChar [I] First glyphs in range to query
2333 * count [I] Last glyphs in range to query
2334 * pgi [i] Array of glyphs to query
2335 * abc [O] Address of character-width structure
2338 * Only works with TrueType fonts
2344 BOOL WINAPI
GetCharABCWidthsI( HDC hdc
, UINT firstChar
, UINT count
,
2345 LPWORD pgi
, LPABC abc
)
2347 DC
*dc
= get_dc_ptr(hdc
);
2352 if (!dc
) return FALSE
;
2356 release_dc_ptr( dc
);
2360 dev
= GET_DC_PHYSDEV( dc
, pGetCharABCWidthsI
);
2361 ret
= dev
->funcs
->pGetCharABCWidthsI( dev
, firstChar
, count
, pgi
, abc
);
2364 /* convert device units to logical */
2365 for( i
= 0; i
< count
; i
++, abc
++ ) {
2366 abc
->abcA
= INTERNAL_XDSTOWS(dc
, abc
->abcA
);
2367 abc
->abcB
= INTERNAL_XDSTOWS(dc
, abc
->abcB
);
2368 abc
->abcC
= INTERNAL_XDSTOWS(dc
, abc
->abcC
);
2372 release_dc_ptr( dc
);
2377 /***********************************************************************
2378 * GetGlyphOutlineA (GDI32.@)
2380 DWORD WINAPI
GetGlyphOutlineA( HDC hdc
, UINT uChar
, UINT fuFormat
,
2381 LPGLYPHMETRICS lpgm
, DWORD cbBuffer
,
2382 LPVOID lpBuffer
, const MAT2
*lpmat2
)
2384 if (!lpmat2
) return GDI_ERROR
;
2386 if(!(fuFormat
& GGO_GLYPH_INDEX
)) {
2391 cp
= GdiGetCodePage(hdc
);
2392 if (IsDBCSLeadByteEx(cp
, uChar
>> 8)) {
2394 mbchs
[0] = (uChar
& 0xff00) >> 8;
2395 mbchs
[1] = (uChar
& 0xff);
2398 mbchs
[0] = (uChar
& 0xff);
2401 MultiByteToWideChar(cp
, 0, mbchs
, len
, (LPWSTR
)&uChar
, 1);
2404 return GetGlyphOutlineW(hdc
, uChar
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
,
2408 /***********************************************************************
2409 * GetGlyphOutlineW (GDI32.@)
2411 DWORD WINAPI
GetGlyphOutlineW( HDC hdc
, UINT uChar
, UINT fuFormat
,
2412 LPGLYPHMETRICS lpgm
, DWORD cbBuffer
,
2413 LPVOID lpBuffer
, const MAT2
*lpmat2
)
2419 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2420 hdc
, uChar
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
, lpmat2
);
2422 if (!lpmat2
) return GDI_ERROR
;
2424 dc
= get_dc_ptr(hdc
);
2425 if(!dc
) return GDI_ERROR
;
2427 dev
= GET_DC_PHYSDEV( dc
, pGetGlyphOutline
);
2428 ret
= dev
->funcs
->pGetGlyphOutline( dev
, uChar
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
, lpmat2
);
2429 release_dc_ptr( dc
);
2434 /***********************************************************************
2435 * CreateScalableFontResourceA (GDI32.@)
2437 BOOL WINAPI
CreateScalableFontResourceA( DWORD fHidden
,
2438 LPCSTR lpszResourceFile
,
2439 LPCSTR lpszFontFile
,
2440 LPCSTR lpszCurrentPath
)
2442 LPWSTR lpszResourceFileW
= NULL
;
2443 LPWSTR lpszFontFileW
= NULL
;
2444 LPWSTR lpszCurrentPathW
= NULL
;
2448 if (lpszResourceFile
)
2450 len
= MultiByteToWideChar(CP_ACP
, 0, lpszResourceFile
, -1, NULL
, 0);
2451 lpszResourceFileW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2452 MultiByteToWideChar(CP_ACP
, 0, lpszResourceFile
, -1, lpszResourceFileW
, len
);
2457 len
= MultiByteToWideChar(CP_ACP
, 0, lpszFontFile
, -1, NULL
, 0);
2458 lpszFontFileW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2459 MultiByteToWideChar(CP_ACP
, 0, lpszFontFile
, -1, lpszFontFileW
, len
);
2462 if (lpszCurrentPath
)
2464 len
= MultiByteToWideChar(CP_ACP
, 0, lpszCurrentPath
, -1, NULL
, 0);
2465 lpszCurrentPathW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2466 MultiByteToWideChar(CP_ACP
, 0, lpszCurrentPath
, -1, lpszCurrentPathW
, len
);
2469 ret
= CreateScalableFontResourceW(fHidden
, lpszResourceFileW
,
2470 lpszFontFileW
, lpszCurrentPathW
);
2472 HeapFree(GetProcessHeap(), 0, lpszResourceFileW
);
2473 HeapFree(GetProcessHeap(), 0, lpszFontFileW
);
2474 HeapFree(GetProcessHeap(), 0, lpszCurrentPathW
);
2479 /***********************************************************************
2480 * CreateScalableFontResourceW (GDI32.@)
2482 BOOL WINAPI
CreateScalableFontResourceW( DWORD fHidden
,
2483 LPCWSTR lpszResourceFile
,
2484 LPCWSTR lpszFontFile
,
2485 LPCWSTR lpszCurrentPath
)
2488 FIXME("(%d,%s,%s,%s): stub\n",
2489 fHidden
, debugstr_w(lpszResourceFile
), debugstr_w(lpszFontFile
),
2490 debugstr_w(lpszCurrentPath
) );
2492 /* fHidden=1 - only visible for the calling app, read-only, not
2493 * enumerated with EnumFonts/EnumFontFamilies
2494 * lpszCurrentPath can be NULL
2497 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2498 if ((f
= CreateFileW(lpszResourceFile
, 0, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, 0)) != INVALID_HANDLE_VALUE
) {
2500 SetLastError(ERROR_FILE_EXISTS
);
2503 return FALSE
; /* create failed */
2506 /*************************************************************************
2507 * GetKerningPairsA (GDI32.@)
2509 DWORD WINAPI
GetKerningPairsA( HDC hDC
, DWORD cPairs
,
2510 LPKERNINGPAIR kern_pairA
)
2514 DWORD i
, total_kern_pairs
, kern_pairs_copied
= 0;
2515 KERNINGPAIR
*kern_pairW
;
2517 if (!cPairs
&& kern_pairA
)
2519 SetLastError(ERROR_INVALID_PARAMETER
);
2523 cp
= GdiGetCodePage(hDC
);
2525 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2526 * to fail on an invalid character for CP_SYMBOL.
2528 cpi
.DefaultChar
[0] = 0;
2529 if (cp
!= CP_SYMBOL
&& !GetCPInfo(cp
, &cpi
))
2531 FIXME("Can't find codepage %u info\n", cp
);
2535 total_kern_pairs
= GetKerningPairsW(hDC
, 0, NULL
);
2536 if (!total_kern_pairs
) return 0;
2538 kern_pairW
= HeapAlloc(GetProcessHeap(), 0, total_kern_pairs
* sizeof(*kern_pairW
));
2539 GetKerningPairsW(hDC
, total_kern_pairs
, kern_pairW
);
2541 for (i
= 0; i
< total_kern_pairs
; i
++)
2545 if (!WideCharToMultiByte(cp
, 0, &kern_pairW
[i
].wFirst
, 1, &first
, 1, NULL
, NULL
))
2548 if (!WideCharToMultiByte(cp
, 0, &kern_pairW
[i
].wSecond
, 1, &second
, 1, NULL
, NULL
))
2551 if (first
== cpi
.DefaultChar
[0] || second
== cpi
.DefaultChar
[0])
2556 if (kern_pairs_copied
>= cPairs
) break;
2558 kern_pairA
->wFirst
= (BYTE
)first
;
2559 kern_pairA
->wSecond
= (BYTE
)second
;
2560 kern_pairA
->iKernAmount
= kern_pairW
[i
].iKernAmount
;
2563 kern_pairs_copied
++;
2566 HeapFree(GetProcessHeap(), 0, kern_pairW
);
2568 return kern_pairs_copied
;
2571 /*************************************************************************
2572 * GetKerningPairsW (GDI32.@)
2574 DWORD WINAPI
GetKerningPairsW( HDC hDC
, DWORD cPairs
,
2575 LPKERNINGPAIR lpKerningPairs
)
2581 TRACE("(%p,%d,%p)\n", hDC
, cPairs
, lpKerningPairs
);
2583 if (!cPairs
&& lpKerningPairs
)
2585 SetLastError(ERROR_INVALID_PARAMETER
);
2589 dc
= get_dc_ptr(hDC
);
2592 dev
= GET_DC_PHYSDEV( dc
, pGetKerningPairs
);
2593 ret
= dev
->funcs
->pGetKerningPairs( dev
, cPairs
, lpKerningPairs
);
2594 release_dc_ptr( dc
);
2598 /*************************************************************************
2599 * TranslateCharsetInfo [GDI32.@]
2601 * Fills a CHARSETINFO structure for a character set, code page, or
2602 * font. This allows making the correspondence between different labels
2603 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2604 * of the same encoding.
2606 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2607 * only one codepage should be set in *lpSrc.
2610 * TRUE on success, FALSE on failure.
2613 BOOL WINAPI
TranslateCharsetInfo(
2614 LPDWORD lpSrc
, /* [in]
2615 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2616 if flags == TCI_SRCCHARSET: a character set value
2617 if flags == TCI_SRCCODEPAGE: a code page value
2619 LPCHARSETINFO lpCs
, /* [out] structure to receive charset information */
2620 DWORD flags
/* [in] determines interpretation of lpSrc */)
2624 case TCI_SRCFONTSIG
:
2625 while (index
< MAXTCIINDEX
&& !(*lpSrc
>>index
& 0x0001)) index
++;
2627 case TCI_SRCCODEPAGE
:
2628 while (index
< MAXTCIINDEX
&& PtrToUlong(lpSrc
) != FONT_tci
[index
].ciACP
) index
++;
2630 case TCI_SRCCHARSET
:
2631 while (index
< MAXTCIINDEX
&& PtrToUlong(lpSrc
) != FONT_tci
[index
].ciCharset
) index
++;
2636 if (index
>= MAXTCIINDEX
|| FONT_tci
[index
].ciCharset
== DEFAULT_CHARSET
) return FALSE
;
2637 *lpCs
= FONT_tci
[index
];
2641 /*************************************************************************
2642 * GetFontLanguageInfo (GDI32.@)
2644 DWORD WINAPI
GetFontLanguageInfo(HDC hdc
)
2646 FONTSIGNATURE fontsig
;
2647 static const DWORD GCP_DBCS_MASK
=0x003F0000,
2648 GCP_DIACRITIC_MASK
=0x00000000,
2649 FLI_GLYPHS_MASK
=0x00000000,
2650 GCP_GLYPHSHAPE_MASK
=0x00000040,
2651 GCP_KASHIDA_MASK
=0x00000000,
2652 GCP_LIGATE_MASK
=0x00000000,
2653 GCP_USEKERNING_MASK
=0x00000000,
2654 GCP_REORDER_MASK
=0x00000060;
2658 GetTextCharsetInfo( hdc
, &fontsig
, 0 );
2659 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2661 if( (fontsig
.fsCsb
[0]&GCP_DBCS_MASK
)!=0 )
2664 if( (fontsig
.fsCsb
[0]&GCP_DIACRITIC_MASK
)!=0 )
2665 result
|=GCP_DIACRITIC
;
2667 if( (fontsig
.fsCsb
[0]&FLI_GLYPHS_MASK
)!=0 )
2670 if( (fontsig
.fsCsb
[0]&GCP_GLYPHSHAPE_MASK
)!=0 )
2671 result
|=GCP_GLYPHSHAPE
;
2673 if( (fontsig
.fsCsb
[0]&GCP_KASHIDA_MASK
)!=0 )
2674 result
|=GCP_KASHIDA
;
2676 if( (fontsig
.fsCsb
[0]&GCP_LIGATE_MASK
)!=0 )
2679 if( (fontsig
.fsCsb
[0]&GCP_USEKERNING_MASK
)!=0 )
2680 result
|=GCP_USEKERNING
;
2682 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2683 if( GetTextAlign( hdc
) & TA_RTLREADING
)
2684 if( (fontsig
.fsCsb
[0]&GCP_REORDER_MASK
)!=0 )
2685 result
|=GCP_REORDER
;
2691 /*************************************************************************
2692 * GetFontData [GDI32.@]
2694 * Retrieve data for TrueType font.
2698 * success: Number of bytes returned
2699 * failure: GDI_ERROR
2703 * Calls SetLastError()
2706 DWORD WINAPI
GetFontData(HDC hdc
, DWORD table
, DWORD offset
,
2707 LPVOID buffer
, DWORD length
)
2709 DC
*dc
= get_dc_ptr(hdc
);
2713 if(!dc
) return GDI_ERROR
;
2715 dev
= GET_DC_PHYSDEV( dc
, pGetFontData
);
2716 ret
= dev
->funcs
->pGetFontData( dev
, table
, offset
, buffer
, length
);
2717 release_dc_ptr( dc
);
2721 /*************************************************************************
2722 * GetGlyphIndicesA [GDI32.@]
2724 DWORD WINAPI
GetGlyphIndicesA(HDC hdc
, LPCSTR lpstr
, INT count
,
2725 LPWORD pgi
, DWORD flags
)
2731 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2732 hdc
, debugstr_an(lpstr
, count
), count
, pgi
, flags
);
2734 lpstrW
= FONT_mbtowc(hdc
, lpstr
, count
, &countW
, NULL
);
2735 ret
= GetGlyphIndicesW(hdc
, lpstrW
, countW
, pgi
, flags
);
2736 HeapFree(GetProcessHeap(), 0, lpstrW
);
2741 /*************************************************************************
2742 * GetGlyphIndicesW [GDI32.@]
2744 DWORD WINAPI
GetGlyphIndicesW(HDC hdc
, LPCWSTR lpstr
, INT count
,
2745 LPWORD pgi
, DWORD flags
)
2747 DC
*dc
= get_dc_ptr(hdc
);
2751 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2752 hdc
, debugstr_wn(lpstr
, count
), count
, pgi
, flags
);
2754 if(!dc
) return GDI_ERROR
;
2756 dev
= GET_DC_PHYSDEV( dc
, pGetGlyphIndices
);
2757 ret
= dev
->funcs
->pGetGlyphIndices( dev
, lpstr
, count
, pgi
, flags
);
2758 release_dc_ptr( dc
);
2762 /*************************************************************************
2763 * GetCharacterPlacementA [GDI32.@]
2765 * See GetCharacterPlacementW.
2768 * the web browser control of ie4 calls this with dwFlags=0
2771 GetCharacterPlacementA(HDC hdc
, LPCSTR lpString
, INT uCount
,
2772 INT nMaxExtent
, GCP_RESULTSA
*lpResults
,
2777 GCP_RESULTSW resultsW
;
2781 TRACE("%s, %d, %d, 0x%08x\n",
2782 debugstr_an(lpString
, uCount
), uCount
, nMaxExtent
, dwFlags
);
2784 /* both structs are equal in size */
2785 memcpy(&resultsW
, lpResults
, sizeof(resultsW
));
2787 lpStringW
= FONT_mbtowc(hdc
, lpString
, uCount
, &uCountW
, &font_cp
);
2788 if(lpResults
->lpOutString
)
2789 resultsW
.lpOutString
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*uCountW
);
2791 ret
= GetCharacterPlacementW(hdc
, lpStringW
, uCountW
, nMaxExtent
, &resultsW
, dwFlags
);
2793 lpResults
->nGlyphs
= resultsW
.nGlyphs
;
2794 lpResults
->nMaxFit
= resultsW
.nMaxFit
;
2796 if(lpResults
->lpOutString
) {
2797 WideCharToMultiByte(font_cp
, 0, resultsW
.lpOutString
, uCountW
,
2798 lpResults
->lpOutString
, uCount
, NULL
, NULL
);
2801 HeapFree(GetProcessHeap(), 0, lpStringW
);
2802 HeapFree(GetProcessHeap(), 0, resultsW
.lpOutString
);
2807 /*************************************************************************
2808 * GetCharacterPlacementW [GDI32.@]
2810 * Retrieve information about a string. This includes the width, reordering,
2811 * Glyphing and so on.
2815 * The width and height of the string if successful, 0 if failed.
2819 * All flags except GCP_REORDER are not yet implemented.
2820 * Reordering is not 100% compliant to the Windows BiDi method.
2821 * Caret positioning is not yet implemented for BiDi.
2822 * Classes are not yet implemented.
2826 GetCharacterPlacementW(
2827 HDC hdc
, /* [in] Device context for which the rendering is to be done */
2828 LPCWSTR lpString
, /* [in] The string for which information is to be returned */
2829 INT uCount
, /* [in] Number of WORDS in string. */
2830 INT nMaxExtent
, /* [in] Maximum extent the string is to take (in HDC logical units) */
2831 GCP_RESULTSW
*lpResults
,/* [in/out] A pointer to a GCP_RESULTSW struct */
2832 DWORD dwFlags
/* [in] Flags specifying how to process the string */
2839 TRACE("%s, %d, %d, 0x%08x\n",
2840 debugstr_wn(lpString
, uCount
), uCount
, nMaxExtent
, dwFlags
);
2842 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2843 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2844 lpResults
->lStructSize
, lpResults
->lpOutString
, lpResults
->lpOrder
,
2845 lpResults
->lpDx
, lpResults
->lpCaretPos
, lpResults
->lpClass
,
2846 lpResults
->lpGlyphs
, lpResults
->nGlyphs
, lpResults
->nMaxFit
);
2848 if(dwFlags
&(~GCP_REORDER
)) FIXME("flags 0x%08x ignored\n", dwFlags
);
2849 if(lpResults
->lpClass
) FIXME("classes not implemented\n");
2850 if (lpResults
->lpCaretPos
&& (dwFlags
& GCP_REORDER
))
2851 FIXME("Caret positions for complex scripts not implemented\n");
2853 nSet
= (UINT
)uCount
;
2854 if(nSet
> lpResults
->nGlyphs
)
2855 nSet
= lpResults
->nGlyphs
;
2857 /* return number of initialized fields */
2858 lpResults
->nGlyphs
= nSet
;
2860 if((dwFlags
&GCP_REORDER
)==0 )
2862 /* Treat the case where no special handling was requested in a fastpath way */
2863 /* copy will do if the GCP_REORDER flag is not set */
2864 if(lpResults
->lpOutString
)
2865 memcpy( lpResults
->lpOutString
, lpString
, nSet
* sizeof(WCHAR
));
2867 if(lpResults
->lpOrder
)
2869 for(i
= 0; i
< nSet
; i
++)
2870 lpResults
->lpOrder
[i
] = i
;
2874 BIDI_Reorder(NULL
, lpString
, uCount
, dwFlags
, WINE_GCPW_FORCE_LTR
, lpResults
->lpOutString
,
2875 nSet
, lpResults
->lpOrder
, NULL
, NULL
);
2878 /* FIXME: Will use the placement chars */
2879 if (lpResults
->lpDx
)
2882 for (i
= 0; i
< nSet
; i
++)
2884 if (GetCharWidth32W(hdc
, lpString
[i
], lpString
[i
], &c
))
2885 lpResults
->lpDx
[i
]= c
;
2889 if (lpResults
->lpCaretPos
&& !(dwFlags
& GCP_REORDER
))
2893 lpResults
->lpCaretPos
[0] = 0;
2894 for (i
= 1; i
< nSet
; i
++)
2895 if (GetTextExtentPoint32W(hdc
, &(lpString
[i
- 1]), 1, &size
))
2896 lpResults
->lpCaretPos
[i
] = (pos
+= size
.cx
);
2899 if(lpResults
->lpGlyphs
)
2900 GetGlyphIndicesW(hdc
, lpString
, nSet
, lpResults
->lpGlyphs
, 0);
2902 if (GetTextExtentPoint32W(hdc
, lpString
, uCount
, &size
))
2903 ret
= MAKELONG(size
.cx
, size
.cy
);
2908 /*************************************************************************
2909 * GetCharABCWidthsFloatA [GDI32.@]
2911 * See GetCharABCWidthsFloatW.
2913 BOOL WINAPI
GetCharABCWidthsFloatA( HDC hdc
, UINT first
, UINT last
, LPABCFLOAT abcf
)
2920 str
= FONT_GetCharsByRangeA(hdc
, first
, last
, &i
);
2924 wstr
= FONT_mbtowc( hdc
, str
, i
, &wlen
, NULL
);
2926 for (i
= 0; i
< wlen
; i
++)
2928 if (!GetCharABCWidthsFloatW( hdc
, wstr
[i
], wstr
[i
], abcf
))
2936 HeapFree( GetProcessHeap(), 0, str
);
2937 HeapFree( GetProcessHeap(), 0, wstr
);
2942 /*************************************************************************
2943 * GetCharABCWidthsFloatW [GDI32.@]
2945 * Retrieves widths of a range of characters.
2948 * hdc [I] Handle to device context.
2949 * first [I] First character in range to query.
2950 * last [I] Last character in range to query.
2951 * abcf [O] Array of LPABCFLOAT structures.
2957 BOOL WINAPI
GetCharABCWidthsFloatW( HDC hdc
, UINT first
, UINT last
, LPABCFLOAT abcf
)
2963 DC
*dc
= get_dc_ptr( hdc
);
2965 TRACE("%p, %d, %d, %p\n", hdc
, first
, last
, abcf
);
2967 if (!dc
) return FALSE
;
2969 if (!abcf
) goto done
;
2970 if (!(abc
= HeapAlloc( GetProcessHeap(), 0, (last
- first
+ 1) * sizeof(*abc
) ))) goto done
;
2972 dev
= GET_DC_PHYSDEV( dc
, pGetCharABCWidths
);
2973 ret
= dev
->funcs
->pGetCharABCWidths( dev
, first
, last
, abc
);
2976 /* convert device units to logical */
2977 for (i
= first
; i
<= last
; i
++, abcf
++)
2979 abcf
->abcfA
= abc
->abcA
* dc
->xformVport2World
.eM11
;
2980 abcf
->abcfB
= abc
->abcB
* dc
->xformVport2World
.eM11
;
2981 abcf
->abcfC
= abc
->abcC
* dc
->xformVport2World
.eM11
;
2984 HeapFree( GetProcessHeap(), 0, abc
);
2987 release_dc_ptr( dc
);
2991 /*************************************************************************
2992 * GetCharWidthFloatA [GDI32.@]
2994 BOOL WINAPI
GetCharWidthFloatA(HDC hdc
, UINT iFirstChar
,
2995 UINT iLastChar
, PFLOAT pxBuffer
)
2997 FIXME("%p, %u, %u, %p: stub!\n", hdc
, iFirstChar
, iLastChar
, pxBuffer
);
3001 /*************************************************************************
3002 * GetCharWidthFloatW [GDI32.@]
3004 BOOL WINAPI
GetCharWidthFloatW(HDC hdc
, UINT iFirstChar
,
3005 UINT iLastChar
, PFLOAT pxBuffer
)
3007 FIXME("%p, %u, %u, %p: stub!\n", hdc
, iFirstChar
, iLastChar
, pxBuffer
);
3012 /***********************************************************************
3014 * Font Resource API *
3016 ***********************************************************************/
3018 /***********************************************************************
3019 * AddFontResourceA (GDI32.@)
3021 INT WINAPI
AddFontResourceA( LPCSTR str
)
3023 return AddFontResourceExA( str
, 0, NULL
);
3026 /***********************************************************************
3027 * AddFontResourceW (GDI32.@)
3029 INT WINAPI
AddFontResourceW( LPCWSTR str
)
3031 return AddFontResourceExW(str
, 0, NULL
);
3035 /***********************************************************************
3036 * AddFontResourceExA (GDI32.@)
3038 INT WINAPI
AddFontResourceExA( LPCSTR str
, DWORD fl
, PVOID pdv
)
3040 DWORD len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
3041 LPWSTR strW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3044 MultiByteToWideChar(CP_ACP
, 0, str
, -1, strW
, len
);
3045 ret
= AddFontResourceExW(strW
, fl
, pdv
);
3046 HeapFree(GetProcessHeap(), 0, strW
);
3050 static BOOL CALLBACK
load_enumed_resource(HMODULE hModule
, LPCWSTR type
, LPWSTR name
, LONG_PTR lParam
)
3052 HRSRC rsrc
= FindResourceW(hModule
, name
, type
);
3053 HGLOBAL hMem
= LoadResource(hModule
, rsrc
);
3054 LPVOID
*pMem
= LockResource(hMem
);
3055 int *num_total
= (int *)lParam
;
3058 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type
));
3059 if (!AddFontMemResourceEx(pMem
, SizeofResource(hModule
, rsrc
), NULL
, &num_in_res
))
3061 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule
, hMem
);
3065 *num_total
+= num_in_res
;
3069 /***********************************************************************
3070 * AddFontResourceExW (GDI32.@)
3072 INT WINAPI
AddFontResourceExW( LPCWSTR str
, DWORD fl
, PVOID pdv
)
3074 int ret
= WineEngAddFontResourceEx(str
, fl
, pdv
);
3077 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3078 HMODULE hModule
= LoadLibraryExW(str
, NULL
, LOAD_LIBRARY_AS_DATAFILE
);
3079 if (hModule
!= NULL
)
3081 int num_resources
= 0;
3082 LPWSTR rt_font
= (LPWSTR
)((ULONG_PTR
)8); /* we don't want to include winuser.h */
3084 TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3085 wine_dbgstr_w(str
));
3086 if (EnumResourceNamesW(hModule
, rt_font
, load_enumed_resource
, (LONG_PTR
)&num_resources
))
3087 ret
= num_resources
;
3088 FreeLibrary(hModule
);
3094 /***********************************************************************
3095 * RemoveFontResourceA (GDI32.@)
3097 BOOL WINAPI
RemoveFontResourceA( LPCSTR str
)
3099 return RemoveFontResourceExA(str
, 0, 0);
3102 /***********************************************************************
3103 * RemoveFontResourceW (GDI32.@)
3105 BOOL WINAPI
RemoveFontResourceW( LPCWSTR str
)
3107 return RemoveFontResourceExW(str
, 0, 0);
3110 /***********************************************************************
3111 * AddFontMemResourceEx (GDI32.@)
3113 HANDLE WINAPI
AddFontMemResourceEx( PVOID pbFont
, DWORD cbFont
, PVOID pdv
, DWORD
*pcFonts
)
3118 if (!pbFont
|| !cbFont
|| !pcFonts
)
3120 SetLastError(ERROR_INVALID_PARAMETER
);
3124 ret
= WineEngAddFontMemResourceEx(pbFont
, cbFont
, pdv
, &num_fonts
);
3129 *pcFonts
= num_fonts
;
3133 WARN("page fault while writing to *pcFonts (%p)\n", pcFonts
);
3134 RemoveFontMemResourceEx(ret
);
3142 /***********************************************************************
3143 * RemoveFontMemResourceEx (GDI32.@)
3145 BOOL WINAPI
RemoveFontMemResourceEx( HANDLE fh
)
3147 FIXME("(%p) stub\n", fh
);
3151 /***********************************************************************
3152 * RemoveFontResourceExA (GDI32.@)
3154 BOOL WINAPI
RemoveFontResourceExA( LPCSTR str
, DWORD fl
, PVOID pdv
)
3156 DWORD len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
3157 LPWSTR strW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3160 MultiByteToWideChar(CP_ACP
, 0, str
, -1, strW
, len
);
3161 ret
= RemoveFontResourceExW(strW
, fl
, pdv
);
3162 HeapFree(GetProcessHeap(), 0, strW
);
3166 /***********************************************************************
3167 * RemoveFontResourceExW (GDI32.@)
3169 BOOL WINAPI
RemoveFontResourceExW( LPCWSTR str
, DWORD fl
, PVOID pdv
)
3171 return WineEngRemoveFontResourceEx(str
, fl
, pdv
);
3174 /***********************************************************************
3175 * GetTextCharset (GDI32.@)
3177 UINT WINAPI
GetTextCharset(HDC hdc
)
3179 /* MSDN docs say this is equivalent */
3180 return GetTextCharsetInfo(hdc
, NULL
, 0);
3183 /***********************************************************************
3184 * GetTextCharsetInfo (GDI32.@)
3186 UINT WINAPI
GetTextCharsetInfo(HDC hdc
, LPFONTSIGNATURE fs
, DWORD flags
)
3188 UINT ret
= DEFAULT_CHARSET
;
3189 DC
*dc
= get_dc_ptr(hdc
);
3194 dev
= GET_DC_PHYSDEV( dc
, pGetTextCharsetInfo
);
3195 ret
= dev
->funcs
->pGetTextCharsetInfo( dev
, fs
, flags
);
3196 release_dc_ptr( dc
);
3199 if (ret
== DEFAULT_CHARSET
&& fs
)
3200 memset(fs
, 0, sizeof(FONTSIGNATURE
));
3204 /***********************************************************************
3205 * GdiGetCharDimensions (GDI32.@)
3207 * Gets the average width of the characters in the English alphabet.
3210 * hdc [I] Handle to the device context to measure on.
3211 * lptm [O] Pointer to memory to store the text metrics into.
3212 * height [O] On exit, the maximum height of characters in the English alphabet.
3215 * The average width of characters in the English alphabet.
3218 * This function is used by the dialog manager to get the size of a dialog
3219 * unit. It should also be used by other pieces of code that need to know
3220 * the size of a dialog unit in logical units without having access to the
3221 * window handle of the dialog.
3222 * Windows caches the font metrics from this function, but we don't and
3223 * there doesn't appear to be an immediate advantage to do so.
3226 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3228 LONG WINAPI
GdiGetCharDimensions(HDC hdc
, LPTEXTMETRICW lptm
, LONG
*height
)
3231 static const WCHAR alphabet
[] = {
3232 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3233 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3234 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3236 if(lptm
&& !GetTextMetricsW(hdc
, lptm
)) return 0;
3238 if(!GetTextExtentPointW(hdc
, alphabet
, 52, &sz
)) return 0;
3240 if (height
) *height
= sz
.cy
;
3241 return (sz
.cx
/ 26 + 1) / 2;
3244 BOOL WINAPI
EnableEUDC(BOOL fEnableEUDC
)
3246 FIXME("(%d): stub\n", fEnableEUDC
);
3250 /***********************************************************************
3251 * GetCharWidthI (GDI32.@)
3253 * Retrieve widths of characters.
3256 * hdc [I] Handle to a device context.
3257 * first [I] First glyph in range to query.
3258 * count [I] Number of glyph indices to query.
3259 * glyphs [I] Array of glyphs to query.
3260 * buffer [O] Buffer to receive character widths.
3263 * Only works with TrueType fonts.
3269 BOOL WINAPI
GetCharWidthI(HDC hdc
, UINT first
, UINT count
, LPWORD glyphs
, LPINT buffer
)
3274 TRACE("(%p, %d, %d, %p, %p)\n", hdc
, first
, count
, glyphs
, buffer
);
3276 if (!(abc
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(ABC
))))
3279 if (!GetCharABCWidthsI(hdc
, first
, count
, glyphs
, abc
))
3281 HeapFree(GetProcessHeap(), 0, abc
);
3285 for (i
= 0; i
< count
; i
++)
3286 buffer
[i
] = abc
->abcA
+ abc
->abcB
+ abc
->abcC
;
3288 HeapFree(GetProcessHeap(), 0, abc
);
3292 /***********************************************************************
3293 * GetFontUnicodeRanges (GDI32.@)
3295 * Retrieve a list of supported Unicode characters in a font.
3298 * hdc [I] Handle to a device context.
3299 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3302 * Success: Number of bytes written to the buffer pointed to by lpgs.
3306 DWORD WINAPI
GetFontUnicodeRanges(HDC hdc
, LPGLYPHSET lpgs
)
3310 DC
*dc
= get_dc_ptr(hdc
);
3312 TRACE("(%p, %p)\n", hdc
, lpgs
);
3316 dev
= GET_DC_PHYSDEV( dc
, pGetFontUnicodeRanges
);
3317 ret
= dev
->funcs
->pGetFontUnicodeRanges( dev
, lpgs
);
3323 /*************************************************************
3324 * FontIsLinked (GDI32.@)
3326 BOOL WINAPI
FontIsLinked(HDC hdc
)
3328 DC
*dc
= get_dc_ptr(hdc
);
3332 if (!dc
) return FALSE
;
3333 dev
= GET_DC_PHYSDEV( dc
, pFontIsLinked
);
3334 ret
= dev
->funcs
->pFontIsLinked( dev
);
3336 TRACE("returning %d\n", ret
);
3340 /*************************************************************
3341 * GdiRealizationInfo (GDI32.@)
3343 * Returns a structure that contains some font information.
3345 BOOL WINAPI
GdiRealizationInfo(HDC hdc
, realization_info_t
*info
)
3347 DC
*dc
= get_dc_ptr(hdc
);
3351 if (!dc
) return FALSE
;
3352 dev
= GET_DC_PHYSDEV( dc
, pGdiRealizationInfo
);
3353 ret
= dev
->funcs
->pGdiRealizationInfo( dev
, info
);