mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 06:43:01 +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 <precomp.h>
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#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
|
* For TranslateCharsetInfo
|
||||||
*/
|
*/
|
||||||
|
@ -1204,6 +1215,29 @@ end:
|
||||||
return ret;
|
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
|
* @implemented
|
||||||
|
@ -1217,8 +1251,146 @@ GetOutlineTextMetricsW(
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
TMDIFF Tmd; // Should not be zero.
|
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