Author: jgardou
Date: Wed Sep 17 09:54:14 2014
New Revision: 64176
URL:
http://svn.reactos.org/svn/reactos?rev=64176&view=rev
Log:
[GDI32]
- Fix up values got from win32k in GetOutlineTextMetrics and do not fail if the provided
buffersize is only sizeof(OUTLINETEXTMETRICW).
CORE-8507 #resolve
Modified:
trunk/reactos/win32ss/gdi/gdi32/objects/font.c
Modified: trunk/reactos/win32ss/gdi/gdi32/objects/font.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/gdi/gdi32/objects/…
==============================================================================
--- trunk/reactos/win32ss/gdi/gdi32/objects/font.c [iso-8859-1] (original)
+++ trunk/reactos/win32ss/gdi/gdi32/objects/font.c [iso-8859-1] Wed Sep 17 09:54:14 2014
@@ -9,8 +9,19 @@
#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 @@
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 @@
)
{
TMDIFF Tmd; // Should not be zero.
-
- return NtGdiGetOutlineTextMetricsInternalW(hdc, cbData, lpOTM, &Tmd);
+ UINT Size, AvailableSize = 0, StringSize;
+ XFORM DevToWorld;
+ OUTLINETEXTMETRICW* LocalOTM;
+ WCHAR* Str;
+ BYTE* Ptr;
+
+ /* 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;
}
/*