mirror of
https://github.com/reactos/reactos.git
synced 2025-07-31 11:31:40 +00:00
[GDI32]
- Fix up values got from win32k in GetOutlineTextMetrics and do not fail if the provided buffersize is only sizeof(OUTLINETEXTMETRICW). CORE-8507 #resolve svn path=/trunk/; revision=64176
This commit is contained in:
parent
725cca1c7f
commit
726e4806e9
1 changed files with 173 additions and 1 deletions
|
@ -9,9 +9,20 @@
|
|||
|
||||
#include <precomp.h>
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
/* Rounds a floating point number to integer. The world-to-viewport
|
||||
* transformation process is done in floating point internally. This function
|
||||
* is then used to round these coordinates to integer values.
|
||||
*/
|
||||
static __inline INT GDI_ROUND(FLOAT val)
|
||||
{
|
||||
return (int)floor(val + 0.5);
|
||||
}
|
||||
|
||||
/*
|
||||
* For TranslateCharsetInfo
|
||||
*/
|
||||
|
@ -1204,6 +1215,29 @@ end:
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* Performs a device to world transformation on the specified size (which
|
||||
* is in integer format).
|
||||
*/
|
||||
static inline INT INTERNAL_YDSTOWS(XFORM *xForm, INT height)
|
||||
{
|
||||
double floatHeight;
|
||||
|
||||
/* Perform operation with floating point */
|
||||
floatHeight = (double)height * xForm->eM22;
|
||||
/* Round to integers */
|
||||
return GDI_ROUND(floatHeight);
|
||||
}
|
||||
|
||||
/* scale width and height but don't mirror them */
|
||||
static inline INT width_to_LP( XFORM *xForm, INT width )
|
||||
{
|
||||
return GDI_ROUND( (double)width * fabs( xForm->eM11));
|
||||
}
|
||||
|
||||
static inline INT height_to_LP( XFORM *xForm, INT height )
|
||||
{
|
||||
return GDI_ROUND( (double)height * fabs( xForm->eM22 ));
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
|
@ -1217,8 +1251,146 @@ GetOutlineTextMetricsW(
|
|||
)
|
||||
{
|
||||
TMDIFF Tmd; // Should not be zero.
|
||||
UINT Size, AvailableSize = 0, StringSize;
|
||||
XFORM DevToWorld;
|
||||
OUTLINETEXTMETRICW* LocalOTM;
|
||||
WCHAR* Str;
|
||||
BYTE* Ptr;
|
||||
|
||||
return NtGdiGetOutlineTextMetricsInternalW(hdc, cbData, lpOTM, &Tmd);
|
||||
/* Get the structure */
|
||||
Size = NtGdiGetOutlineTextMetricsInternalW(hdc, 0, NULL, &Tmd);
|
||||
if (!Size)
|
||||
return 0;
|
||||
if (!lpOTM || (cbData < sizeof(*lpOTM)))
|
||||
return Size;
|
||||
|
||||
LocalOTM = HeapAlloc(GetProcessHeap(), 0, Size);
|
||||
LocalOTM->otmSize = Size;
|
||||
Size = NtGdiGetOutlineTextMetricsInternalW(hdc, Size, LocalOTM, &Tmd);
|
||||
if (!Size)
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, LocalOTM);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!NtGdiGetTransform(hdc, GdiDeviceSpaceToWorldSpace, &DevToWorld))
|
||||
{
|
||||
DPRINT1("NtGdiGetTransform failed!\n");
|
||||
HeapFree(GetProcessHeap(), 0, LocalOTM);
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Fill in DC specific data */
|
||||
LocalOTM->otmTextMetrics.tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
|
||||
LocalOTM->otmTextMetrics.tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
|
||||
LocalOTM->otmTextMetrics.tmHeight = height_to_LP( &DevToWorld, LocalOTM->otmTextMetrics.tmHeight );
|
||||
LocalOTM->otmTextMetrics.tmAscent = height_to_LP( &DevToWorld, LocalOTM->otmTextMetrics.tmAscent );
|
||||
LocalOTM->otmTextMetrics.tmDescent = height_to_LP( &DevToWorld, LocalOTM->otmTextMetrics.tmDescent );
|
||||
LocalOTM->otmTextMetrics.tmInternalLeading = height_to_LP( &DevToWorld, LocalOTM->otmTextMetrics.tmInternalLeading );
|
||||
LocalOTM->otmTextMetrics.tmExternalLeading = height_to_LP( &DevToWorld, LocalOTM->otmTextMetrics.tmExternalLeading );
|
||||
LocalOTM->otmTextMetrics.tmAveCharWidth = width_to_LP( &DevToWorld, LocalOTM->otmTextMetrics.tmAveCharWidth );
|
||||
LocalOTM->otmTextMetrics.tmMaxCharWidth = width_to_LP( &DevToWorld, LocalOTM->otmTextMetrics.tmMaxCharWidth );
|
||||
LocalOTM->otmTextMetrics.tmOverhang = width_to_LP( &DevToWorld, LocalOTM->otmTextMetrics.tmOverhang );
|
||||
LocalOTM->otmAscent = height_to_LP( &DevToWorld, LocalOTM->otmAscent);
|
||||
LocalOTM->otmDescent = height_to_LP( &DevToWorld, LocalOTM->otmDescent);
|
||||
LocalOTM->otmLineGap = abs(INTERNAL_YDSTOWS(&DevToWorld,LocalOTM->otmLineGap));
|
||||
LocalOTM->otmsCapEmHeight = abs(INTERNAL_YDSTOWS(&DevToWorld,LocalOTM->otmsCapEmHeight));
|
||||
LocalOTM->otmsXHeight = abs(INTERNAL_YDSTOWS(&DevToWorld,LocalOTM->otmsXHeight));
|
||||
LocalOTM->otmrcFontBox.top = height_to_LP( &DevToWorld, LocalOTM->otmrcFontBox.top);
|
||||
LocalOTM->otmrcFontBox.bottom = height_to_LP( &DevToWorld, LocalOTM->otmrcFontBox.bottom);
|
||||
LocalOTM->otmrcFontBox.left = width_to_LP( &DevToWorld, LocalOTM->otmrcFontBox.left);
|
||||
LocalOTM->otmrcFontBox.right = width_to_LP( &DevToWorld, LocalOTM->otmrcFontBox.right);
|
||||
LocalOTM->otmMacAscent = height_to_LP( &DevToWorld, LocalOTM->otmMacAscent);
|
||||
LocalOTM->otmMacDescent = height_to_LP( &DevToWorld, LocalOTM->otmMacDescent);
|
||||
LocalOTM->otmMacLineGap = abs(INTERNAL_YDSTOWS(&DevToWorld,LocalOTM->otmMacLineGap));
|
||||
LocalOTM->otmptSubscriptSize.x = width_to_LP( &DevToWorld, LocalOTM->otmptSubscriptSize.x);
|
||||
LocalOTM->otmptSubscriptSize.y = height_to_LP( &DevToWorld, LocalOTM->otmptSubscriptSize.y);
|
||||
LocalOTM->otmptSubscriptOffset.x = width_to_LP( &DevToWorld, LocalOTM->otmptSubscriptOffset.x);
|
||||
LocalOTM->otmptSubscriptOffset.y = height_to_LP( &DevToWorld, LocalOTM->otmptSubscriptOffset.y);
|
||||
LocalOTM->otmptSuperscriptSize.x = width_to_LP( &DevToWorld, LocalOTM->otmptSuperscriptSize.x);
|
||||
LocalOTM->otmptSuperscriptSize.y = height_to_LP( &DevToWorld, LocalOTM->otmptSuperscriptSize.y);
|
||||
LocalOTM->otmptSuperscriptOffset.x = width_to_LP( &DevToWorld, LocalOTM->otmptSuperscriptOffset.x);
|
||||
LocalOTM->otmptSuperscriptOffset.y = height_to_LP( &DevToWorld, LocalOTM->otmptSuperscriptOffset.y);
|
||||
LocalOTM->otmsStrikeoutSize = abs(INTERNAL_YDSTOWS(&DevToWorld,LocalOTM->otmsStrikeoutSize));
|
||||
LocalOTM->otmsStrikeoutPosition = height_to_LP( &DevToWorld, LocalOTM->otmsStrikeoutPosition);
|
||||
LocalOTM->otmsUnderscoreSize = height_to_LP( &DevToWorld, LocalOTM->otmsUnderscoreSize);
|
||||
LocalOTM->otmsUnderscorePosition = height_to_LP( &DevToWorld, LocalOTM->otmsUnderscorePosition);
|
||||
|
||||
/* Copy what we can */
|
||||
CopyMemory(lpOTM, LocalOTM, min(Size, cbData));
|
||||
|
||||
lpOTM->otmpFamilyName = NULL;
|
||||
lpOTM->otmpFaceName = NULL;
|
||||
lpOTM->otmpStyleName = NULL;
|
||||
lpOTM->otmpFullName = NULL;
|
||||
|
||||
Size = sizeof(*lpOTM);
|
||||
AvailableSize = cbData - Size;
|
||||
Ptr = (BYTE*)lpOTM + sizeof(*lpOTM);
|
||||
|
||||
/* Fix string values up */
|
||||
if (LocalOTM->otmpFamilyName)
|
||||
{
|
||||
Str = (WCHAR*)((char*)LocalOTM + (ptrdiff_t)LocalOTM->otmpFamilyName);
|
||||
StringSize = (wcslen(Str) + 1) * sizeof(WCHAR);
|
||||
if (AvailableSize >= StringSize)
|
||||
{
|
||||
CopyMemory(Ptr, Str, StringSize);
|
||||
lpOTM->otmpFamilyName = (PSTR)(Ptr - (BYTE*)lpOTM);
|
||||
Ptr += StringSize;
|
||||
AvailableSize -= StringSize;
|
||||
Size += StringSize;
|
||||
}
|
||||
}
|
||||
|
||||
if (LocalOTM->otmpFaceName)
|
||||
{
|
||||
Str = (WCHAR*)((char*)LocalOTM + (ptrdiff_t)LocalOTM->otmpFaceName);
|
||||
StringSize = (wcslen(Str) + 1) * sizeof(WCHAR);
|
||||
if (AvailableSize >= StringSize)
|
||||
{
|
||||
CopyMemory(Ptr, Str, StringSize);
|
||||
lpOTM->otmpFaceName = (PSTR)(Ptr - (BYTE*)lpOTM);
|
||||
Ptr += StringSize;
|
||||
AvailableSize -= StringSize;
|
||||
Size += StringSize;
|
||||
}
|
||||
}
|
||||
|
||||
if (LocalOTM->otmpStyleName)
|
||||
{
|
||||
Str = (WCHAR*)((char*)LocalOTM + (ptrdiff_t)LocalOTM->otmpStyleName);
|
||||
StringSize = (wcslen(Str) + 1) * sizeof(WCHAR);
|
||||
if (AvailableSize >= StringSize)
|
||||
{
|
||||
CopyMemory(Ptr, Str, StringSize);
|
||||
lpOTM->otmpStyleName = (PSTR)(Ptr - (BYTE*)lpOTM);
|
||||
Ptr += StringSize;
|
||||
AvailableSize -= StringSize;
|
||||
Size += StringSize;
|
||||
}
|
||||
}
|
||||
|
||||
if (LocalOTM->otmpFullName)
|
||||
{
|
||||
Str = (WCHAR*)((char*)LocalOTM + (ptrdiff_t)LocalOTM->otmpFullName);
|
||||
StringSize = (wcslen(Str) + 1) * sizeof(WCHAR);
|
||||
if (AvailableSize >= StringSize)
|
||||
{
|
||||
CopyMemory(Ptr, Str, StringSize);
|
||||
lpOTM->otmpFullName = (PSTR)(Ptr - (BYTE*)lpOTM);
|
||||
Ptr += StringSize;
|
||||
AvailableSize -= StringSize;
|
||||
Size += StringSize;
|
||||
}
|
||||
}
|
||||
|
||||
lpOTM->otmSize = Size;
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, LocalOTM);
|
||||
|
||||
return Size;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue