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:
Jacek Caban 2021-08-20 10:43:13 +02:00 committed by Alexandre Julliard
parent 75786478c6
commit 0669b6cd48
2 changed files with 187 additions and 183 deletions

View File

@ -4737,188 +4737,10 @@ BOOL WINAPI NtGdiGetTextMetricsW( HDC hdc, TEXTMETRICW *metrics, ULONG flags )
/*********************************************************************** /***********************************************************************
* GetOutlineTextMetricsA (GDI32.@) * NtGdiGetOutlineTextMetricsInternalW (win32u.@)
* 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
*/ */
UINT WINAPI GetOutlineTextMetricsA( UINT WINAPI NtGdiGetOutlineTextMetricsInternalW( HDC hdc, UINT cbData,
HDC hdc, /* [in] Handle of device context */ OUTLINETEXTMETRICW *lpOTM, ULONG opts )
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 */
{ {
DC *dc = get_dc_ptr( hdc ); DC *dc = get_dc_ptr( hdc );
OUTLINETEXTMETRICW *output = lpOTM; OUTLINETEXTMETRICW *output = lpOTM;
@ -5702,7 +5524,7 @@ done:
{ {
int underlinePos, strikeoutPos; int underlinePos, strikeoutPos;
int underlineWidth, strikeoutWidth; int underlineWidth, strikeoutWidth;
UINT size = GetOutlineTextMetricsW(hdc, 0, NULL); UINT size = NtGdiGetOutlineTextMetricsInternalW( hdc, 0, NULL, 0 );
OUTLINETEXTMETRICW* otm = NULL; OUTLINETEXTMETRICW* otm = NULL;
POINT pts[5]; POINT pts[5];
HPEN hpen = NtGdiSelectPen(hdc, GetStockObject(NULL_PEN)); HPEN hpen = NtGdiSelectPen(hdc, GetStockObject(NULL_PEN));
@ -5720,7 +5542,7 @@ done:
else else
{ {
otm = HeapAlloc(GetProcessHeap(), 0, size); otm = HeapAlloc(GetProcessHeap(), 0, size);
GetOutlineTextMetricsW(hdc, size, otm); NtGdiGetOutlineTextMetricsInternalW( hdc, size, otm, 0 );
underlinePos = abs( INTERNAL_YWSTODS( dc, otm->otmsUnderscorePosition )); underlinePos = abs( INTERNAL_YWSTODS( dc, otm->otmsUnderscorePosition ));
if (otm->otmsUnderscorePosition < 0) underlinePos = -underlinePos; if (otm->otmsUnderscorePosition < 0) underlinePos = -underlinePos;
underlineWidth = get_line_width( dc, otm->otmsUnderscoreSize ); underlineWidth = get_line_width( dc, otm->otmsUnderscoreSize );

View File

@ -45,6 +45,7 @@
#include <stdarg.h> #include <stdarg.h>
#include <limits.h> #include <limits.h>
#include <assert.h>
#include "windef.h" #include "windef.h"
#include "winbase.h" #include "winbase.h"
@ -1388,3 +1389,184 @@ BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
text_metric_WtoA( &tm32, metrics ); text_metric_WtoA( &tm32, metrics );
return TRUE; 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 );
}