gdi32: Use NtGdiGetOutlineTextMetricsInternalW for GetOutlineTextMetrics.
Signed-off-by: Jacek Caban <jacek@codeweavers.com> Signed-off-by: Huw Davies <huw@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
75786478c6
commit
0669b6cd48
|
@ -4737,188 +4737,10 @@ BOOL WINAPI NtGdiGetTextMetricsW( HDC hdc, TEXTMETRICW *metrics, ULONG flags )
|
|||
|
||||
|
||||
/***********************************************************************
|
||||
* GetOutlineTextMetricsA (GDI32.@)
|
||||
* Gets metrics for TrueType fonts.
|
||||
*
|
||||
* NOTES
|
||||
* If the supplied buffer isn't big enough Windows partially fills it up to
|
||||
* its given length and returns that length.
|
||||
*
|
||||
* RETURNS
|
||||
* Success: Non-zero or size of required buffer
|
||||
* Failure: 0
|
||||
* NtGdiGetOutlineTextMetricsInternalW (win32u.@)
|
||||
*/
|
||||
UINT WINAPI GetOutlineTextMetricsA(
|
||||
HDC hdc, /* [in] Handle of device context */
|
||||
UINT cbData, /* [in] Size of metric data array */
|
||||
LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
|
||||
{
|
||||
char buf[512], *ptr;
|
||||
UINT ret, needed;
|
||||
OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
|
||||
OUTLINETEXTMETRICA *output = lpOTM;
|
||||
INT left, len;
|
||||
|
||||
if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
|
||||
return 0;
|
||||
if(ret > sizeof(buf))
|
||||
lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
|
||||
GetOutlineTextMetricsW(hdc, ret, lpOTMW);
|
||||
|
||||
needed = sizeof(OUTLINETEXTMETRICA);
|
||||
if(lpOTMW->otmpFamilyName)
|
||||
needed += WideCharToMultiByte(CP_ACP, 0,
|
||||
(WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
|
||||
NULL, 0, NULL, NULL);
|
||||
if(lpOTMW->otmpFaceName)
|
||||
needed += WideCharToMultiByte(CP_ACP, 0,
|
||||
(WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
|
||||
NULL, 0, NULL, NULL);
|
||||
if(lpOTMW->otmpStyleName)
|
||||
needed += WideCharToMultiByte(CP_ACP, 0,
|
||||
(WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
|
||||
NULL, 0, NULL, NULL);
|
||||
if(lpOTMW->otmpFullName)
|
||||
needed += WideCharToMultiByte(CP_ACP, 0,
|
||||
(WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
|
||||
NULL, 0, NULL, NULL);
|
||||
|
||||
if(!lpOTM) {
|
||||
ret = needed;
|
||||
goto end;
|
||||
}
|
||||
|
||||
TRACE("needed = %d\n", needed);
|
||||
if(needed > cbData)
|
||||
/* Since the supplied buffer isn't big enough, we'll alloc one
|
||||
that is and memcpy the first cbData bytes into the lpOTM at
|
||||
the end. */
|
||||
output = HeapAlloc(GetProcessHeap(), 0, needed);
|
||||
|
||||
ret = output->otmSize = min(needed, cbData);
|
||||
FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
|
||||
output->otmFiller = 0;
|
||||
output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
|
||||
output->otmfsSelection = lpOTMW->otmfsSelection;
|
||||
output->otmfsType = lpOTMW->otmfsType;
|
||||
output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
|
||||
output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
|
||||
output->otmItalicAngle = lpOTMW->otmItalicAngle;
|
||||
output->otmEMSquare = lpOTMW->otmEMSquare;
|
||||
output->otmAscent = lpOTMW->otmAscent;
|
||||
output->otmDescent = lpOTMW->otmDescent;
|
||||
output->otmLineGap = lpOTMW->otmLineGap;
|
||||
output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
|
||||
output->otmsXHeight = lpOTMW->otmsXHeight;
|
||||
output->otmrcFontBox = lpOTMW->otmrcFontBox;
|
||||
output->otmMacAscent = lpOTMW->otmMacAscent;
|
||||
output->otmMacDescent = lpOTMW->otmMacDescent;
|
||||
output->otmMacLineGap = lpOTMW->otmMacLineGap;
|
||||
output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
|
||||
output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
|
||||
output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
|
||||
output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
|
||||
output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
|
||||
output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
|
||||
output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
|
||||
output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
|
||||
output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
|
||||
|
||||
|
||||
ptr = (char*)(output + 1);
|
||||
left = needed - sizeof(*output);
|
||||
|
||||
if(lpOTMW->otmpFamilyName) {
|
||||
output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
|
||||
len = WideCharToMultiByte(CP_ACP, 0,
|
||||
(WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
|
||||
ptr, left, NULL, NULL);
|
||||
left -= len;
|
||||
ptr += len;
|
||||
} else
|
||||
output->otmpFamilyName = 0;
|
||||
|
||||
if(lpOTMW->otmpFaceName) {
|
||||
output->otmpFaceName = (LPSTR)(ptr - (char*)output);
|
||||
len = WideCharToMultiByte(CP_ACP, 0,
|
||||
(WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
|
||||
ptr, left, NULL, NULL);
|
||||
left -= len;
|
||||
ptr += len;
|
||||
} else
|
||||
output->otmpFaceName = 0;
|
||||
|
||||
if(lpOTMW->otmpStyleName) {
|
||||
output->otmpStyleName = (LPSTR)(ptr - (char*)output);
|
||||
len = WideCharToMultiByte(CP_ACP, 0,
|
||||
(WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
|
||||
ptr, left, NULL, NULL);
|
||||
left -= len;
|
||||
ptr += len;
|
||||
} else
|
||||
output->otmpStyleName = 0;
|
||||
|
||||
if(lpOTMW->otmpFullName) {
|
||||
output->otmpFullName = (LPSTR)(ptr - (char*)output);
|
||||
len = WideCharToMultiByte(CP_ACP, 0,
|
||||
(WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
|
||||
ptr, left, NULL, NULL);
|
||||
left -= len;
|
||||
} else
|
||||
output->otmpFullName = 0;
|
||||
|
||||
assert(left == 0);
|
||||
|
||||
if(output != lpOTM) {
|
||||
memcpy(lpOTM, output, cbData);
|
||||
HeapFree(GetProcessHeap(), 0, output);
|
||||
|
||||
/* check if the string offsets really fit into the provided size */
|
||||
/* FIXME: should we check string length as well? */
|
||||
/* make sure that we don't read/write beyond the provided buffer */
|
||||
if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(LPSTR))
|
||||
{
|
||||
if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
|
||||
lpOTM->otmpFamilyName = 0; /* doesn't fit */
|
||||
}
|
||||
|
||||
/* make sure that we don't read/write beyond the provided buffer */
|
||||
if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(LPSTR))
|
||||
{
|
||||
if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
|
||||
lpOTM->otmpFaceName = 0; /* doesn't fit */
|
||||
}
|
||||
|
||||
/* make sure that we don't read/write beyond the provided buffer */
|
||||
if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(LPSTR))
|
||||
{
|
||||
if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
|
||||
lpOTM->otmpStyleName = 0; /* doesn't fit */
|
||||
}
|
||||
|
||||
/* make sure that we don't read/write beyond the provided buffer */
|
||||
if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(LPSTR))
|
||||
{
|
||||
if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
|
||||
lpOTM->otmpFullName = 0; /* doesn't fit */
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
|
||||
HeapFree(GetProcessHeap(), 0, lpOTMW);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* GetOutlineTextMetricsW [GDI32.@]
|
||||
*/
|
||||
UINT WINAPI GetOutlineTextMetricsW(
|
||||
HDC hdc, /* [in] Handle of device context */
|
||||
UINT cbData, /* [in] Size of metric data array */
|
||||
LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
|
||||
UINT WINAPI NtGdiGetOutlineTextMetricsInternalW( HDC hdc, UINT cbData,
|
||||
OUTLINETEXTMETRICW *lpOTM, ULONG opts )
|
||||
{
|
||||
DC *dc = get_dc_ptr( hdc );
|
||||
OUTLINETEXTMETRICW *output = lpOTM;
|
||||
|
@ -5702,7 +5524,7 @@ done:
|
|||
{
|
||||
int underlinePos, strikeoutPos;
|
||||
int underlineWidth, strikeoutWidth;
|
||||
UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
|
||||
UINT size = NtGdiGetOutlineTextMetricsInternalW( hdc, 0, NULL, 0 );
|
||||
OUTLINETEXTMETRICW* otm = NULL;
|
||||
POINT pts[5];
|
||||
HPEN hpen = NtGdiSelectPen(hdc, GetStockObject(NULL_PEN));
|
||||
|
@ -5720,7 +5542,7 @@ done:
|
|||
else
|
||||
{
|
||||
otm = HeapAlloc(GetProcessHeap(), 0, size);
|
||||
GetOutlineTextMetricsW(hdc, size, otm);
|
||||
NtGdiGetOutlineTextMetricsInternalW( hdc, size, otm, 0 );
|
||||
underlinePos = abs( INTERNAL_YWSTODS( dc, otm->otmsUnderscorePosition ));
|
||||
if (otm->otmsUnderscorePosition < 0) underlinePos = -underlinePos;
|
||||
underlineWidth = get_line_width( dc, otm->otmsUnderscoreSize );
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
|
||||
#include <stdarg.h>
|
||||
#include <limits.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
|
@ -1388,3 +1389,184 @@ BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
|
|||
text_metric_WtoA( &tm32, metrics );
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* GetOutlineTextMetricsA (GDI32.@)
|
||||
*
|
||||
* Gets metrics for TrueType fonts.
|
||||
*
|
||||
* NOTES
|
||||
* If the supplied buffer isn't big enough Windows partially fills it up to
|
||||
* its given length and returns that length.
|
||||
*/
|
||||
UINT WINAPI GetOutlineTextMetricsA( HDC hdc, UINT size, OUTLINETEXTMETRICA *otm )
|
||||
{
|
||||
char buf[512], *ptr;
|
||||
UINT ret, needed;
|
||||
OUTLINETEXTMETRICW *otmW = (OUTLINETEXTMETRICW *)buf;
|
||||
OUTLINETEXTMETRICA *output = otm;
|
||||
INT left, len;
|
||||
|
||||
if ((ret = GetOutlineTextMetricsW( hdc, 0, NULL )) == 0) return 0;
|
||||
if (ret > sizeof(buf) && !(otmW = HeapAlloc( GetProcessHeap(), 0, ret )))
|
||||
return 0;
|
||||
|
||||
GetOutlineTextMetricsW( hdc, ret, otmW );
|
||||
|
||||
needed = sizeof(OUTLINETEXTMETRICA);
|
||||
if (otmW->otmpFamilyName)
|
||||
needed += WideCharToMultiByte( CP_ACP, 0,
|
||||
(WCHAR *)((char *)otmW + (ptrdiff_t)otmW->otmpFamilyName),
|
||||
-1, NULL, 0, NULL, NULL );
|
||||
if (otmW->otmpFaceName)
|
||||
needed += WideCharToMultiByte( CP_ACP, 0,
|
||||
(WCHAR *)((char *)otmW + (ptrdiff_t)otmW->otmpFaceName),
|
||||
-1, NULL, 0, NULL, NULL );
|
||||
if (otmW->otmpStyleName)
|
||||
needed += WideCharToMultiByte( CP_ACP, 0,
|
||||
(WCHAR *)((char *)otmW + (ptrdiff_t)otmW->otmpStyleName),
|
||||
-1, NULL, 0, NULL, NULL );
|
||||
if (otmW->otmpFullName)
|
||||
needed += WideCharToMultiByte( CP_ACP, 0,
|
||||
(WCHAR *)((char *)otmW + (ptrdiff_t)otmW->otmpFullName),
|
||||
-1, NULL, 0, NULL, NULL );
|
||||
|
||||
if (!otm)
|
||||
{
|
||||
ret = needed;
|
||||
goto end;
|
||||
}
|
||||
|
||||
TRACE( "needed = %d\n", needed );
|
||||
if (needed > size)
|
||||
/* Since the supplied buffer isn't big enough, we'll alloc one
|
||||
that is and memcpy the first size bytes into the otm at
|
||||
the end. */
|
||||
output = HeapAlloc( GetProcessHeap(), 0, needed );
|
||||
|
||||
ret = output->otmSize = min( needed, size );
|
||||
text_metric_WtoA( &otmW->otmTextMetrics, &output->otmTextMetrics );
|
||||
output->otmFiller = 0;
|
||||
output->otmPanoseNumber = otmW->otmPanoseNumber;
|
||||
output->otmfsSelection = otmW->otmfsSelection;
|
||||
output->otmfsType = otmW->otmfsType;
|
||||
output->otmsCharSlopeRise = otmW->otmsCharSlopeRise;
|
||||
output->otmsCharSlopeRun = otmW->otmsCharSlopeRun;
|
||||
output->otmItalicAngle = otmW->otmItalicAngle;
|
||||
output->otmEMSquare = otmW->otmEMSquare;
|
||||
output->otmAscent = otmW->otmAscent;
|
||||
output->otmDescent = otmW->otmDescent;
|
||||
output->otmLineGap = otmW->otmLineGap;
|
||||
output->otmsCapEmHeight = otmW->otmsCapEmHeight;
|
||||
output->otmsXHeight = otmW->otmsXHeight;
|
||||
output->otmrcFontBox = otmW->otmrcFontBox;
|
||||
output->otmMacAscent = otmW->otmMacAscent;
|
||||
output->otmMacDescent = otmW->otmMacDescent;
|
||||
output->otmMacLineGap = otmW->otmMacLineGap;
|
||||
output->otmusMinimumPPEM = otmW->otmusMinimumPPEM;
|
||||
output->otmptSubscriptSize = otmW->otmptSubscriptSize;
|
||||
output->otmptSubscriptOffset = otmW->otmptSubscriptOffset;
|
||||
output->otmptSuperscriptSize = otmW->otmptSuperscriptSize;
|
||||
output->otmptSuperscriptOffset = otmW->otmptSuperscriptOffset;
|
||||
output->otmsStrikeoutSize = otmW->otmsStrikeoutSize;
|
||||
output->otmsStrikeoutPosition = otmW->otmsStrikeoutPosition;
|
||||
output->otmsUnderscoreSize = otmW->otmsUnderscoreSize;
|
||||
output->otmsUnderscorePosition = otmW->otmsUnderscorePosition;
|
||||
|
||||
ptr = (char *)(output + 1);
|
||||
left = needed - sizeof(*output);
|
||||
|
||||
if (otmW->otmpFamilyName)
|
||||
{
|
||||
output->otmpFamilyName = (char *)(ptr - (char *)output);
|
||||
len = WideCharToMultiByte( CP_ACP, 0,
|
||||
(WCHAR *)((char *)otmW + (ptrdiff_t)otmW->otmpFamilyName),
|
||||
-1, ptr, left, NULL, NULL );
|
||||
left -= len;
|
||||
ptr += len;
|
||||
}
|
||||
else output->otmpFamilyName = 0;
|
||||
|
||||
if (otmW->otmpFaceName)
|
||||
{
|
||||
output->otmpFaceName = (char *)(ptr - (char *)output);
|
||||
len = WideCharToMultiByte( CP_ACP, 0,
|
||||
(WCHAR *)((char *)otmW + (ptrdiff_t)otmW->otmpFaceName),
|
||||
-1, ptr, left, NULL, NULL );
|
||||
left -= len;
|
||||
ptr += len;
|
||||
}
|
||||
else output->otmpFaceName = 0;
|
||||
|
||||
if (otmW->otmpStyleName)
|
||||
{
|
||||
output->otmpStyleName = (char *)(ptr - (char *)output);
|
||||
len = WideCharToMultiByte( CP_ACP, 0,
|
||||
(WCHAR *)((char *)otmW + (ptrdiff_t)otmW->otmpStyleName),
|
||||
-1, ptr, left, NULL, NULL);
|
||||
left -= len;
|
||||
ptr += len;
|
||||
}
|
||||
else output->otmpStyleName = 0;
|
||||
|
||||
if (otmW->otmpFullName)
|
||||
{
|
||||
output->otmpFullName = (char *)(ptr - (char *)output);
|
||||
len = WideCharToMultiByte( CP_ACP, 0,
|
||||
(WCHAR *)((char *)otmW + (ptrdiff_t)otmW->otmpFullName),
|
||||
-1, ptr, left, NULL, NULL );
|
||||
left -= len;
|
||||
}
|
||||
else output->otmpFullName = 0;
|
||||
|
||||
assert( left == 0 );
|
||||
|
||||
if (output != otm)
|
||||
{
|
||||
memcpy( otm, output, size );
|
||||
HeapFree( GetProcessHeap(), 0, output );
|
||||
|
||||
/* check if the string offsets really fit into the provided size */
|
||||
/* FIXME: should we check string length as well? */
|
||||
/* make sure that we don't read/write beyond the provided buffer */
|
||||
if (otm->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(char *))
|
||||
{
|
||||
if ((UINT_PTR)otm->otmpFamilyName >= otm->otmSize)
|
||||
otm->otmpFamilyName = 0; /* doesn't fit */
|
||||
}
|
||||
|
||||
/* make sure that we don't read/write beyond the provided buffer */
|
||||
if (otm->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(char *))
|
||||
{
|
||||
if ((UINT_PTR)otm->otmpFaceName >= otm->otmSize)
|
||||
otm->otmpFaceName = 0; /* doesn't fit */
|
||||
}
|
||||
|
||||
/* make sure that we don't read/write beyond the provided buffer */
|
||||
if (otm->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(char *))
|
||||
{
|
||||
if ((UINT_PTR)otm->otmpStyleName >= otm->otmSize)
|
||||
otm->otmpStyleName = 0; /* doesn't fit */
|
||||
}
|
||||
|
||||
/* make sure that we don't read/write beyond the provided buffer */
|
||||
if (otm->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(char *))
|
||||
{
|
||||
if ((UINT_PTR)otm->otmpFullName >= otm->otmSize)
|
||||
otm->otmpFullName = 0; /* doesn't fit */
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
if (otmW != (OUTLINETEXTMETRICW *)buf)
|
||||
HeapFree(GetProcessHeap(), 0, otmW);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* GetOutlineTextMetricsW [GDI32.@]
|
||||
*/
|
||||
UINT WINAPI GetOutlineTextMetricsW( HDC hdc, UINT size, OUTLINETEXTMETRICW *otm )
|
||||
{
|
||||
return NtGdiGetOutlineTextMetricsInternalW( hdc, size, otm, 0 );
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue