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"
35 #include "gdi_private.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 */
103 #define ENUM_UNICODE 0x00000001
104 #define ENUM_CALLED 0x00000002
114 LPLOGFONTW lpLogFontParam
;
115 FONTENUMPROCW lpEnumFunc
;
122 * For TranslateCharsetInfo
124 #define MAXTCIINDEX 32
125 static const CHARSETINFO FONT_tci
[MAXTCIINDEX
] = {
127 { ANSI_CHARSET
, 1252, {{0,0,0,0},{FS_LATIN1
,0}} },
128 { EASTEUROPE_CHARSET
, 1250, {{0,0,0,0},{FS_LATIN2
,0}} },
129 { RUSSIAN_CHARSET
, 1251, {{0,0,0,0},{FS_CYRILLIC
,0}} },
130 { GREEK_CHARSET
, 1253, {{0,0,0,0},{FS_GREEK
,0}} },
131 { TURKISH_CHARSET
, 1254, {{0,0,0,0},{FS_TURKISH
,0}} },
132 { HEBREW_CHARSET
, 1255, {{0,0,0,0},{FS_HEBREW
,0}} },
133 { ARABIC_CHARSET
, 1256, {{0,0,0,0},{FS_ARABIC
,0}} },
134 { BALTIC_CHARSET
, 1257, {{0,0,0,0},{FS_BALTIC
,0}} },
135 { VIETNAMESE_CHARSET
, 1258, {{0,0,0,0},{FS_VIETNAMESE
,0}} },
136 /* reserved by ANSI */
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}} },
141 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
142 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
143 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
145 { THAI_CHARSET
, 874, {{0,0,0,0},{FS_THAI
,0}} },
146 { SHIFTJIS_CHARSET
, 932, {{0,0,0,0},{FS_JISJAPAN
,0}} },
147 { GB2312_CHARSET
, 936, {{0,0,0,0},{FS_CHINESESIMP
,0}} },
148 { HANGEUL_CHARSET
, 949, {{0,0,0,0},{FS_WANSUNG
,0}} },
149 { CHINESEBIG5_CHARSET
, 950, {{0,0,0,0},{FS_CHINESETRAD
,0}} },
150 { JOHAB_CHARSET
, 1361, {{0,0,0,0},{FS_JOHAB
,0}} },
151 /* reserved for alternate ANSI and OEM */
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 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
158 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
159 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
160 /* reserved for system */
161 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
162 { SYMBOL_CHARSET
, CP_SYMBOL
, {{0,0,0,0},{FS_SYMBOL
,0}} }
165 static void FONT_LogFontAToW( const LOGFONTA
*fontA
, LPLOGFONTW fontW
)
167 memcpy(fontW
, fontA
, sizeof(LOGFONTA
) - LF_FACESIZE
);
168 MultiByteToWideChar(CP_ACP
, 0, fontA
->lfFaceName
, -1, fontW
->lfFaceName
,
170 fontW
->lfFaceName
[LF_FACESIZE
-1] = 0;
173 static void FONT_LogFontWToA( const LOGFONTW
*fontW
, LPLOGFONTA fontA
)
175 memcpy(fontA
, fontW
, sizeof(LOGFONTA
) - LF_FACESIZE
);
176 WideCharToMultiByte(CP_ACP
, 0, fontW
->lfFaceName
, -1, fontA
->lfFaceName
,
177 LF_FACESIZE
, NULL
, NULL
);
178 fontA
->lfFaceName
[LF_FACESIZE
-1] = 0;
181 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW
*fontW
, LPENUMLOGFONTEXA fontA
)
183 FONT_LogFontWToA( (const LOGFONTW
*)fontW
, (LPLOGFONTA
)fontA
);
185 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfFullName
, -1,
186 (LPSTR
) fontA
->elfFullName
, LF_FULLFACESIZE
, NULL
, NULL
);
187 fontA
->elfFullName
[LF_FULLFACESIZE
-1] = '\0';
188 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfStyle
, -1,
189 (LPSTR
) fontA
->elfStyle
, LF_FACESIZE
, NULL
, NULL
);
190 fontA
->elfStyle
[LF_FACESIZE
-1] = '\0';
191 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfScript
, -1,
192 (LPSTR
) fontA
->elfScript
, LF_FACESIZE
, NULL
, NULL
);
193 fontA
->elfScript
[LF_FACESIZE
-1] = '\0';
196 /***********************************************************************
197 * TEXTMETRIC conversion functions.
199 static void FONT_TextMetricWToA(const TEXTMETRICW
*ptmW
, LPTEXTMETRICA ptmA
)
201 ptmA
->tmHeight
= ptmW
->tmHeight
;
202 ptmA
->tmAscent
= ptmW
->tmAscent
;
203 ptmA
->tmDescent
= ptmW
->tmDescent
;
204 ptmA
->tmInternalLeading
= ptmW
->tmInternalLeading
;
205 ptmA
->tmExternalLeading
= ptmW
->tmExternalLeading
;
206 ptmA
->tmAveCharWidth
= ptmW
->tmAveCharWidth
;
207 ptmA
->tmMaxCharWidth
= ptmW
->tmMaxCharWidth
;
208 ptmA
->tmWeight
= ptmW
->tmWeight
;
209 ptmA
->tmOverhang
= ptmW
->tmOverhang
;
210 ptmA
->tmDigitizedAspectX
= ptmW
->tmDigitizedAspectX
;
211 ptmA
->tmDigitizedAspectY
= ptmW
->tmDigitizedAspectY
;
212 ptmA
->tmFirstChar
= min(ptmW
->tmFirstChar
, 255);
213 if (ptmW
->tmCharSet
== SYMBOL_CHARSET
)
215 UINT last_char
= ptmW
->tmLastChar
;
216 if (last_char
> 0xf000) last_char
-= 0xf000;
217 ptmA
->tmLastChar
= min(last_char
, 255);
220 ptmA
->tmLastChar
= min(ptmW
->tmLastChar
, 255);
221 ptmA
->tmDefaultChar
= min(ptmW
->tmDefaultChar
, 255);
222 ptmA
->tmBreakChar
= min(ptmW
->tmBreakChar
, 255);
223 ptmA
->tmItalic
= ptmW
->tmItalic
;
224 ptmA
->tmUnderlined
= ptmW
->tmUnderlined
;
225 ptmA
->tmStruckOut
= ptmW
->tmStruckOut
;
226 ptmA
->tmPitchAndFamily
= ptmW
->tmPitchAndFamily
;
227 ptmA
->tmCharSet
= ptmW
->tmCharSet
;
231 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW
*ptmW
, NEWTEXTMETRICEXA
*ptmA
)
233 FONT_TextMetricWToA((const TEXTMETRICW
*)ptmW
, (LPTEXTMETRICA
)ptmA
);
234 ptmA
->ntmTm
.ntmFlags
= ptmW
->ntmTm
.ntmFlags
;
235 ptmA
->ntmTm
.ntmSizeEM
= ptmW
->ntmTm
.ntmSizeEM
;
236 ptmA
->ntmTm
.ntmCellHeight
= ptmW
->ntmTm
.ntmCellHeight
;
237 ptmA
->ntmTm
.ntmAvgWidth
= ptmW
->ntmTm
.ntmAvgWidth
;
238 memcpy(&ptmA
->ntmFontSig
, &ptmW
->ntmFontSig
, sizeof(FONTSIGNATURE
));
242 /***********************************************************************
243 * GdiGetCodePage (GDI32.@)
245 DWORD WINAPI
GdiGetCodePage( HDC hdc
)
249 int charset
= GetTextCharset(hdc
);
251 /* Hmm, nicely designed api this one! */
252 if(TranslateCharsetInfo(ULongToPtr(charset
), &csi
, TCI_SRCCHARSET
))
259 case DEFAULT_CHARSET
:
270 /* FIXME: These have no place here, but because x11drv
271 enumerates fonts with these (made up) charsets some apps
272 might use them and then the FIXME below would become
273 annoying. Now we could pick the intended codepage for
274 each of these, but since it's broken anyway we'll just
275 use CP_ACP and hope it'll go away...
281 FIXME("Can't find codepage for charset %d\n", charset
);
286 TRACE("charset %d => cp %d\n", charset
, cp
);
290 /***********************************************************************
293 * Returns a Unicode translation of str using the charset of the
294 * currently selected font in hdc. If count is -1 then str is assumed
295 * to be '\0' terminated, otherwise it contains the number of bytes to
296 * convert. If plenW is non-NULL, on return it will point to the
297 * number of WCHARs that have been written. If pCP is non-NULL, on
298 * return it will point to the codepage used in the conversion. The
299 * caller should free the returned LPWSTR from the process heap
302 static LPWSTR
FONT_mbtowc(HDC hdc
, LPCSTR str
, INT count
, INT
*plenW
, UINT
*pCP
)
308 cp
= GdiGetCodePage( hdc
);
310 if(count
== -1) count
= strlen(str
);
311 lenW
= MultiByteToWideChar(cp
, 0, str
, count
, NULL
, 0);
312 strW
= HeapAlloc(GetProcessHeap(), 0, lenW
*sizeof(WCHAR
));
313 MultiByteToWideChar(cp
, 0, str
, count
, strW
, lenW
);
314 TRACE("mapped %s -> %s\n", debugstr_an(str
, count
), debugstr_wn(strW
, lenW
));
315 if(plenW
) *plenW
= lenW
;
321 /***********************************************************************
322 * CreateFontIndirectA (GDI32.@)
324 HFONT WINAPI
CreateFontIndirectA( const LOGFONTA
*plfA
)
330 FONT_LogFontAToW( plfA
, &lfW
);
331 return CreateFontIndirectW( &lfW
);
334 /***********************************************************************
335 * CreateFontIndirectW (GDI32.@)
337 HFONT WINAPI
CreateFontIndirectW( const LOGFONTW
*plf
)
339 static const WCHAR ItalicW
[] = {' ','I','t','a','l','i','c','\0'};
340 static const WCHAR BoldW
[] = {' ','B','o','l','d','\0'};
341 WCHAR
*pFaceNameItalicSuffix
, *pFaceNameBoldSuffix
;
342 WCHAR
*pFaceNameSuffix
= NULL
;
348 if (!(fontPtr
= HeapAlloc( GetProcessHeap(), 0, sizeof(*fontPtr
) ))) return 0;
350 fontPtr
->logfont
= *plf
;
352 if (plf
->lfEscapement
!= plf
->lfOrientation
)
354 /* this should really depend on whether GM_ADVANCED is set */
355 fontPtr
->logfont
.lfOrientation
= fontPtr
->logfont
.lfEscapement
;
356 WARN("orientation angle %f set to "
357 "escapement angle %f for new font %p\n",
358 plf
->lfOrientation
/10., plf
->lfEscapement
/10., fontPtr
);
361 pFaceNameItalicSuffix
= strstrW(fontPtr
->logfont
.lfFaceName
, ItalicW
);
362 if (pFaceNameItalicSuffix
)
364 fontPtr
->logfont
.lfItalic
= TRUE
;
365 pFaceNameSuffix
= pFaceNameItalicSuffix
;
368 pFaceNameBoldSuffix
= strstrW(fontPtr
->logfont
.lfFaceName
, BoldW
);
369 if (pFaceNameBoldSuffix
)
371 if (fontPtr
->logfont
.lfWeight
< FW_BOLD
)
372 fontPtr
->logfont
.lfWeight
= FW_BOLD
;
373 if (!pFaceNameSuffix
|| (pFaceNameBoldSuffix
< pFaceNameSuffix
))
374 pFaceNameSuffix
= pFaceNameBoldSuffix
;
377 if (pFaceNameSuffix
) *pFaceNameSuffix
= 0;
379 if (!(hFont
= alloc_gdi_handle( &fontPtr
->header
, OBJ_FONT
, &font_funcs
)))
381 HeapFree( GetProcessHeap(), 0, fontPtr
);
385 TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
386 plf
->lfHeight
, plf
->lfWidth
,
387 plf
->lfEscapement
, plf
->lfOrientation
,
388 plf
->lfPitchAndFamily
,
389 plf
->lfOutPrecision
, plf
->lfClipPrecision
,
390 plf
->lfQuality
, plf
->lfCharSet
,
391 debugstr_w(plf
->lfFaceName
),
392 plf
->lfWeight
> 400 ? "Bold" : "",
393 plf
->lfItalic
? "Italic" : "",
394 plf
->lfUnderline
? "Underline" : "", hFont
);
399 /*************************************************************************
400 * CreateFontA (GDI32.@)
402 HFONT WINAPI
CreateFontA( INT height
, INT width
, INT esc
,
403 INT orient
, INT weight
, DWORD italic
,
404 DWORD underline
, DWORD strikeout
, DWORD charset
,
405 DWORD outpres
, DWORD clippres
, DWORD quality
,
406 DWORD pitch
, LPCSTR name
)
410 logfont
.lfHeight
= height
;
411 logfont
.lfWidth
= width
;
412 logfont
.lfEscapement
= esc
;
413 logfont
.lfOrientation
= orient
;
414 logfont
.lfWeight
= weight
;
415 logfont
.lfItalic
= italic
;
416 logfont
.lfUnderline
= underline
;
417 logfont
.lfStrikeOut
= strikeout
;
418 logfont
.lfCharSet
= charset
;
419 logfont
.lfOutPrecision
= outpres
;
420 logfont
.lfClipPrecision
= clippres
;
421 logfont
.lfQuality
= quality
;
422 logfont
.lfPitchAndFamily
= pitch
;
425 lstrcpynA(logfont
.lfFaceName
,name
,sizeof(logfont
.lfFaceName
));
427 logfont
.lfFaceName
[0] = '\0';
429 return CreateFontIndirectA( &logfont
);
432 /*************************************************************************
433 * CreateFontW (GDI32.@)
435 HFONT WINAPI
CreateFontW( INT height
, INT width
, INT esc
,
436 INT orient
, INT weight
, DWORD italic
,
437 DWORD underline
, DWORD strikeout
, DWORD charset
,
438 DWORD outpres
, DWORD clippres
, DWORD quality
,
439 DWORD pitch
, LPCWSTR name
)
443 logfont
.lfHeight
= height
;
444 logfont
.lfWidth
= width
;
445 logfont
.lfEscapement
= esc
;
446 logfont
.lfOrientation
= orient
;
447 logfont
.lfWeight
= weight
;
448 logfont
.lfItalic
= italic
;
449 logfont
.lfUnderline
= underline
;
450 logfont
.lfStrikeOut
= strikeout
;
451 logfont
.lfCharSet
= charset
;
452 logfont
.lfOutPrecision
= outpres
;
453 logfont
.lfClipPrecision
= clippres
;
454 logfont
.lfQuality
= quality
;
455 logfont
.lfPitchAndFamily
= pitch
;
458 lstrcpynW(logfont
.lfFaceName
, name
,
459 sizeof(logfont
.lfFaceName
) / sizeof(WCHAR
));
461 logfont
.lfFaceName
[0] = '\0';
463 return CreateFontIndirectW( &logfont
);
467 /***********************************************************************
470 * If the driver supports vector fonts we create a gdi font first and
471 * then call the driver to give it a chance to supply its own device
472 * font. If the driver wants to do this it returns TRUE and we can
473 * delete the gdi font, if the driver wants to use the gdi font it
474 * should return FALSE, to signal an error return GDI_ERROR. For
475 * drivers that don't support vector fonts they must supply their own
478 static HGDIOBJ
FONT_SelectObject( HGDIOBJ handle
, HDC hdc
)
481 DC
*dc
= get_dc_ptr( hdc
);
485 if (!GDI_inc_ref_count( handle
))
487 release_dc_ptr( dc
);
491 if (GetDeviceCaps( dc
->hSelf
, TEXTCAPS
) & TC_VA_ABLE
)
492 dc
->gdiFont
= WineEngCreateFontInstance( dc
, handle
);
494 if (dc
->funcs
->pSelectFont
) ret
= dc
->funcs
->pSelectFont( dc
->physDev
, handle
, dc
->gdiFont
);
496 if (ret
&& dc
->gdiFont
) dc
->gdiFont
= 0;
498 if (ret
== HGDI_ERROR
)
500 GDI_dec_ref_count( handle
);
501 ret
= 0; /* SelectObject returns 0 on error */
507 GDI_dec_ref_count( ret
);
509 release_dc_ptr( dc
);
514 /***********************************************************************
517 static INT
FONT_GetObjectA( HGDIOBJ handle
, INT count
, LPVOID buffer
)
519 FONTOBJ
*font
= GDI_GetObjPtr( handle
, OBJ_FONT
);
525 FONT_LogFontWToA( &font
->logfont
, &lfA
);
526 if (count
> sizeof(lfA
)) count
= sizeof(lfA
);
527 memcpy( buffer
, &lfA
, count
);
529 else count
= sizeof(lfA
);
530 GDI_ReleaseObj( handle
);
534 /***********************************************************************
537 static INT
FONT_GetObjectW( HGDIOBJ handle
, INT count
, LPVOID buffer
)
539 FONTOBJ
*font
= GDI_GetObjPtr( handle
, OBJ_FONT
);
544 if (count
> sizeof(LOGFONTW
)) count
= sizeof(LOGFONTW
);
545 memcpy( buffer
, &font
->logfont
, count
);
547 else count
= sizeof(LOGFONTW
);
548 GDI_ReleaseObj( handle
);
553 /***********************************************************************
556 static BOOL
FONT_DeleteObject( HGDIOBJ handle
)
560 WineEngDestroyFontInstance( handle
);
562 if (!(obj
= free_gdi_handle( handle
))) return FALSE
;
563 return HeapFree( GetProcessHeap(), 0, obj
);
567 /***********************************************************************
570 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
571 * We have to use other types because of the FONTENUMPROCW definition.
573 static INT CALLBACK
FONT_EnumInstance( const LOGFONTW
*plf
, const TEXTMETRICW
*ptm
,
574 DWORD fType
, LPARAM lp
)
576 fontEnum32
*pfe
= (fontEnum32
*)lp
;
579 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
580 if ((!pfe
->lpLogFontParam
||
581 pfe
->lpLogFontParam
->lfCharSet
== DEFAULT_CHARSET
||
582 pfe
->lpLogFontParam
->lfCharSet
== plf
->lfCharSet
) &&
583 (!(fType
& RASTER_FONTTYPE
) || GetDeviceCaps(pfe
->hdc
, TEXTCAPS
) & TC_RA_ABLE
) )
585 /* convert font metrics */
586 ENUMLOGFONTEXA logfont
;
587 NEWTEXTMETRICEXA tmA
;
589 pfe
->dwFlags
|= ENUM_CALLED
;
590 if (!(pfe
->dwFlags
& ENUM_UNICODE
))
592 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW
*)plf
, &logfont
);
593 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW
*)ptm
, &tmA
);
594 plf
= (LOGFONTW
*)&logfont
.elfLogFont
;
595 ptm
= (TEXTMETRICW
*)&tmA
;
598 ret
= pfe
->lpEnumFunc( plf
, ptm
, fType
, pfe
->lpData
);
603 /***********************************************************************
604 * FONT_EnumFontFamiliesEx
606 static INT
FONT_EnumFontFamiliesEx( HDC hDC
, LPLOGFONTW plf
,
607 FONTENUMPROCW efproc
,
608 LPARAM lParam
, DWORD dwUnicode
)
611 DC
*dc
= get_dc_ptr( hDC
);
618 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf
->lfFaceName
),
620 fe32
.lpLogFontParam
= plf
;
621 fe32
.lpEnumFunc
= efproc
;
622 fe32
.lpData
= lParam
;
623 fe32
.dwFlags
= dwUnicode
;
626 enum_gdi_fonts
= GetDeviceCaps(hDC
, TEXTCAPS
) & TC_VA_ABLE
;
628 if (!dc
->funcs
->pEnumDeviceFonts
&& !enum_gdi_fonts
)
635 ret
= WineEngEnumFonts( plf
, FONT_EnumInstance
, (LPARAM
)&fe32
);
636 fe32
.dwFlags
&= ~ENUM_CALLED
;
637 if (ret
&& dc
->funcs
->pEnumDeviceFonts
) {
638 ret2
= dc
->funcs
->pEnumDeviceFonts( dc
->physDev
, plf
, FONT_EnumInstance
, (LPARAM
)&fe32
);
639 if(fe32
.dwFlags
& ENUM_CALLED
) /* update ret iff a font gets enumed */
643 release_dc_ptr( dc
);
647 /***********************************************************************
648 * EnumFontFamiliesExW (GDI32.@)
650 INT WINAPI
EnumFontFamiliesExW( HDC hDC
, LPLOGFONTW plf
,
651 FONTENUMPROCW efproc
,
652 LPARAM lParam
, DWORD dwFlags
)
654 return FONT_EnumFontFamiliesEx( hDC
, plf
, efproc
, lParam
, ENUM_UNICODE
);
657 /***********************************************************************
658 * EnumFontFamiliesExA (GDI32.@)
660 INT WINAPI
EnumFontFamiliesExA( HDC hDC
, LPLOGFONTA plf
,
661 FONTENUMPROCA efproc
,
662 LPARAM lParam
, DWORD dwFlags
)
668 FONT_LogFontAToW( plf
, &lfW
);
673 return FONT_EnumFontFamiliesEx( hDC
, plfW
, (FONTENUMPROCW
)efproc
, lParam
, 0);
676 /***********************************************************************
677 * EnumFontFamiliesA (GDI32.@)
679 INT WINAPI
EnumFontFamiliesA( HDC hDC
, LPCSTR lpFamily
,
680 FONTENUMPROCA efproc
, LPARAM lpData
)
686 if (!*lpFamily
) return 1;
687 lstrcpynA( lf
.lfFaceName
, lpFamily
, LF_FACESIZE
);
688 lf
.lfCharSet
= DEFAULT_CHARSET
;
689 lf
.lfPitchAndFamily
= 0;
694 return EnumFontFamiliesExA( hDC
, plf
, efproc
, lpData
, 0 );
697 /***********************************************************************
698 * EnumFontFamiliesW (GDI32.@)
700 INT WINAPI
EnumFontFamiliesW( HDC hDC
, LPCWSTR lpFamily
,
701 FONTENUMPROCW efproc
, LPARAM lpData
)
707 if (!*lpFamily
) return 1;
708 lstrcpynW( lf
.lfFaceName
, lpFamily
, LF_FACESIZE
);
709 lf
.lfCharSet
= DEFAULT_CHARSET
;
710 lf
.lfPitchAndFamily
= 0;
715 return EnumFontFamiliesExW( hDC
, plf
, efproc
, lpData
, 0 );
718 /***********************************************************************
719 * EnumFontsA (GDI32.@)
721 INT WINAPI
EnumFontsA( HDC hDC
, LPCSTR lpName
, FONTENUMPROCA efproc
,
724 return EnumFontFamiliesA( hDC
, lpName
, efproc
, lpData
);
727 /***********************************************************************
728 * EnumFontsW (GDI32.@)
730 INT WINAPI
EnumFontsW( HDC hDC
, LPCWSTR lpName
, FONTENUMPROCW efproc
,
733 return EnumFontFamiliesW( hDC
, lpName
, efproc
, lpData
);
737 /***********************************************************************
738 * GetTextCharacterExtra (GDI32.@)
740 INT WINAPI
GetTextCharacterExtra( HDC hdc
)
743 DC
*dc
= get_dc_ptr( hdc
);
744 if (!dc
) return 0x80000000;
746 release_dc_ptr( dc
);
751 /***********************************************************************
752 * SetTextCharacterExtra (GDI32.@)
754 INT WINAPI
SetTextCharacterExtra( HDC hdc
, INT extra
)
757 DC
* dc
= get_dc_ptr( hdc
);
758 if (!dc
) return 0x80000000;
759 if (dc
->funcs
->pSetTextCharacterExtra
)
760 prev
= dc
->funcs
->pSetTextCharacterExtra( dc
->physDev
, extra
);
763 prev
= dc
->charExtra
;
764 dc
->charExtra
= extra
;
766 release_dc_ptr( dc
);
771 /***********************************************************************
772 * SetTextJustification (GDI32.@)
774 BOOL WINAPI
SetTextJustification( HDC hdc
, INT extra
, INT breaks
)
777 DC
* dc
= get_dc_ptr( hdc
);
778 if (!dc
) return FALSE
;
779 if (dc
->funcs
->pSetTextJustification
)
780 ret
= dc
->funcs
->pSetTextJustification( dc
->physDev
, extra
, breaks
);
783 extra
= abs((extra
* dc
->vportExtX
+ dc
->wndExtX
/ 2) / dc
->wndExtX
);
784 if (!extra
) breaks
= 0;
787 dc
->breakExtra
= extra
/ breaks
;
788 dc
->breakRem
= extra
- (breaks
* dc
->breakExtra
);
796 release_dc_ptr( dc
);
801 /***********************************************************************
802 * GetTextFaceA (GDI32.@)
804 INT WINAPI
GetTextFaceA( HDC hdc
, INT count
, LPSTR name
)
806 INT res
= GetTextFaceW(hdc
, 0, NULL
);
807 LPWSTR nameW
= HeapAlloc( GetProcessHeap(), 0, res
* 2 );
808 GetTextFaceW( hdc
, res
, nameW
);
814 res
= WideCharToMultiByte(CP_ACP
, 0, nameW
, -1, name
, count
, NULL
, NULL
);
818 /* GetTextFaceA does NOT include the nul byte in the return count. */
825 res
= WideCharToMultiByte( CP_ACP
, 0, nameW
, -1, NULL
, 0, NULL
, NULL
);
826 HeapFree( GetProcessHeap(), 0, nameW
);
830 /***********************************************************************
831 * GetTextFaceW (GDI32.@)
833 INT WINAPI
GetTextFaceW( HDC hdc
, INT count
, LPWSTR name
)
838 DC
* dc
= get_dc_ptr( hdc
);
842 ret
= WineEngGetTextFace(dc
->gdiFont
, count
, name
);
843 else if ((font
= GDI_GetObjPtr( dc
->hFont
, OBJ_FONT
)))
845 INT n
= strlenW(font
->logfont
.lfFaceName
) + 1;
848 lstrcpynW( name
, font
->logfont
.lfFaceName
, count
);
852 GDI_ReleaseObj( dc
->hFont
);
854 release_dc_ptr( dc
);
859 /***********************************************************************
860 * GetTextExtentPoint32A (GDI32.@)
862 * See GetTextExtentPoint32W.
864 BOOL WINAPI
GetTextExtentPoint32A( HDC hdc
, LPCSTR str
, INT count
,
869 LPWSTR p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
872 ret
= GetTextExtentPoint32W( hdc
, p
, wlen
, size
);
873 HeapFree( GetProcessHeap(), 0, p
);
876 TRACE("(%p %s %d %p): returning %d x %d\n",
877 hdc
, debugstr_an (str
, count
), count
, size
, size
->cx
, size
->cy
);
882 /***********************************************************************
883 * GetTextExtentPoint32W [GDI32.@]
885 * Computes width/height for a string.
887 * Computes width and height of the specified string.
893 BOOL WINAPI
GetTextExtentPoint32W(
894 HDC hdc
, /* [in] Handle of device context */
895 LPCWSTR str
, /* [in] Address of text string */
896 INT count
, /* [in] Number of characters in string */
897 LPSIZE size
) /* [out] Address of structure for string size */
899 return GetTextExtentExPointW(hdc
, str
, count
, 0, NULL
, NULL
, size
);
902 /***********************************************************************
903 * GetTextExtentExPointI [GDI32.@]
905 * Computes width and height of the array of glyph indices.
908 * hdc [I] Handle of device context.
909 * indices [I] Glyph index array.
910 * count [I] Number of glyphs in array.
911 * max_ext [I] Maximum width in glyphs.
912 * nfit [O] Maximum number of characters.
913 * dxs [O] Partial string widths.
914 * size [O] Returned string size.
920 BOOL WINAPI
GetTextExtentExPointI( HDC hdc
, const WORD
*indices
, INT count
, INT max_ext
,
921 LPINT nfit
, LPINT dxs
, LPSIZE size
)
924 DC
* dc
= get_dc_ptr( hdc
);
925 if (!dc
) return FALSE
;
928 ret
= WineEngGetTextExtentExPointI(dc
->gdiFont
, indices
, count
, max_ext
, nfit
, dxs
, size
);
929 size
->cx
= abs(INTERNAL_XDSTOWS(dc
, size
->cx
));
930 size
->cy
= abs(INTERNAL_YDSTOWS(dc
, size
->cy
));
931 size
->cx
+= count
* dc
->charExtra
;
933 else if(dc
->funcs
->pGetTextExtentExPoint
) {
934 FIXME("calling GetTextExtentExPoint\n");
935 ret
= dc
->funcs
->pGetTextExtentExPoint( dc
->physDev
, indices
, count
,
936 max_ext
, nfit
, dxs
, size
);
939 release_dc_ptr( dc
);
941 TRACE("(%p %p %d %p): returning %d x %d\n",
942 hdc
, indices
, count
, size
, size
->cx
, size
->cy
);
946 /***********************************************************************
947 * GetTextExtentPointI [GDI32.@]
949 * Computes width and height of the array of glyph indices.
952 * hdc [I] Handle of device context.
953 * indices [I] Glyph index array.
954 * count [I] Number of glyphs in array.
955 * size [O] Returned string size.
961 BOOL WINAPI
GetTextExtentPointI( HDC hdc
, const WORD
*indices
, INT count
, LPSIZE size
)
963 return GetTextExtentExPointI( hdc
, indices
, count
, 0, NULL
, NULL
, size
);
967 /***********************************************************************
968 * GetTextExtentPointA (GDI32.@)
970 BOOL WINAPI
GetTextExtentPointA( HDC hdc
, LPCSTR str
, INT count
,
973 TRACE("not bug compatible.\n");
974 return GetTextExtentPoint32A( hdc
, str
, count
, size
);
977 /***********************************************************************
978 * GetTextExtentPointW (GDI32.@)
980 BOOL WINAPI
GetTextExtentPointW( HDC hdc
, LPCWSTR str
, INT count
,
983 TRACE("not bug compatible.\n");
984 return GetTextExtentPoint32W( hdc
, str
, count
, size
);
988 /***********************************************************************
989 * GetTextExtentExPointA (GDI32.@)
991 BOOL WINAPI
GetTextExtentExPointA( HDC hdc
, LPCSTR str
, INT count
,
992 INT maxExt
, LPINT lpnFit
,
993 LPINT alpDx
, LPSIZE size
)
1001 NULL
== (walpDx
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(INT
))))
1004 p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
1005 ret
= GetTextExtentExPointW( hdc
, p
, wlen
, maxExt
, lpnFit
, walpDx
, size
);
1008 INT n
= lpnFit
? *lpnFit
: wlen
;
1010 for(i
= 0, j
= 0; i
< n
; i
++, j
++)
1012 alpDx
[j
] = walpDx
[i
];
1013 if (IsDBCSLeadByte(str
[j
])) alpDx
[++j
] = walpDx
[i
];
1016 if (lpnFit
) *lpnFit
= WideCharToMultiByte(CP_ACP
,0,p
,*lpnFit
,NULL
,0,NULL
,NULL
);
1017 HeapFree( GetProcessHeap(), 0, p
);
1018 HeapFree( GetProcessHeap(), 0, walpDx
);
1023 /***********************************************************************
1024 * GetTextExtentExPointW (GDI32.@)
1026 * Return the size of the string as it would be if it was output properly by
1029 * This should include
1030 * - Intercharacter spacing
1031 * - justification spacing (not yet done)
1032 * - kerning? see below
1034 * Kerning. Since kerning would be carried out by the rendering code it should
1035 * be done by the driver. However they don't support it yet. Also I am not
1036 * yet persuaded that (certainly under Win95) any kerning is actually done.
1038 * str: According to MSDN this should be null-terminated. That is not true; a
1039 * null will not terminate it early.
1040 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1041 * than count. I have seen it be either the size of the full string or
1042 * 1 less than the size of the full string. I have not seen it bear any
1043 * resemblance to the portion that would fit.
1044 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1045 * trailing intercharacter spacing and any trailing justification.
1048 * Currently we do this by measuring each character etc. We should do it by
1049 * passing the request to the driver, perhaps by extending the
1050 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1051 * thinking about kerning issues and rounding issues in the justification.
1054 BOOL WINAPI
GetTextExtentExPointW( HDC hdc
, LPCWSTR str
, INT count
,
1055 INT maxExt
, LPINT lpnFit
,
1056 LPINT alpDx
, LPSIZE size
)
1064 TRACE("(%p, %s, %d)\n",hdc
,debugstr_wn(str
,count
),maxExt
);
1066 dc
= get_dc_ptr(hdc
);
1070 GetTextMetricsW(hdc
, &tm
);
1072 /* If we need to calculate nFit, then we need the partial extents even if
1073 the user hasn't provided us with an array. */
1076 dxs
= alpDx
? alpDx
: HeapAlloc(GetProcessHeap(), 0, count
* sizeof alpDx
[0]);
1080 SetLastError(ERROR_OUTOFMEMORY
);
1088 ret
= WineEngGetTextExtentExPoint(dc
->gdiFont
, str
, count
,
1089 0, NULL
, dxs
, size
);
1090 else if (dc
->funcs
->pGetTextExtentExPoint
)
1091 ret
= dc
->funcs
->pGetTextExtentExPoint(dc
->physDev
, str
, count
,
1092 0, NULL
, dxs
, size
);
1094 /* Perform device size to world size transformations. */
1097 INT extra
= dc
->charExtra
,
1098 breakExtra
= dc
->breakExtra
,
1099 breakRem
= dc
->breakRem
,
1104 for (i
= 0; i
< count
; ++i
)
1106 dxs
[i
] = abs(INTERNAL_XDSTOWS(dc
, dxs
[i
]));
1107 dxs
[i
] += (i
+1) * extra
;
1108 if (count
> 1 && (breakExtra
|| breakRem
) && str
[i
] == tm
.tmBreakChar
)
1110 dxs
[i
] += breakExtra
;
1117 if (dxs
[i
] <= maxExt
)
1120 breakRem
= dc
->breakRem
;
1122 size
->cx
= abs(INTERNAL_XDSTOWS(dc
, size
->cx
));
1123 size
->cy
= abs(INTERNAL_YDSTOWS(dc
, size
->cy
));
1125 if (!dxs
&& count
> 1 && (breakExtra
|| breakRem
))
1127 for (i
= 0; i
< count
; i
++)
1129 if (str
[i
] == tm
.tmBreakChar
)
1131 size
->cx
+= breakExtra
;
1146 HeapFree(GetProcessHeap(), 0, dxs
);
1148 release_dc_ptr( dc
);
1150 TRACE("returning %d %d x %d\n",nFit
,size
->cx
,size
->cy
);
1154 /***********************************************************************
1155 * GetTextMetricsA (GDI32.@)
1157 BOOL WINAPI
GetTextMetricsA( HDC hdc
, TEXTMETRICA
*metrics
)
1161 if (!GetTextMetricsW( hdc
, &tm32
)) return FALSE
;
1162 FONT_TextMetricWToA( &tm32
, metrics
);
1166 /***********************************************************************
1167 * GetTextMetricsW (GDI32.@)
1169 BOOL WINAPI
GetTextMetricsW( HDC hdc
, TEXTMETRICW
*metrics
)
1172 DC
* dc
= get_dc_ptr( hdc
);
1173 if (!dc
) return FALSE
;
1176 ret
= WineEngGetTextMetrics(dc
->gdiFont
, metrics
);
1177 else if (dc
->funcs
->pGetTextMetrics
)
1178 ret
= dc
->funcs
->pGetTextMetrics( dc
->physDev
, metrics
);
1182 /* device layer returns values in device units
1183 * therefore we have to convert them to logical */
1185 metrics
->tmDigitizedAspectX
= GetDeviceCaps(hdc
, LOGPIXELSX
);
1186 metrics
->tmDigitizedAspectY
= GetDeviceCaps(hdc
, LOGPIXELSY
);
1188 #define WDPTOLP(x) ((x<0)? \
1189 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1190 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1191 #define HDPTOLP(y) ((y<0)? \
1192 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1193 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1195 metrics
->tmHeight
= HDPTOLP(metrics
->tmHeight
);
1196 metrics
->tmAscent
= HDPTOLP(metrics
->tmAscent
);
1197 metrics
->tmDescent
= HDPTOLP(metrics
->tmDescent
);
1198 metrics
->tmInternalLeading
= HDPTOLP(metrics
->tmInternalLeading
);
1199 metrics
->tmExternalLeading
= HDPTOLP(metrics
->tmExternalLeading
);
1200 metrics
->tmAveCharWidth
= WDPTOLP(metrics
->tmAveCharWidth
);
1201 metrics
->tmMaxCharWidth
= WDPTOLP(metrics
->tmMaxCharWidth
);
1202 metrics
->tmOverhang
= WDPTOLP(metrics
->tmOverhang
);
1206 TRACE("text metrics:\n"
1207 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1208 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1209 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1210 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1211 " PitchAndFamily = %02x\n"
1212 " --------------------\n"
1213 " InternalLeading = %i\n"
1217 metrics
->tmWeight
, metrics
->tmFirstChar
, metrics
->tmAveCharWidth
,
1218 metrics
->tmItalic
, metrics
->tmLastChar
, metrics
->tmMaxCharWidth
,
1219 metrics
->tmUnderlined
, metrics
->tmDefaultChar
, metrics
->tmOverhang
,
1220 metrics
->tmStruckOut
, metrics
->tmBreakChar
, metrics
->tmCharSet
,
1221 metrics
->tmPitchAndFamily
,
1222 metrics
->tmInternalLeading
,
1225 metrics
->tmHeight
);
1227 release_dc_ptr( dc
);
1232 /***********************************************************************
1233 * GetOutlineTextMetricsA (GDI32.@)
1234 * Gets metrics for TrueType fonts.
1237 * If the supplied buffer isn't big enough Windows partially fills it up to
1238 * its given length and returns that length.
1241 * Success: Non-zero or size of required buffer
1244 UINT WINAPI
GetOutlineTextMetricsA(
1245 HDC hdc
, /* [in] Handle of device context */
1246 UINT cbData
, /* [in] Size of metric data array */
1247 LPOUTLINETEXTMETRICA lpOTM
) /* [out] Address of metric data array */
1249 char buf
[512], *ptr
;
1251 OUTLINETEXTMETRICW
*lpOTMW
= (OUTLINETEXTMETRICW
*)buf
;
1252 OUTLINETEXTMETRICA
*output
= lpOTM
;
1255 if((ret
= GetOutlineTextMetricsW(hdc
, 0, NULL
)) == 0)
1257 if(ret
> sizeof(buf
))
1258 lpOTMW
= HeapAlloc(GetProcessHeap(), 0, ret
);
1259 GetOutlineTextMetricsW(hdc
, ret
, lpOTMW
);
1261 needed
= sizeof(OUTLINETEXTMETRICA
);
1262 if(lpOTMW
->otmpFamilyName
)
1263 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1264 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFamilyName
), -1,
1265 NULL
, 0, NULL
, NULL
);
1266 if(lpOTMW
->otmpFaceName
)
1267 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1268 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFaceName
), -1,
1269 NULL
, 0, NULL
, NULL
);
1270 if(lpOTMW
->otmpStyleName
)
1271 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1272 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpStyleName
), -1,
1273 NULL
, 0, NULL
, NULL
);
1274 if(lpOTMW
->otmpFullName
)
1275 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1276 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFullName
), -1,
1277 NULL
, 0, NULL
, NULL
);
1284 TRACE("needed = %d\n", needed
);
1286 /* Since the supplied buffer isn't big enough, we'll alloc one
1287 that is and memcpy the first cbData bytes into the lpOTM at
1289 output
= HeapAlloc(GetProcessHeap(), 0, needed
);
1291 ret
= output
->otmSize
= min(needed
, cbData
);
1292 FONT_TextMetricWToA( &lpOTMW
->otmTextMetrics
, &output
->otmTextMetrics
);
1293 output
->otmFiller
= 0;
1294 output
->otmPanoseNumber
= lpOTMW
->otmPanoseNumber
;
1295 output
->otmfsSelection
= lpOTMW
->otmfsSelection
;
1296 output
->otmfsType
= lpOTMW
->otmfsType
;
1297 output
->otmsCharSlopeRise
= lpOTMW
->otmsCharSlopeRise
;
1298 output
->otmsCharSlopeRun
= lpOTMW
->otmsCharSlopeRun
;
1299 output
->otmItalicAngle
= lpOTMW
->otmItalicAngle
;
1300 output
->otmEMSquare
= lpOTMW
->otmEMSquare
;
1301 output
->otmAscent
= lpOTMW
->otmAscent
;
1302 output
->otmDescent
= lpOTMW
->otmDescent
;
1303 output
->otmLineGap
= lpOTMW
->otmLineGap
;
1304 output
->otmsCapEmHeight
= lpOTMW
->otmsCapEmHeight
;
1305 output
->otmsXHeight
= lpOTMW
->otmsXHeight
;
1306 output
->otmrcFontBox
= lpOTMW
->otmrcFontBox
;
1307 output
->otmMacAscent
= lpOTMW
->otmMacAscent
;
1308 output
->otmMacDescent
= lpOTMW
->otmMacDescent
;
1309 output
->otmMacLineGap
= lpOTMW
->otmMacLineGap
;
1310 output
->otmusMinimumPPEM
= lpOTMW
->otmusMinimumPPEM
;
1311 output
->otmptSubscriptSize
= lpOTMW
->otmptSubscriptSize
;
1312 output
->otmptSubscriptOffset
= lpOTMW
->otmptSubscriptOffset
;
1313 output
->otmptSuperscriptSize
= lpOTMW
->otmptSuperscriptSize
;
1314 output
->otmptSuperscriptOffset
= lpOTMW
->otmptSuperscriptOffset
;
1315 output
->otmsStrikeoutSize
= lpOTMW
->otmsStrikeoutSize
;
1316 output
->otmsStrikeoutPosition
= lpOTMW
->otmsStrikeoutPosition
;
1317 output
->otmsUnderscoreSize
= lpOTMW
->otmsUnderscoreSize
;
1318 output
->otmsUnderscorePosition
= lpOTMW
->otmsUnderscorePosition
;
1321 ptr
= (char*)(output
+ 1);
1322 left
= needed
- sizeof(*output
);
1324 if(lpOTMW
->otmpFamilyName
) {
1325 output
->otmpFamilyName
= (LPSTR
)(ptr
- (char*)output
);
1326 len
= WideCharToMultiByte(CP_ACP
, 0,
1327 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFamilyName
), -1,
1328 ptr
, left
, NULL
, NULL
);
1332 output
->otmpFamilyName
= 0;
1334 if(lpOTMW
->otmpFaceName
) {
1335 output
->otmpFaceName
= (LPSTR
)(ptr
- (char*)output
);
1336 len
= WideCharToMultiByte(CP_ACP
, 0,
1337 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFaceName
), -1,
1338 ptr
, left
, NULL
, NULL
);
1342 output
->otmpFaceName
= 0;
1344 if(lpOTMW
->otmpStyleName
) {
1345 output
->otmpStyleName
= (LPSTR
)(ptr
- (char*)output
);
1346 len
= WideCharToMultiByte(CP_ACP
, 0,
1347 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpStyleName
), -1,
1348 ptr
, left
, NULL
, NULL
);
1352 output
->otmpStyleName
= 0;
1354 if(lpOTMW
->otmpFullName
) {
1355 output
->otmpFullName
= (LPSTR
)(ptr
- (char*)output
);
1356 len
= WideCharToMultiByte(CP_ACP
, 0,
1357 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFullName
), -1,
1358 ptr
, left
, NULL
, NULL
);
1361 output
->otmpFullName
= 0;
1365 if(output
!= lpOTM
) {
1366 memcpy(lpOTM
, output
, cbData
);
1367 HeapFree(GetProcessHeap(), 0, output
);
1369 /* check if the string offsets really fit into the provided size */
1370 /* FIXME: should we check string length as well? */
1371 /* make sure that we don't read/write beyond the provided buffer */
1372 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFamilyName
) + sizeof(LPSTR
))
1374 if ((UINT_PTR
)lpOTM
->otmpFamilyName
>= lpOTM
->otmSize
)
1375 lpOTM
->otmpFamilyName
= 0; /* doesn't fit */
1378 /* make sure that we don't read/write beyond the provided buffer */
1379 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFaceName
) + sizeof(LPSTR
))
1381 if ((UINT_PTR
)lpOTM
->otmpFaceName
>= lpOTM
->otmSize
)
1382 lpOTM
->otmpFaceName
= 0; /* doesn't fit */
1385 /* make sure that we don't read/write beyond the provided buffer */
1386 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpStyleName
) + sizeof(LPSTR
))
1388 if ((UINT_PTR
)lpOTM
->otmpStyleName
>= lpOTM
->otmSize
)
1389 lpOTM
->otmpStyleName
= 0; /* doesn't fit */
1392 /* make sure that we don't read/write beyond the provided buffer */
1393 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFullName
) + sizeof(LPSTR
))
1395 if ((UINT_PTR
)lpOTM
->otmpFullName
>= lpOTM
->otmSize
)
1396 lpOTM
->otmpFullName
= 0; /* doesn't fit */
1401 if(lpOTMW
!= (OUTLINETEXTMETRICW
*)buf
)
1402 HeapFree(GetProcessHeap(), 0, lpOTMW
);
1408 /***********************************************************************
1409 * GetOutlineTextMetricsW [GDI32.@]
1411 UINT WINAPI
GetOutlineTextMetricsW(
1412 HDC hdc
, /* [in] Handle of device context */
1413 UINT cbData
, /* [in] Size of metric data array */
1414 LPOUTLINETEXTMETRICW lpOTM
) /* [out] Address of metric data array */
1416 DC
*dc
= get_dc_ptr( hdc
);
1417 OUTLINETEXTMETRICW
*output
= lpOTM
;
1420 TRACE("(%p,%d,%p)\n", hdc
, cbData
, lpOTM
);
1424 ret
= WineEngGetOutlineTextMetrics(dc
->gdiFont
, cbData
, output
);
1427 output
= HeapAlloc(GetProcessHeap(), 0, ret
);
1428 WineEngGetOutlineTextMetrics(dc
->gdiFont
, ret
, output
);
1431 output
->otmTextMetrics
.tmDigitizedAspectX
= GetDeviceCaps(hdc
, LOGPIXELSX
);
1432 output
->otmTextMetrics
.tmDigitizedAspectY
= GetDeviceCaps(hdc
, LOGPIXELSY
);
1434 #define WDPTOLP(x) ((x<0)? \
1435 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1436 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1437 #define HDPTOLP(y) ((y<0)? \
1438 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1439 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1441 output
->otmTextMetrics
.tmHeight
= HDPTOLP(output
->otmTextMetrics
.tmHeight
);
1442 output
->otmTextMetrics
.tmAscent
= HDPTOLP(output
->otmTextMetrics
.tmAscent
);
1443 output
->otmTextMetrics
.tmDescent
= HDPTOLP(output
->otmTextMetrics
.tmDescent
);
1444 output
->otmTextMetrics
.tmInternalLeading
= HDPTOLP(output
->otmTextMetrics
.tmInternalLeading
);
1445 output
->otmTextMetrics
.tmExternalLeading
= HDPTOLP(output
->otmTextMetrics
.tmExternalLeading
);
1446 output
->otmTextMetrics
.tmAveCharWidth
= WDPTOLP(output
->otmTextMetrics
.tmAveCharWidth
);
1447 output
->otmTextMetrics
.tmMaxCharWidth
= WDPTOLP(output
->otmTextMetrics
.tmMaxCharWidth
);
1448 output
->otmTextMetrics
.tmOverhang
= WDPTOLP(output
->otmTextMetrics
.tmOverhang
);
1449 output
->otmAscent
= HDPTOLP(output
->otmAscent
);
1450 output
->otmDescent
= HDPTOLP(output
->otmDescent
);
1451 output
->otmLineGap
= abs(INTERNAL_YDSTOWS(dc
,output
->otmLineGap
));
1452 output
->otmsCapEmHeight
= abs(INTERNAL_YDSTOWS(dc
,output
->otmsCapEmHeight
));
1453 output
->otmsXHeight
= abs(INTERNAL_YDSTOWS(dc
,output
->otmsXHeight
));
1454 output
->otmrcFontBox
.top
= HDPTOLP(output
->otmrcFontBox
.top
);
1455 output
->otmrcFontBox
.bottom
= HDPTOLP(output
->otmrcFontBox
.bottom
);
1456 output
->otmrcFontBox
.left
= WDPTOLP(output
->otmrcFontBox
.left
);
1457 output
->otmrcFontBox
.right
= WDPTOLP(output
->otmrcFontBox
.right
);
1458 output
->otmMacAscent
= HDPTOLP(output
->otmMacAscent
);
1459 output
->otmMacDescent
= HDPTOLP(output
->otmMacDescent
);
1460 output
->otmMacLineGap
= abs(INTERNAL_YDSTOWS(dc
,output
->otmMacLineGap
));
1461 output
->otmptSubscriptSize
.x
= WDPTOLP(output
->otmptSubscriptSize
.x
);
1462 output
->otmptSubscriptSize
.y
= HDPTOLP(output
->otmptSubscriptSize
.y
);
1463 output
->otmptSubscriptOffset
.x
= WDPTOLP(output
->otmptSubscriptOffset
.x
);
1464 output
->otmptSubscriptOffset
.y
= HDPTOLP(output
->otmptSubscriptOffset
.y
);
1465 output
->otmptSuperscriptSize
.x
= WDPTOLP(output
->otmptSuperscriptSize
.x
);
1466 output
->otmptSuperscriptSize
.y
= HDPTOLP(output
->otmptSuperscriptSize
.y
);
1467 output
->otmptSuperscriptOffset
.x
= WDPTOLP(output
->otmptSuperscriptOffset
.x
);
1468 output
->otmptSuperscriptOffset
.y
= HDPTOLP(output
->otmptSuperscriptOffset
.y
);
1469 output
->otmsStrikeoutSize
= abs(INTERNAL_YDSTOWS(dc
,output
->otmsStrikeoutSize
));
1470 output
->otmsStrikeoutPosition
= HDPTOLP(output
->otmsStrikeoutPosition
);
1471 output
->otmsUnderscoreSize
= HDPTOLP(output
->otmsUnderscoreSize
);
1472 output
->otmsUnderscorePosition
= HDPTOLP(output
->otmsUnderscorePosition
);
1475 if(output
!= lpOTM
) {
1476 memcpy(lpOTM
, output
, cbData
);
1477 HeapFree(GetProcessHeap(), 0, output
);
1483 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1484 but really this should just be a return 0. */
1486 ret
= sizeof(*lpOTM
);
1491 memset(lpOTM
, 0, ret
);
1492 lpOTM
->otmSize
= sizeof(*lpOTM
);
1493 GetTextMetricsW(hdc
, &lpOTM
->otmTextMetrics
);
1495 Further fill of the structure not implemented,
1496 Needs real values for the structure members
1506 /***********************************************************************
1507 * GetCharWidthW (GDI32.@)
1508 * GetCharWidth32W (GDI32.@)
1510 BOOL WINAPI
GetCharWidth32W( HDC hdc
, UINT firstChar
, UINT lastChar
,
1515 DC
* dc
= get_dc_ptr( hdc
);
1516 if (!dc
) return FALSE
;
1519 ret
= WineEngGetCharWidth( dc
->gdiFont
, firstChar
, lastChar
, buffer
);
1520 else if (dc
->funcs
->pGetCharWidth
)
1521 ret
= dc
->funcs
->pGetCharWidth( dc
->physDev
, firstChar
, lastChar
, buffer
);
1525 /* convert device units to logical */
1526 for( i
= firstChar
; i
<= lastChar
; i
++, buffer
++ )
1527 *buffer
= INTERNAL_XDSTOWS(dc
, *buffer
);
1530 release_dc_ptr( dc
);
1535 /***********************************************************************
1536 * GetCharWidthA (GDI32.@)
1537 * GetCharWidth32A (GDI32.@)
1539 BOOL WINAPI
GetCharWidth32A( HDC hdc
, UINT firstChar
, UINT lastChar
,
1542 INT i
, wlen
, count
= (INT
)(lastChar
- firstChar
+ 1);
1547 if(count
<= 0) return FALSE
;
1549 str
= HeapAlloc(GetProcessHeap(), 0, count
);
1550 for(i
= 0; i
< count
; i
++)
1551 str
[i
] = (BYTE
)(firstChar
+ i
);
1553 wstr
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
1555 for(i
= 0; i
< wlen
; i
++)
1557 if(!GetCharWidth32W(hdc
, wstr
[i
], wstr
[i
], buffer
))
1565 HeapFree(GetProcessHeap(), 0, str
);
1566 HeapFree(GetProcessHeap(), 0, wstr
);
1572 /***********************************************************************
1573 * ExtTextOutA (GDI32.@)
1577 BOOL WINAPI
ExtTextOutA( HDC hdc
, INT x
, INT y
, UINT flags
,
1578 const RECT
*lprect
, LPCSTR str
, UINT count
, const INT
*lpDx
)
1586 if (flags
& ETO_GLYPH_INDEX
)
1587 return ExtTextOutW( hdc
, x
, y
, flags
, lprect
, (LPCWSTR
)str
, count
, lpDx
);
1589 p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, &codepage
);
1592 unsigned int i
= 0, j
= 0;
1594 lpDxW
= HeapAlloc( GetProcessHeap(), 0, wlen
*sizeof(INT
));
1596 if(IsDBCSLeadByteEx(codepage
, str
[i
])) {
1597 lpDxW
[j
++] = lpDx
[i
] + lpDx
[i
+1];
1600 lpDxW
[j
++] = lpDx
[i
];
1606 ret
= ExtTextOutW( hdc
, x
, y
, flags
, lprect
, p
, wlen
, lpDxW
);
1608 HeapFree( GetProcessHeap(), 0, p
);
1609 HeapFree( GetProcessHeap(), 0, lpDxW
);
1614 /***********************************************************************
1615 * ExtTextOutW (GDI32.@)
1617 * Draws text using the currently selected font, background color, and text color.
1621 * x,y [I] coordinates of string
1623 * ETO_GRAYED - undocumented on MSDN
1624 * ETO_OPAQUE - use background color for fill the rectangle
1625 * ETO_CLIPPED - clipping text to the rectangle
1626 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1627 * than encoded characters. Implies ETO_IGNORELANGUAGE
1628 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1629 * Affects BiDi ordering
1630 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1631 * ETO_PDY - unimplemented
1632 * ETO_NUMERICSLATIN - unimplemented always assumed -
1633 * do not translate numbers into locale representations
1634 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1635 * lprect [I] dimensions for clipping or/and opaquing
1636 * str [I] text string
1637 * count [I] number of symbols in string
1638 * lpDx [I] optional parameter with distance between drawing characters
1644 BOOL WINAPI
ExtTextOutW( HDC hdc
, INT x
, INT y
, UINT flags
,
1645 const RECT
*lprect
, LPCWSTR str
, UINT count
, const INT
*lpDx
)
1648 LPWSTR reordered_str
= (LPWSTR
)str
;
1649 WORD
*glyphs
= NULL
;
1650 UINT align
= GetTextAlign( hdc
);
1654 double cosEsc
, sinEsc
;
1655 INT
*deltas
= NULL
, char_extra
;
1658 BOOL done_extents
= FALSE
;
1659 INT width
= 0, xwidth
= 0, ywidth
= 0;
1661 DC
* dc
= get_dc_ptr( hdc
);
1663 static int quietfixme
= 0;
1665 if (!dc
) return FALSE
;
1667 breakRem
= dc
->breakRem
;
1669 if (quietfixme
== 0 && flags
& (ETO_NUMERICSLOCAL
| ETO_NUMERICSLATIN
| ETO_PDY
))
1671 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY unimplemented\n");
1674 if (!dc
->funcs
->pExtTextOut
&& !PATH_IsPathOpen(dc
->path
))
1676 release_dc_ptr( dc
);
1681 type
= GetObjectType(hdc
);
1682 if(type
== OBJ_METADC
|| type
== OBJ_ENHMETADC
)
1684 ret
= dc
->funcs
->pExtTextOut(dc
->physDev
, x
, y
, flags
, lprect
, str
, count
, lpDx
);
1685 release_dc_ptr( dc
);
1690 flags
&= ~ETO_CLIPPED
;
1692 if( !(flags
& (ETO_GLYPH_INDEX
| ETO_IGNORELANGUAGE
)) && count
> 0 )
1694 reordered_str
= HeapAlloc(GetProcessHeap(), 0, count
*sizeof(WCHAR
));
1696 BIDI_Reorder( str
, count
, GCP_REORDER
,
1697 ((flags
&ETO_RTLREADING
)!=0 || (GetTextAlign(hdc
)&TA_RTLREADING
)!=0)?
1698 WINE_GCPW_FORCE_RTL
:WINE_GCPW_FORCE_LTR
,
1699 reordered_str
, count
, NULL
);
1701 flags
|= ETO_IGNORELANGUAGE
;
1704 TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc
, x
, y
, flags
,
1705 lprect
, debugstr_wn(str
, count
), count
, lpDx
);
1707 if(flags
& ETO_GLYPH_INDEX
)
1708 glyphs
= reordered_str
;
1711 TRACE("rect: %d,%d - %d,%d\n", lprect
->left
, lprect
->top
, lprect
->right
,
1713 TRACE("align = %x bkmode = %x mapmode = %x\n", align
, GetBkMode(hdc
), GetMapMode(hdc
));
1715 if(align
& TA_UPDATECP
)
1717 GetCurrentPositionEx( hdc
, &pt
);
1722 GetTextMetricsW(hdc
, &tm
);
1723 GetObjectW(GetCurrentObject(hdc
, OBJ_FONT
), sizeof(lf
), &lf
);
1725 if(!(tm
.tmPitchAndFamily
& TMPF_VECTOR
)) /* Non-scalable fonts shouldn't be rotated */
1726 lf
.lfEscapement
= 0;
1728 if(lf
.lfEscapement
!= 0)
1730 cosEsc
= cos(lf
.lfEscapement
* M_PI
/ 1800);
1731 sinEsc
= sin(lf
.lfEscapement
* M_PI
/ 1800);
1739 if(flags
& (ETO_CLIPPED
| ETO_OPAQUE
))
1743 if(flags
& ETO_GLYPH_INDEX
)
1744 GetTextExtentPointI(hdc
, glyphs
, count
, &sz
);
1746 GetTextExtentPointW(hdc
, reordered_str
, count
, &sz
);
1748 done_extents
= TRUE
;
1751 rc
.right
= x
+ sz
.cx
;
1752 rc
.bottom
= y
+ sz
.cy
;
1759 LPtoDP(hdc
, (POINT
*)&rc
, 2);
1761 if(rc
.left
> rc
.right
) {INT tmp
= rc
.left
; rc
.left
= rc
.right
; rc
.right
= tmp
;}
1762 if(rc
.top
> rc
.bottom
) {INT tmp
= rc
.top
; rc
.top
= rc
.bottom
; rc
.bottom
= tmp
;}
1765 if ((flags
& ETO_OPAQUE
) && !PATH_IsPathOpen(dc
->path
))
1766 dc
->funcs
->pExtTextOut(dc
->physDev
, 0, 0, ETO_OPAQUE
, &rc
, NULL
, 0, NULL
);
1776 LPtoDP(hdc
, &pt
, 1);
1780 char_extra
= GetTextCharacterExtra(hdc
);
1781 if(char_extra
|| dc
->breakExtra
|| breakRem
|| lpDx
|| lf
.lfEscapement
!= 0)
1785 deltas
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(INT
));
1786 for(i
= 0; i
< count
; i
++)
1788 if(lpDx
&& (flags
& ETO_PDY
))
1789 deltas
[i
] = lpDx
[i
*2] + char_extra
;
1791 deltas
[i
] = lpDx
[i
] + char_extra
;
1794 if(flags
& ETO_GLYPH_INDEX
)
1795 GetTextExtentPointI(hdc
, glyphs
+ i
, 1, &tmpsz
);
1797 GetTextExtentPointW(hdc
, reordered_str
+ i
, 1, &tmpsz
);
1799 deltas
[i
] = tmpsz
.cx
;
1802 if (!(flags
& ETO_GLYPH_INDEX
) && (dc
->breakExtra
|| breakRem
) && reordered_str
[i
] == tm
.tmBreakChar
)
1804 deltas
[i
] = deltas
[i
] + dc
->breakExtra
;
1811 deltas
[i
] = INTERNAL_XWSTODS(dc
, deltas
[i
]);
1819 if(flags
& ETO_GLYPH_INDEX
)
1820 GetTextExtentPointI(hdc
, glyphs
, count
, &sz
);
1822 GetTextExtentPointW(hdc
, reordered_str
, count
, &sz
);
1823 done_extents
= TRUE
;
1825 width
= INTERNAL_XWSTODS(dc
, sz
.cx
);
1827 xwidth
= width
* cosEsc
;
1828 ywidth
= width
* sinEsc
;
1830 tm
.tmAscent
= abs(INTERNAL_YWSTODS(dc
, tm
.tmAscent
));
1831 tm
.tmDescent
= abs(INTERNAL_YWSTODS(dc
, tm
.tmDescent
));
1832 switch( align
& (TA_LEFT
| TA_RIGHT
| TA_CENTER
) )
1835 if (align
& TA_UPDATECP
)
1839 DPtoLP(hdc
, &pt
, 1);
1840 MoveToEx(hdc
, pt
.x
, pt
.y
, NULL
);
1852 if (align
& TA_UPDATECP
)
1856 DPtoLP(hdc
, &pt
, 1);
1857 MoveToEx(hdc
, pt
.x
, pt
.y
, NULL
);
1862 switch( align
& (TA_TOP
| TA_BOTTOM
| TA_BASELINE
) )
1865 y
+= tm
.tmAscent
* cosEsc
;
1866 x
+= tm
.tmAscent
* sinEsc
;
1870 y
-= tm
.tmDescent
* cosEsc
;
1871 x
-= tm
.tmDescent
* sinEsc
;
1878 if (GetBkMode(hdc
) != TRANSPARENT
&& !PATH_IsPathOpen(dc
->path
))
1880 if(!((flags
& ETO_CLIPPED
) && (flags
& ETO_OPAQUE
)))
1882 if(!(flags
& ETO_OPAQUE
) || x
< rc
.left
|| x
+ width
>= rc
.right
||
1883 y
- tm
.tmAscent
< rc
.top
|| y
+ tm
.tmDescent
>= rc
.bottom
)
1887 rc
.right
= x
+ width
;
1888 rc
.top
= y
- tm
.tmAscent
;
1889 rc
.bottom
= y
+ tm
.tmDescent
;
1890 dc
->funcs
->pExtTextOut(dc
->physDev
, 0, 0, ETO_OPAQUE
, &rc
, NULL
, 0, NULL
);
1895 if(FontIsLinked(hdc
) && !(flags
& ETO_GLYPH_INDEX
))
1897 HFONT orig_font
= dc
->hFont
, cur_font
;
1899 INT span
= 0, *offsets
= NULL
;
1902 glyphs
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(WORD
));
1903 for(i
= 0; i
< count
; i
++)
1905 WineEngGetLinkedHFont(dc
, reordered_str
[i
], &cur_font
, &glyph
);
1906 if(cur_font
!= dc
->hFont
)
1911 offsets
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(*deltas
));
1916 for(j
= 1; j
< count
; j
++)
1918 GetTextExtentPointW(hdc
, reordered_str
+ j
- 1, 1, &tmpsz
);
1919 offsets
[j
] = offsets
[j
-1] + INTERNAL_XWSTODS(dc
, tmpsz
.cx
);
1924 for(j
= 1; j
< count
; j
++)
1925 offsets
[j
] = offsets
[j
-1] + deltas
[j
];
1930 if (PATH_IsPathOpen(dc
->path
))
1931 ret
= PATH_ExtTextOut(dc
, x
+ offsets
[i
- span
] * cosEsc
, y
- offsets
[i
- span
] * sinEsc
,
1932 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
,
1933 glyphs
, span
, deltas
? deltas
+ i
- span
: NULL
);
1935 dc
->funcs
->pExtTextOut(dc
->physDev
, x
+ offsets
[i
- span
] * cosEsc
, y
- offsets
[i
- span
] * sinEsc
,
1936 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
,
1937 glyphs
, span
, deltas
? deltas
+ i
- span
: NULL
);
1940 SelectObject(hdc
, cur_font
);
1942 glyphs
[span
++] = glyph
;
1946 if (PATH_IsPathOpen(dc
->path
))
1947 ret
= PATH_ExtTextOut(dc
, x
+ (offsets
? offsets
[count
- span
] * cosEsc
: 0),
1948 y
- (offsets
? offsets
[count
- span
] * sinEsc
: 0),
1949 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
,
1950 glyphs
, span
, deltas
? deltas
+ count
- span
: NULL
);
1952 ret
= dc
->funcs
->pExtTextOut(dc
->physDev
, x
+ (offsets
? offsets
[count
- span
] * cosEsc
: 0),
1953 y
- (offsets
? offsets
[count
- span
] * sinEsc
: 0),
1954 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
,
1955 glyphs
, span
, deltas
? deltas
+ count
- span
: NULL
);
1956 SelectObject(hdc
, orig_font
);
1957 HeapFree(GetProcessHeap(), 0, offsets
);
1963 if(!(flags
& ETO_GLYPH_INDEX
) && dc
->gdiFont
)
1965 glyphs
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(WORD
));
1966 GetGlyphIndicesW(hdc
, reordered_str
, count
, glyphs
, 0);
1967 flags
|= ETO_GLYPH_INDEX
;
1970 if (PATH_IsPathOpen(dc
->path
))
1971 ret
= PATH_ExtTextOut(dc
, x
, y
, (flags
& ~ETO_OPAQUE
), &rc
,
1972 glyphs
? glyphs
: reordered_str
, count
, deltas
);
1974 ret
= dc
->funcs
->pExtTextOut(dc
->physDev
, x
, y
, (flags
& ~ETO_OPAQUE
), &rc
,
1975 glyphs
? glyphs
: reordered_str
, count
, deltas
);
1979 HeapFree(GetProcessHeap(), 0, deltas
);
1980 if(glyphs
!= reordered_str
)
1981 HeapFree(GetProcessHeap(), 0, glyphs
);
1982 if(reordered_str
!= str
)
1983 HeapFree(GetProcessHeap(), 0, reordered_str
);
1985 release_dc_ptr( dc
);
1987 if (ret
&& (lf
.lfUnderline
|| lf
.lfStrikeOut
))
1989 int underlinePos
, strikeoutPos
;
1990 int underlineWidth
, strikeoutWidth
;
1991 UINT size
= GetOutlineTextMetricsW(hdc
, 0, NULL
);
1992 OUTLINETEXTMETRICW
* otm
= NULL
;
1997 underlineWidth
= tm
.tmAscent
/ 20 + 1;
1998 strikeoutPos
= tm
.tmAscent
/ 2;
1999 strikeoutWidth
= underlineWidth
;
2003 otm
= HeapAlloc(GetProcessHeap(), 0, size
);
2004 GetOutlineTextMetricsW(hdc
, size
, otm
);
2005 underlinePos
= otm
->otmsUnderscorePosition
;
2006 underlineWidth
= otm
->otmsUnderscoreSize
;
2007 strikeoutPos
= otm
->otmsStrikeoutPosition
;
2008 strikeoutWidth
= otm
->otmsStrikeoutSize
;
2009 HeapFree(GetProcessHeap(), 0, otm
);
2012 if (PATH_IsPathOpen(dc
->path
))
2016 HBRUSH hbrush
= CreateSolidBrush(GetTextColor(hdc
));
2018 hbrush
= SelectObject(hdc
, hbrush
);
2019 hpen
= SelectObject(hdc
, GetStockObject(NULL_PEN
));
2023 pts
[0].x
= x
- underlinePos
* sinEsc
;
2024 pts
[0].y
= y
- underlinePos
* cosEsc
;
2025 pts
[1].x
= x
+ xwidth
- underlinePos
* sinEsc
;
2026 pts
[1].y
= y
- ywidth
- underlinePos
* cosEsc
;
2027 pts
[2].x
= pts
[1].x
+ underlineWidth
* sinEsc
;
2028 pts
[2].y
= pts
[1].y
+ underlineWidth
* cosEsc
;
2029 pts
[3].x
= pts
[0].x
+ underlineWidth
* sinEsc
;
2030 pts
[3].y
= pts
[0].y
+ underlineWidth
* cosEsc
;
2031 pts
[4].x
= pts
[0].x
;
2032 pts
[4].y
= pts
[0].y
;
2033 DPtoLP(hdc
, pts
, 5);
2034 Polygon(hdc
, pts
, 5);
2039 pts
[0].x
= x
- strikeoutPos
* sinEsc
;
2040 pts
[0].y
= y
- strikeoutPos
* cosEsc
;
2041 pts
[1].x
= x
+ xwidth
- strikeoutPos
* sinEsc
;
2042 pts
[1].y
= y
- ywidth
- strikeoutPos
* cosEsc
;
2043 pts
[2].x
= pts
[1].x
+ strikeoutWidth
* sinEsc
;
2044 pts
[2].y
= pts
[1].y
+ strikeoutWidth
* cosEsc
;
2045 pts
[3].x
= pts
[0].x
+ strikeoutWidth
* sinEsc
;
2046 pts
[3].y
= pts
[0].y
+ strikeoutWidth
* cosEsc
;
2047 pts
[4].x
= pts
[0].x
;
2048 pts
[4].y
= pts
[0].y
;
2049 DPtoLP(hdc
, pts
, 5);
2050 Polygon(hdc
, pts
, 5);
2053 SelectObject(hdc
, hpen
);
2054 hbrush
= SelectObject(hdc
, hbrush
);
2055 DeleteObject(hbrush
);
2059 POINT pts
[2], oldpt
;
2064 hpen
= CreatePen(PS_SOLID
, underlineWidth
, GetTextColor(hdc
));
2065 hpen
= SelectObject(hdc
, hpen
);
2068 pts
[1].x
= x
+ xwidth
;
2069 pts
[1].y
= y
- ywidth
;
2070 DPtoLP(hdc
, pts
, 2);
2071 MoveToEx(hdc
, pts
[0].x
- underlinePos
* sinEsc
, pts
[0].y
- underlinePos
* cosEsc
, &oldpt
);
2072 LineTo(hdc
, pts
[1].x
- underlinePos
* sinEsc
, pts
[1].y
- underlinePos
* cosEsc
);
2073 MoveToEx(hdc
, oldpt
.x
, oldpt
.y
, NULL
);
2074 DeleteObject(SelectObject(hdc
, hpen
));
2079 hpen
= CreatePen(PS_SOLID
, strikeoutWidth
, GetTextColor(hdc
));
2080 hpen
= SelectObject(hdc
, hpen
);
2083 pts
[1].x
= x
+ xwidth
;
2084 pts
[1].y
= y
- ywidth
;
2085 DPtoLP(hdc
, pts
, 2);
2086 MoveToEx(hdc
, pts
[0].x
- strikeoutPos
* sinEsc
, pts
[0].y
- strikeoutPos
* cosEsc
, &oldpt
);
2087 LineTo(hdc
, pts
[1].x
- strikeoutPos
* sinEsc
, pts
[1].y
- strikeoutPos
* cosEsc
);
2088 MoveToEx(hdc
, oldpt
.x
, oldpt
.y
, NULL
);
2089 DeleteObject(SelectObject(hdc
, hpen
));
2098 /***********************************************************************
2099 * TextOutA (GDI32.@)
2101 BOOL WINAPI
TextOutA( HDC hdc
, INT x
, INT y
, LPCSTR str
, INT count
)
2103 return ExtTextOutA( hdc
, x
, y
, 0, NULL
, str
, count
, NULL
);
2107 /***********************************************************************
2108 * TextOutW (GDI32.@)
2110 BOOL WINAPI
TextOutW(HDC hdc
, INT x
, INT y
, LPCWSTR str
, INT count
)
2112 return ExtTextOutW( hdc
, x
, y
, 0, NULL
, str
, count
, NULL
);
2116 /***********************************************************************
2117 * PolyTextOutA (GDI32.@)
2121 BOOL WINAPI
PolyTextOutA( HDC hdc
, const POLYTEXTA
*pptxt
, INT cStrings
)
2123 for (; cStrings
>0; cStrings
--, pptxt
++)
2124 if (!ExtTextOutA( hdc
, pptxt
->x
, pptxt
->y
, pptxt
->uiFlags
, &pptxt
->rcl
, pptxt
->lpstr
, pptxt
->n
, pptxt
->pdx
))
2131 /***********************************************************************
2132 * PolyTextOutW (GDI32.@)
2134 * Draw several Strings
2140 BOOL WINAPI
PolyTextOutW( HDC hdc
, const POLYTEXTW
*pptxt
, INT cStrings
)
2142 for (; cStrings
>0; cStrings
--, pptxt
++)
2143 if (!ExtTextOutW( hdc
, pptxt
->x
, pptxt
->y
, pptxt
->uiFlags
, &pptxt
->rcl
, pptxt
->lpstr
, pptxt
->n
, pptxt
->pdx
))
2149 /* FIXME: all following APIs ******************************************/
2152 /***********************************************************************
2153 * SetMapperFlags (GDI32.@)
2155 DWORD WINAPI
SetMapperFlags( HDC hDC
, DWORD dwFlag
)
2157 DC
*dc
= get_dc_ptr( hDC
);
2160 if(dc
->funcs
->pSetMapperFlags
)
2162 ret
= dc
->funcs
->pSetMapperFlags( dc
->physDev
, dwFlag
);
2163 /* FIXME: ret is just a success flag, we should return a proper value */
2166 FIXME("(%p, 0x%08x): stub - harmless\n", hDC
, dwFlag
);
2167 release_dc_ptr( dc
);
2171 /***********************************************************************
2172 * GetAspectRatioFilterEx (GDI32.@)
2174 BOOL WINAPI
GetAspectRatioFilterEx( HDC hdc
, LPSIZE pAspectRatio
)
2176 FIXME("(%p, %p): -- Empty Stub !\n", hdc
, pAspectRatio
);
2181 /***********************************************************************
2182 * GetCharABCWidthsA (GDI32.@)
2184 * See GetCharABCWidthsW.
2186 BOOL WINAPI
GetCharABCWidthsA(HDC hdc
, UINT firstChar
, UINT lastChar
,
2189 INT i
, wlen
, count
= (INT
)(lastChar
- firstChar
+ 1);
2194 if(count
<= 0) return FALSE
;
2196 str
= HeapAlloc(GetProcessHeap(), 0, count
);
2197 for(i
= 0; i
< count
; i
++)
2198 str
[i
] = (BYTE
)(firstChar
+ i
);
2200 wstr
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
2202 for(i
= 0; i
< wlen
; i
++)
2204 if(!GetCharABCWidthsW(hdc
, wstr
[i
], wstr
[i
], abc
))
2212 HeapFree(GetProcessHeap(), 0, str
);
2213 HeapFree(GetProcessHeap(), 0, wstr
);
2219 /******************************************************************************
2220 * GetCharABCWidthsW [GDI32.@]
2222 * Retrieves widths of characters in range.
2225 * hdc [I] Handle of device context
2226 * firstChar [I] First character in range to query
2227 * lastChar [I] Last character in range to query
2228 * abc [O] Address of character-width structure
2231 * Only works with TrueType fonts
2237 BOOL WINAPI
GetCharABCWidthsW( HDC hdc
, UINT firstChar
, UINT lastChar
,
2240 DC
*dc
= get_dc_ptr(hdc
);
2244 if (!dc
) return FALSE
;
2248 release_dc_ptr( dc
);
2253 ret
= WineEngGetCharABCWidths( dc
->gdiFont
, firstChar
, lastChar
, abc
);
2259 /* convert device units to logical */
2260 for( i
= firstChar
; i
<= lastChar
; i
++, abc
++ ) {
2261 abc
->abcA
= INTERNAL_XDSTOWS(dc
, abc
->abcA
);
2262 abc
->abcB
= INTERNAL_XDSTOWS(dc
, abc
->abcB
);
2263 abc
->abcC
= INTERNAL_XDSTOWS(dc
, abc
->abcC
);
2268 release_dc_ptr( dc
);
2273 /******************************************************************************
2274 * GetCharABCWidthsI [GDI32.@]
2276 * Retrieves widths of characters in range.
2279 * hdc [I] Handle of device context
2280 * firstChar [I] First glyphs in range to query
2281 * count [I] Last glyphs in range to query
2282 * pgi [i] Array of glyphs to query
2283 * abc [O] Address of character-width structure
2286 * Only works with TrueType fonts
2292 BOOL WINAPI
GetCharABCWidthsI( HDC hdc
, UINT firstChar
, UINT count
,
2293 LPWORD pgi
, LPABC abc
)
2295 DC
*dc
= get_dc_ptr(hdc
);
2299 if (!dc
) return FALSE
;
2303 release_dc_ptr( dc
);
2308 ret
= WineEngGetCharABCWidthsI( dc
->gdiFont
, firstChar
, count
, pgi
, abc
);
2314 /* convert device units to logical */
2315 for( i
= 0; i
< count
; i
++, abc
++ ) {
2316 abc
->abcA
= INTERNAL_XDSTOWS(dc
, abc
->abcA
);
2317 abc
->abcB
= INTERNAL_XDSTOWS(dc
, abc
->abcB
);
2318 abc
->abcC
= INTERNAL_XDSTOWS(dc
, abc
->abcC
);
2323 release_dc_ptr( dc
);
2328 /***********************************************************************
2329 * GetGlyphOutlineA (GDI32.@)
2331 DWORD WINAPI
GetGlyphOutlineA( HDC hdc
, UINT uChar
, UINT fuFormat
,
2332 LPGLYPHMETRICS lpgm
, DWORD cbBuffer
,
2333 LPVOID lpBuffer
, const MAT2
*lpmat2
)
2339 if (!lpmat2
) return GDI_ERROR
;
2341 if(!(fuFormat
& GGO_GLYPH_INDEX
)) {
2344 if(uChar
> 0xff) { /* but, 2 bytes character only */
2346 mbchs
[0] = (uChar
& 0xff00) >> 8;
2347 mbchs
[1] = (uChar
& 0xff);
2350 mbchs
[0] = (uChar
& 0xff);
2352 p
= FONT_mbtowc(hdc
, mbchs
, len
, NULL
, NULL
);
2356 ret
= GetGlyphOutlineW(hdc
, c
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
,
2358 HeapFree(GetProcessHeap(), 0, p
);
2362 /***********************************************************************
2363 * GetGlyphOutlineW (GDI32.@)
2365 DWORD WINAPI
GetGlyphOutlineW( HDC hdc
, UINT uChar
, UINT fuFormat
,
2366 LPGLYPHMETRICS lpgm
, DWORD cbBuffer
,
2367 LPVOID lpBuffer
, const MAT2
*lpmat2
)
2372 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2373 hdc
, uChar
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
, lpmat2
);
2375 if (!lpmat2
) return GDI_ERROR
;
2377 dc
= get_dc_ptr(hdc
);
2378 if(!dc
) return GDI_ERROR
;
2381 ret
= WineEngGetGlyphOutline(dc
->gdiFont
, uChar
, fuFormat
, lpgm
,
2382 cbBuffer
, lpBuffer
, lpmat2
);
2386 release_dc_ptr( dc
);
2391 /***********************************************************************
2392 * CreateScalableFontResourceA (GDI32.@)
2394 BOOL WINAPI
CreateScalableFontResourceA( DWORD fHidden
,
2395 LPCSTR lpszResourceFile
,
2396 LPCSTR lpszFontFile
,
2397 LPCSTR lpszCurrentPath
)
2399 LPWSTR lpszResourceFileW
= NULL
;
2400 LPWSTR lpszFontFileW
= NULL
;
2401 LPWSTR lpszCurrentPathW
= NULL
;
2405 if (lpszResourceFile
)
2407 len
= MultiByteToWideChar(CP_ACP
, 0, lpszResourceFile
, -1, NULL
, 0);
2408 lpszResourceFileW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2409 MultiByteToWideChar(CP_ACP
, 0, lpszResourceFile
, -1, lpszResourceFileW
, len
);
2414 len
= MultiByteToWideChar(CP_ACP
, 0, lpszFontFile
, -1, NULL
, 0);
2415 lpszFontFileW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2416 MultiByteToWideChar(CP_ACP
, 0, lpszFontFile
, -1, lpszFontFileW
, len
);
2419 if (lpszCurrentPath
)
2421 len
= MultiByteToWideChar(CP_ACP
, 0, lpszCurrentPath
, -1, NULL
, 0);
2422 lpszCurrentPathW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2423 MultiByteToWideChar(CP_ACP
, 0, lpszCurrentPath
, -1, lpszCurrentPathW
, len
);
2426 ret
= CreateScalableFontResourceW(fHidden
, lpszResourceFileW
,
2427 lpszFontFileW
, lpszCurrentPathW
);
2429 HeapFree(GetProcessHeap(), 0, lpszResourceFileW
);
2430 HeapFree(GetProcessHeap(), 0, lpszFontFileW
);
2431 HeapFree(GetProcessHeap(), 0, lpszCurrentPathW
);
2436 /***********************************************************************
2437 * CreateScalableFontResourceW (GDI32.@)
2439 BOOL WINAPI
CreateScalableFontResourceW( DWORD fHidden
,
2440 LPCWSTR lpszResourceFile
,
2441 LPCWSTR lpszFontFile
,
2442 LPCWSTR lpszCurrentPath
)
2445 FIXME("(%d,%s,%s,%s): stub\n",
2446 fHidden
, debugstr_w(lpszResourceFile
), debugstr_w(lpszFontFile
),
2447 debugstr_w(lpszCurrentPath
) );
2449 /* fHidden=1 - only visible for the calling app, read-only, not
2450 * enumerated with EnumFonts/EnumFontFamilies
2451 * lpszCurrentPath can be NULL
2454 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2455 if ((f
= CreateFileW(lpszResourceFile
, 0, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, 0)) != INVALID_HANDLE_VALUE
) {
2457 SetLastError(ERROR_FILE_EXISTS
);
2460 return FALSE
; /* create failed */
2463 /*************************************************************************
2464 * GetKerningPairsA (GDI32.@)
2466 DWORD WINAPI
GetKerningPairsA( HDC hDC
, DWORD cPairs
,
2467 LPKERNINGPAIR kern_pairA
)
2472 DWORD i
, total_kern_pairs
, kern_pairs_copied
= 0;
2473 KERNINGPAIR
*kern_pairW
;
2475 if (!cPairs
&& kern_pairA
)
2477 SetLastError(ERROR_INVALID_PARAMETER
);
2481 charset
= GetTextCharset(hDC
);
2482 if (!TranslateCharsetInfo(ULongToPtr(charset
), &csi
, TCI_SRCCHARSET
))
2484 FIXME("Can't find codepage for charset %d\n", charset
);
2487 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2488 * to fail on an invalid character for CP_SYMBOL.
2490 cpi
.DefaultChar
[0] = 0;
2491 if (csi
.ciACP
!= CP_SYMBOL
&& !GetCPInfo(csi
.ciACP
, &cpi
))
2493 FIXME("Can't find codepage %u info\n", csi
.ciACP
);
2496 TRACE("charset %d => codepage %u\n", charset
, csi
.ciACP
);
2498 total_kern_pairs
= GetKerningPairsW(hDC
, 0, NULL
);
2499 if (!total_kern_pairs
) return 0;
2501 kern_pairW
= HeapAlloc(GetProcessHeap(), 0, total_kern_pairs
* sizeof(*kern_pairW
));
2502 GetKerningPairsW(hDC
, total_kern_pairs
, kern_pairW
);
2504 for (i
= 0; i
< total_kern_pairs
; i
++)
2508 if (!WideCharToMultiByte(csi
.ciACP
, 0, &kern_pairW
[i
].wFirst
, 1, &first
, 1, NULL
, NULL
))
2511 if (!WideCharToMultiByte(csi
.ciACP
, 0, &kern_pairW
[i
].wSecond
, 1, &second
, 1, NULL
, NULL
))
2514 if (first
== cpi
.DefaultChar
[0] || second
== cpi
.DefaultChar
[0])
2519 if (kern_pairs_copied
>= cPairs
) break;
2521 kern_pairA
->wFirst
= (BYTE
)first
;
2522 kern_pairA
->wSecond
= (BYTE
)second
;
2523 kern_pairA
->iKernAmount
= kern_pairW
[i
].iKernAmount
;
2526 kern_pairs_copied
++;
2529 HeapFree(GetProcessHeap(), 0, kern_pairW
);
2531 return kern_pairs_copied
;
2534 /*************************************************************************
2535 * GetKerningPairsW (GDI32.@)
2537 DWORD WINAPI
GetKerningPairsW( HDC hDC
, DWORD cPairs
,
2538 LPKERNINGPAIR lpKerningPairs
)
2543 TRACE("(%p,%d,%p)\n", hDC
, cPairs
, lpKerningPairs
);
2545 if (!cPairs
&& lpKerningPairs
)
2547 SetLastError(ERROR_INVALID_PARAMETER
);
2551 dc
= get_dc_ptr(hDC
);
2555 ret
= WineEngGetKerningPairs(dc
->gdiFont
, cPairs
, lpKerningPairs
);
2557 release_dc_ptr( dc
);
2561 /*************************************************************************
2562 * TranslateCharsetInfo [GDI32.@]
2564 * Fills a CHARSETINFO structure for a character set, code page, or
2565 * font. This allows making the correspondence between different labels
2566 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2567 * of the same encoding.
2569 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2570 * only one codepage should be set in *lpSrc.
2573 * TRUE on success, FALSE on failure.
2576 BOOL WINAPI
TranslateCharsetInfo(
2577 LPDWORD lpSrc
, /* [in]
2578 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2579 if flags == TCI_SRCCHARSET: a character set value
2580 if flags == TCI_SRCCODEPAGE: a code page value
2582 LPCHARSETINFO lpCs
, /* [out] structure to receive charset information */
2583 DWORD flags
/* [in] determines interpretation of lpSrc */)
2587 case TCI_SRCFONTSIG
:
2588 while (!(*lpSrc
>>index
& 0x0001) && index
<MAXTCIINDEX
) index
++;
2590 case TCI_SRCCODEPAGE
:
2591 while (PtrToUlong(lpSrc
) != FONT_tci
[index
].ciACP
&& index
< MAXTCIINDEX
) index
++;
2593 case TCI_SRCCHARSET
:
2594 while (PtrToUlong(lpSrc
) != FONT_tci
[index
].ciCharset
&& index
< MAXTCIINDEX
) index
++;
2599 if (index
>= MAXTCIINDEX
|| FONT_tci
[index
].ciCharset
== DEFAULT_CHARSET
) return FALSE
;
2600 *lpCs
= FONT_tci
[index
];
2604 /*************************************************************************
2605 * GetFontLanguageInfo (GDI32.@)
2607 DWORD WINAPI
GetFontLanguageInfo(HDC hdc
)
2609 FONTSIGNATURE fontsig
;
2610 static const DWORD GCP_DBCS_MASK
=0x003F0000,
2611 GCP_DIACRITIC_MASK
=0x00000000,
2612 FLI_GLYPHS_MASK
=0x00000000,
2613 GCP_GLYPHSHAPE_MASK
=0x00000040,
2614 GCP_KASHIDA_MASK
=0x00000000,
2615 GCP_LIGATE_MASK
=0x00000000,
2616 GCP_USEKERNING_MASK
=0x00000000,
2617 GCP_REORDER_MASK
=0x00000060;
2621 GetTextCharsetInfo( hdc
, &fontsig
, 0 );
2622 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2624 if( (fontsig
.fsCsb
[0]&GCP_DBCS_MASK
)!=0 )
2627 if( (fontsig
.fsCsb
[0]&GCP_DIACRITIC_MASK
)!=0 )
2628 result
|=GCP_DIACRITIC
;
2630 if( (fontsig
.fsCsb
[0]&FLI_GLYPHS_MASK
)!=0 )
2633 if( (fontsig
.fsCsb
[0]&GCP_GLYPHSHAPE_MASK
)!=0 )
2634 result
|=GCP_GLYPHSHAPE
;
2636 if( (fontsig
.fsCsb
[0]&GCP_KASHIDA_MASK
)!=0 )
2637 result
|=GCP_KASHIDA
;
2639 if( (fontsig
.fsCsb
[0]&GCP_LIGATE_MASK
)!=0 )
2642 if( (fontsig
.fsCsb
[0]&GCP_USEKERNING_MASK
)!=0 )
2643 result
|=GCP_USEKERNING
;
2645 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2646 if( GetTextAlign( hdc
) & TA_RTLREADING
)
2647 if( (fontsig
.fsCsb
[0]&GCP_REORDER_MASK
)!=0 )
2648 result
|=GCP_REORDER
;
2654 /*************************************************************************
2655 * GetFontData [GDI32.@]
2657 * Retrieve data for TrueType font.
2661 * success: Number of bytes returned
2662 * failure: GDI_ERROR
2666 * Calls SetLastError()
2669 DWORD WINAPI
GetFontData(HDC hdc
, DWORD table
, DWORD offset
,
2670 LPVOID buffer
, DWORD length
)
2672 DC
*dc
= get_dc_ptr(hdc
);
2673 DWORD ret
= GDI_ERROR
;
2675 if(!dc
) return GDI_ERROR
;
2678 ret
= WineEngGetFontData(dc
->gdiFont
, table
, offset
, buffer
, length
);
2680 release_dc_ptr( dc
);
2684 /*************************************************************************
2685 * GetGlyphIndicesA [GDI32.@]
2687 DWORD WINAPI
GetGlyphIndicesA(HDC hdc
, LPCSTR lpstr
, INT count
,
2688 LPWORD pgi
, DWORD flags
)
2694 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2695 hdc
, debugstr_an(lpstr
, count
), count
, pgi
, flags
);
2697 lpstrW
= FONT_mbtowc(hdc
, lpstr
, count
, &countW
, NULL
);
2698 ret
= GetGlyphIndicesW(hdc
, lpstrW
, countW
, pgi
, flags
);
2699 HeapFree(GetProcessHeap(), 0, lpstrW
);
2704 /*************************************************************************
2705 * GetGlyphIndicesW [GDI32.@]
2707 DWORD WINAPI
GetGlyphIndicesW(HDC hdc
, LPCWSTR lpstr
, INT count
,
2708 LPWORD pgi
, DWORD flags
)
2710 DC
*dc
= get_dc_ptr(hdc
);
2711 DWORD ret
= GDI_ERROR
;
2713 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2714 hdc
, debugstr_wn(lpstr
, count
), count
, pgi
, flags
);
2716 if(!dc
) return GDI_ERROR
;
2719 ret
= WineEngGetGlyphIndices(dc
->gdiFont
, lpstr
, count
, pgi
, flags
);
2721 release_dc_ptr( dc
);
2725 /*************************************************************************
2726 * GetCharacterPlacementA [GDI32.@]
2728 * See GetCharacterPlacementW.
2731 * the web browser control of ie4 calls this with dwFlags=0
2734 GetCharacterPlacementA(HDC hdc
, LPCSTR lpString
, INT uCount
,
2735 INT nMaxExtent
, GCP_RESULTSA
*lpResults
,
2740 GCP_RESULTSW resultsW
;
2744 TRACE("%s, %d, %d, 0x%08x\n",
2745 debugstr_an(lpString
, uCount
), uCount
, nMaxExtent
, dwFlags
);
2747 /* both structs are equal in size */
2748 memcpy(&resultsW
, lpResults
, sizeof(resultsW
));
2750 lpStringW
= FONT_mbtowc(hdc
, lpString
, uCount
, &uCountW
, &font_cp
);
2751 if(lpResults
->lpOutString
)
2752 resultsW
.lpOutString
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*uCountW
);
2754 ret
= GetCharacterPlacementW(hdc
, lpStringW
, uCountW
, nMaxExtent
, &resultsW
, dwFlags
);
2756 lpResults
->nGlyphs
= resultsW
.nGlyphs
;
2757 lpResults
->nMaxFit
= resultsW
.nMaxFit
;
2759 if(lpResults
->lpOutString
) {
2760 WideCharToMultiByte(font_cp
, 0, resultsW
.lpOutString
, uCountW
,
2761 lpResults
->lpOutString
, uCount
, NULL
, NULL
);
2764 HeapFree(GetProcessHeap(), 0, lpStringW
);
2765 HeapFree(GetProcessHeap(), 0, resultsW
.lpOutString
);
2770 /*************************************************************************
2771 * GetCharacterPlacementW [GDI32.@]
2773 * Retrieve information about a string. This includes the width, reordering,
2774 * Glyphing and so on.
2778 * The width and height of the string if successful, 0 if failed.
2782 * All flags except GCP_REORDER are not yet implemented.
2783 * Reordering is not 100% compliant to the Windows BiDi method.
2784 * Caret positioning is not yet implemented for BiDi.
2785 * Classes are not yet implemented.
2789 GetCharacterPlacementW(
2790 HDC hdc
, /* [in] Device context for which the rendering is to be done */
2791 LPCWSTR lpString
, /* [in] The string for which information is to be returned */
2792 INT uCount
, /* [in] Number of WORDS in string. */
2793 INT nMaxExtent
, /* [in] Maximum extent the string is to take (in HDC logical units) */
2794 GCP_RESULTSW
*lpResults
,/* [in/out] A pointer to a GCP_RESULTSW struct */
2795 DWORD dwFlags
/* [in] Flags specifying how to process the string */
2802 TRACE("%s, %d, %d, 0x%08x\n",
2803 debugstr_wn(lpString
, uCount
), uCount
, nMaxExtent
, dwFlags
);
2805 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2806 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2807 lpResults
->lStructSize
, lpResults
->lpOutString
, lpResults
->lpOrder
,
2808 lpResults
->lpDx
, lpResults
->lpCaretPos
, lpResults
->lpClass
,
2809 lpResults
->lpGlyphs
, lpResults
->nGlyphs
, lpResults
->nMaxFit
);
2811 if(dwFlags
&(~GCP_REORDER
)) FIXME("flags 0x%08x ignored\n", dwFlags
);
2812 if(lpResults
->lpClass
) FIXME("classes not implemented\n");
2813 if (lpResults
->lpCaretPos
&& (dwFlags
& GCP_REORDER
))
2814 FIXME("Caret positions for complex scripts not implemented\n");
2816 nSet
= (UINT
)uCount
;
2817 if(nSet
> lpResults
->nGlyphs
)
2818 nSet
= lpResults
->nGlyphs
;
2820 /* return number of initialized fields */
2821 lpResults
->nGlyphs
= nSet
;
2823 if((dwFlags
&GCP_REORDER
)==0 )
2825 /* Treat the case where no special handling was requested in a fastpath way */
2826 /* copy will do if the GCP_REORDER flag is not set */
2827 if(lpResults
->lpOutString
)
2828 memcpy( lpResults
->lpOutString
, lpString
, nSet
* sizeof(WCHAR
));
2830 if(lpResults
->lpOrder
)
2832 for(i
= 0; i
< nSet
; i
++)
2833 lpResults
->lpOrder
[i
] = i
;
2837 BIDI_Reorder( lpString
, uCount
, dwFlags
, WINE_GCPW_FORCE_LTR
, lpResults
->lpOutString
,
2838 nSet
, lpResults
->lpOrder
);
2841 /* FIXME: Will use the placement chars */
2842 if (lpResults
->lpDx
)
2845 for (i
= 0; i
< nSet
; i
++)
2847 if (GetCharWidth32W(hdc
, lpString
[i
], lpString
[i
], &c
))
2848 lpResults
->lpDx
[i
]= c
;
2852 if (lpResults
->lpCaretPos
&& !(dwFlags
& GCP_REORDER
))
2856 lpResults
->lpCaretPos
[0] = 0;
2857 for (i
= 1; i
< nSet
; i
++)
2858 if (GetTextExtentPoint32W(hdc
, &(lpString
[i
- 1]), 1, &size
))
2859 lpResults
->lpCaretPos
[i
] = (pos
+= size
.cx
);
2862 if(lpResults
->lpGlyphs
)
2863 GetGlyphIndicesW(hdc
, lpString
, nSet
, lpResults
->lpGlyphs
, 0);
2865 if (GetTextExtentPoint32W(hdc
, lpString
, uCount
, &size
))
2866 ret
= MAKELONG(size
.cx
, size
.cy
);
2871 /*************************************************************************
2872 * GetCharABCWidthsFloatA [GDI32.@]
2874 * See GetCharABCWidthsFloatW.
2876 BOOL WINAPI
GetCharABCWidthsFloatA( HDC hdc
, UINT first
, UINT last
, LPABCFLOAT abcf
)
2878 INT i
, wlen
, count
= (INT
)(last
- first
+ 1);
2883 if (count
<= 0) return FALSE
;
2885 str
= HeapAlloc(GetProcessHeap(), 0, count
);
2887 for(i
= 0; i
< count
; i
++)
2888 str
[i
] = (BYTE
)(first
+ i
);
2890 wstr
= FONT_mbtowc( hdc
, str
, count
, &wlen
, NULL
);
2892 for (i
= 0; i
< wlen
; i
++)
2894 if (!GetCharABCWidthsFloatW( hdc
, wstr
[i
], wstr
[i
], abcf
))
2902 HeapFree( GetProcessHeap(), 0, str
);
2903 HeapFree( GetProcessHeap(), 0, wstr
);
2908 /*************************************************************************
2909 * GetCharABCWidthsFloatW [GDI32.@]
2911 * Retrieves widths of a range of characters.
2914 * hdc [I] Handle to device context.
2915 * first [I] First character in range to query.
2916 * last [I] Last character in range to query.
2917 * abcf [O] Array of LPABCFLOAT structures.
2924 * Only works with TrueType fonts. It also doesn't return real
2925 * floats but converted integers because it's implemented on
2926 * top of GetCharABCWidthsW.
2928 BOOL WINAPI
GetCharABCWidthsFloatW( HDC hdc
, UINT first
, UINT last
, LPABCFLOAT abcf
)
2930 ABC
*abc
, *abc_base
;
2931 unsigned int i
, size
= sizeof(ABC
) * (last
- first
+ 1);
2934 TRACE("%p, %d, %d, %p - partial stub\n", hdc
, first
, last
, abcf
);
2936 abc
= abc_base
= HeapAlloc( GetProcessHeap(), 0, size
);
2937 if (!abc
) return FALSE
;
2939 ret
= GetCharABCWidthsW( hdc
, first
, last
, abc
);
2942 for (i
= first
; i
<= last
; i
++, abc
++, abcf
++)
2944 abcf
->abcfA
= abc
->abcA
;
2945 abcf
->abcfB
= abc
->abcB
;
2946 abcf
->abcfC
= abc
->abcC
;
2949 HeapFree( GetProcessHeap(), 0, abc_base
);
2953 /*************************************************************************
2954 * GetCharWidthFloatA [GDI32.@]
2956 BOOL WINAPI
GetCharWidthFloatA(HDC hdc
, UINT iFirstChar
,
2957 UINT iLastChar
, PFLOAT pxBuffer
)
2959 FIXME("%p, %u, %u, %p: stub!\n", hdc
, iFirstChar
, iLastChar
, pxBuffer
);
2963 /*************************************************************************
2964 * GetCharWidthFloatW [GDI32.@]
2966 BOOL WINAPI
GetCharWidthFloatW(HDC hdc
, UINT iFirstChar
,
2967 UINT iLastChar
, PFLOAT pxBuffer
)
2969 FIXME("%p, %u, %u, %p: stub!\n", hdc
, iFirstChar
, iLastChar
, pxBuffer
);
2974 /***********************************************************************
2976 * Font Resource API *
2978 ***********************************************************************/
2980 /***********************************************************************
2981 * AddFontResourceA (GDI32.@)
2983 INT WINAPI
AddFontResourceA( LPCSTR str
)
2985 return AddFontResourceExA( str
, 0, NULL
);
2988 /***********************************************************************
2989 * AddFontResourceW (GDI32.@)
2991 INT WINAPI
AddFontResourceW( LPCWSTR str
)
2993 return AddFontResourceExW(str
, 0, NULL
);
2997 /***********************************************************************
2998 * AddFontResourceExA (GDI32.@)
3000 INT WINAPI
AddFontResourceExA( LPCSTR str
, DWORD fl
, PVOID pdv
)
3002 DWORD len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
3003 LPWSTR strW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3006 MultiByteToWideChar(CP_ACP
, 0, str
, -1, strW
, len
);
3007 ret
= AddFontResourceExW(strW
, fl
, pdv
);
3008 HeapFree(GetProcessHeap(), 0, strW
);
3012 static BOOL CALLBACK
load_enumed_resource(HMODULE hModule
, LPCWSTR type
, LPWSTR name
, LONG_PTR lParam
)
3014 HRSRC rsrc
= FindResourceW(hModule
, name
, type
);
3015 HGLOBAL hMem
= LoadResource(hModule
, rsrc
);
3016 LPVOID
*pMem
= LockResource(hMem
);
3017 int *num_total
= (int *)lParam
;
3020 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type
));
3021 if (!AddFontMemResourceEx(pMem
, SizeofResource(hModule
, rsrc
), NULL
, &num_in_res
))
3023 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule
, hMem
);
3027 *num_total
+= num_in_res
;
3031 /***********************************************************************
3032 * AddFontResourceExW (GDI32.@)
3034 INT WINAPI
AddFontResourceExW( LPCWSTR str
, DWORD fl
, PVOID pdv
)
3036 int ret
= WineEngAddFontResourceEx(str
, fl
, pdv
);
3039 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3040 HMODULE hModule
= LoadLibraryExW(str
, NULL
, LOAD_LIBRARY_AS_DATAFILE
);
3041 if (hModule
!= NULL
)
3043 int num_resources
= 0;
3044 LPWSTR rt_font
= (LPWSTR
)((ULONG_PTR
)8); /* we don't want to include winuser.h */
3046 TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3047 wine_dbgstr_w(str
));
3048 if (EnumResourceNamesW(hModule
, rt_font
, load_enumed_resource
, (LONG_PTR
)&num_resources
))
3049 ret
= num_resources
;
3050 FreeLibrary(hModule
);
3056 /***********************************************************************
3057 * RemoveFontResourceA (GDI32.@)
3059 BOOL WINAPI
RemoveFontResourceA( LPCSTR str
)
3061 return RemoveFontResourceExA(str
, 0, 0);
3064 /***********************************************************************
3065 * RemoveFontResourceW (GDI32.@)
3067 BOOL WINAPI
RemoveFontResourceW( LPCWSTR str
)
3069 return RemoveFontResourceExW(str
, 0, 0);
3072 /***********************************************************************
3073 * AddFontMemResourceEx (GDI32.@)
3075 HANDLE WINAPI
AddFontMemResourceEx( PVOID pbFont
, DWORD cbFont
, PVOID pdv
, DWORD
*pcFonts
)
3077 return WineEngAddFontMemResourceEx(pbFont
, cbFont
, pdv
, pcFonts
);
3080 /***********************************************************************
3081 * RemoveFontMemResourceEx (GDI32.@)
3083 BOOL WINAPI
RemoveFontMemResourceEx( HANDLE fh
)
3085 FIXME("(%p) stub\n", fh
);
3089 /***********************************************************************
3090 * RemoveFontResourceExA (GDI32.@)
3092 BOOL WINAPI
RemoveFontResourceExA( LPCSTR str
, DWORD fl
, PVOID pdv
)
3094 DWORD len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
3095 LPWSTR strW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3098 MultiByteToWideChar(CP_ACP
, 0, str
, -1, strW
, len
);
3099 ret
= RemoveFontResourceExW(strW
, fl
, pdv
);
3100 HeapFree(GetProcessHeap(), 0, strW
);
3104 /***********************************************************************
3105 * RemoveFontResourceExW (GDI32.@)
3107 BOOL WINAPI
RemoveFontResourceExW( LPCWSTR str
, DWORD fl
, PVOID pdv
)
3109 return WineEngRemoveFontResourceEx(str
, fl
, pdv
);
3112 /***********************************************************************
3113 * GetTextCharset (GDI32.@)
3115 UINT WINAPI
GetTextCharset(HDC hdc
)
3117 /* MSDN docs say this is equivalent */
3118 return GetTextCharsetInfo(hdc
, NULL
, 0);
3121 /***********************************************************************
3122 * GetTextCharsetInfo (GDI32.@)
3124 UINT WINAPI
GetTextCharsetInfo(HDC hdc
, LPFONTSIGNATURE fs
, DWORD flags
)
3126 UINT ret
= DEFAULT_CHARSET
;
3127 DC
*dc
= get_dc_ptr(hdc
);
3132 ret
= WineEngGetTextCharsetInfo(dc
->gdiFont
, fs
, flags
);
3134 release_dc_ptr( dc
);
3137 if (ret
== DEFAULT_CHARSET
&& fs
)
3138 memset(fs
, 0, sizeof(FONTSIGNATURE
));
3142 /***********************************************************************
3143 * GdiGetCharDimensions (GDI32.@)
3145 * Gets the average width of the characters in the English alphabet.
3148 * hdc [I] Handle to the device context to measure on.
3149 * lptm [O] Pointer to memory to store the text metrics into.
3150 * height [O] On exit, the maximum height of characters in the English alphabet.
3153 * The average width of characters in the English alphabet.
3156 * This function is used by the dialog manager to get the size of a dialog
3157 * unit. It should also be used by other pieces of code that need to know
3158 * the size of a dialog unit in logical units without having access to the
3159 * window handle of the dialog.
3160 * Windows caches the font metrics from this function, but we don't and
3161 * there doesn't appear to be an immediate advantage to do so.
3164 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3166 LONG WINAPI
GdiGetCharDimensions(HDC hdc
, LPTEXTMETRICW lptm
, LONG
*height
)
3169 static const WCHAR alphabet
[] = {
3170 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3171 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3172 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3174 if(lptm
&& !GetTextMetricsW(hdc
, lptm
)) return 0;
3176 if(!GetTextExtentPointW(hdc
, alphabet
, 52, &sz
)) return 0;
3178 if (height
) *height
= sz
.cy
;
3179 return (sz
.cx
/ 26 + 1) / 2;
3182 BOOL WINAPI
EnableEUDC(BOOL fEnableEUDC
)
3184 FIXME("(%d): stub\n", fEnableEUDC
);
3188 /***********************************************************************
3189 * GetCharWidthI (GDI32.@)
3191 * Retrieve widths of characters.
3194 * hdc [I] Handle to a device context.
3195 * first [I] First glyph in range to query.
3196 * count [I] Number of glyph indices to query.
3197 * glyphs [I] Array of glyphs to query.
3198 * buffer [O] Buffer to receive character widths.
3201 * Only works with TrueType fonts.
3207 BOOL WINAPI
GetCharWidthI(HDC hdc
, UINT first
, UINT count
, LPWORD glyphs
, LPINT buffer
)
3212 TRACE("(%p, %d, %d, %p, %p)\n", hdc
, first
, count
, glyphs
, buffer
);
3214 if (!(abc
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(ABC
))))
3217 if (!GetCharABCWidthsI(hdc
, first
, count
, glyphs
, abc
))
3219 HeapFree(GetProcessHeap(), 0, abc
);
3223 for (i
= 0; i
< count
; i
++)
3224 buffer
[i
] = abc
->abcA
+ abc
->abcB
+ abc
->abcC
;
3226 HeapFree(GetProcessHeap(), 0, abc
);
3230 /***********************************************************************
3231 * GetFontUnicodeRanges (GDI32.@)
3233 * Retrieve a list of supported Unicode characters in a font.
3236 * hdc [I] Handle to a device context.
3237 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3240 * Success: Number of bytes written to the buffer pointed to by lpgs.
3244 DWORD WINAPI
GetFontUnicodeRanges(HDC hdc
, LPGLYPHSET lpgs
)
3247 DC
*dc
= get_dc_ptr(hdc
);
3249 TRACE("(%p, %p)\n", hdc
, lpgs
);
3253 if (dc
->gdiFont
) ret
= WineEngGetFontUnicodeRanges(dc
->gdiFont
, lpgs
);
3259 /*************************************************************
3260 * FontIsLinked (GDI32.@)
3262 BOOL WINAPI
FontIsLinked(HDC hdc
)
3264 DC
*dc
= get_dc_ptr(hdc
);
3267 if (!dc
) return FALSE
;
3268 if (dc
->gdiFont
) ret
= WineEngFontIsLinked(dc
->gdiFont
);
3270 TRACE("returning %d\n", ret
);
3274 /*************************************************************
3275 * GdiRealizationInfo (GDI32.@)
3277 * Returns a structure that contains some font information.
3279 BOOL WINAPI
GdiRealizationInfo(HDC hdc
, realization_info_t
*info
)
3281 DC
*dc
= get_dc_ptr(hdc
);
3284 if (!dc
) return FALSE
;
3285 if (dc
->gdiFont
) ret
= WineEngRealizationInfo(dc
->gdiFont
, info
);