From 1b601af92fcd6fa3417e10120a3c39e4161a8287 Mon Sep 17 00:00:00 2001 From: James Tabor Date: Sun, 28 May 2006 22:49:52 +0000 Subject: [PATCH] Implement NtGdiGetOutlineTextMetrics and GetOutlineTextMetricsA/W. GetOutlineTextMetricsA is from Wine. Tested with Mozilla 1.7.12. svn path=/trunk/; revision=22096 --- reactos/dll/win32/gdi32/objects/font.c | 181 ++++++++++++++++++ .../subsystems/win32/win32k/objects/text.c | 57 +++++- 2 files changed, 236 insertions(+), 2 deletions(-) diff --git a/reactos/dll/win32/gdi32/objects/font.c b/reactos/dll/win32/gdi32/objects/font.c index cefdc9fe7d0..48aadddc405 100644 --- a/reactos/dll/win32/gdi32/objects/font.c +++ b/reactos/dll/win32/gdi32/objects/font.c @@ -15,6 +15,33 @@ #define INITIAL_FAMILY_COUNT 64 +/*********************************************************************** + * TEXTMETRIC conversion functions. + */ +static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA ) +{ + ptmA->tmHeight = ptmW->tmHeight; + ptmA->tmAscent = ptmW->tmAscent; + ptmA->tmDescent = ptmW->tmDescent; + ptmA->tmInternalLeading = ptmW->tmInternalLeading; + ptmA->tmExternalLeading = ptmW->tmExternalLeading; + ptmA->tmAveCharWidth = ptmW->tmAveCharWidth; + ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth; + ptmA->tmWeight = ptmW->tmWeight; + ptmA->tmOverhang = ptmW->tmOverhang; + ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX; + ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY; + ptmA->tmFirstChar = ptmW->tmFirstChar > 255 ? 255 : ptmW->tmFirstChar; + ptmA->tmLastChar = ptmW->tmLastChar > 255 ? 255 : ptmW->tmLastChar; + ptmA->tmDefaultChar = ptmW->tmDefaultChar > 255 ? 255 : ptmW->tmDefaultChar; + ptmA->tmBreakChar = ptmW->tmBreakChar > 255 ? 255 : ptmW->tmBreakChar; + ptmA->tmItalic = ptmW->tmItalic; + ptmA->tmUnderlined = ptmW->tmUnderlined; + ptmA->tmStruckOut = ptmW->tmStruckOut; + ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily; + ptmA->tmCharSet = ptmW->tmCharSet; +} + static BOOL FASTCALL MetricsCharConvert(WCHAR w, UCHAR *b) { @@ -539,6 +566,160 @@ GetGlyphOutlineW( } +/* + * @implemented + */ +UINT +APIENTRY +GetOutlineTextMetricsA( + HDC hdc, + UINT cbData, + LPOUTLINETEXTMETRICA lpOTM + ) +{ + 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 + (int)lpOTMW->otmpFamilyName), -1, + NULL, 0, NULL, NULL); + if(lpOTMW->otmpFaceName) + needed += WideCharToMultiByte(CP_ACP, 0, + (WCHAR*)((char*)lpOTMW + (int)lpOTMW->otmpFaceName), -1, + NULL, 0, NULL, NULL); + if(lpOTMW->otmpStyleName) + needed += WideCharToMultiByte(CP_ACP, 0, + (WCHAR*)((char*)lpOTMW + (int)lpOTMW->otmpStyleName), -1, + NULL, 0, NULL, NULL); + if(lpOTMW->otmpFullName) + needed += WideCharToMultiByte(CP_ACP, 0, + (WCHAR*)((char*)lpOTMW + (int)lpOTMW->otmpFullName), -1, + NULL, 0, NULL, NULL); + + if(!lpOTM) { + ret = needed; + goto end; + } + + DPRINT("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 + (int)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 + (int)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 + (int)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 + (int)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); + } + +end: + if(lpOTMW != (OUTLINETEXTMETRICW *)buf) + HeapFree(GetProcessHeap(), 0, lpOTMW); + + return ret; +} + + +/* + * @implemented + */ +UINT +APIENTRY +GetOutlineTextMetricsW( + HDC hdc, + UINT cbData, + LPOUTLINETEXTMETRICW lpOTM + ) +{ + return NtGdiGetOutlineTextMetrics(hdc, cbData, lpOTM); +} + /* * @implemented diff --git a/reactos/subsystems/win32/win32k/objects/text.c b/reactos/subsystems/win32/win32k/objects/text.c index 8a82739eca9..01efeecccf0 100644 --- a/reactos/subsystems/win32/win32k/objects/text.c +++ b/reactos/subsystems/win32/win32k/objects/text.c @@ -2143,16 +2143,69 @@ NtGdiGetKerningPairs(HDC hDC, return 0; } +/* + From "Undocumented Windows 2000 Secrets" Appendix B, Table B-2, page + 472, this is NtGdiGetOutlineTextMetricsInternalW. + */ UINT STDCALL NtGdiGetOutlineTextMetrics(HDC hDC, UINT Data, LPOUTLINETEXTMETRICW otm) { - UNIMPLEMENTED; - return 0; + PDC dc; + PTEXTOBJ TextObj; + PFONTGDI FontGDI; + HFONT hFont = 0; + ULONG Size; + OUTLINETEXTMETRICW *potm; + NTSTATUS Status; + + dc = DC_LockDc(hDC); + if (dc == NULL) + { + SetLastWin32Error(ERROR_INVALID_HANDLE); + return 0; + } + hFont = dc->w.hFont; + TextObj = TEXTOBJ_LockText(hFont); + DC_UnlockDc(dc); + if (TextObj == NULL) + { + SetLastWin32Error(ERROR_INVALID_HANDLE); + return 0; + } + FontGDI = ObjToGDI(TextObj->Font, FONT); + TEXTOBJ_UnlockText(TextObj); + Size = IntGetOutlineTextMetrics(FontGDI, 0, NULL); + if (!otm) return Size; + if (Size > Data) + { + SetLastWin32Error(ERROR_INSUFFICIENT_BUFFER); + return 0; + } + potm = ExAllocatePoolWithTag(PagedPool, Size, TAG_GDITEXT); + if (NULL == potm) + { + SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); + return 0; + } + IntGetOutlineTextMetrics(FontGDI, Size, potm); + if (otm) + { + Status = MmCopyToCaller(otm, potm, Size); + if (! NT_SUCCESS(Status)) + { + SetLastWin32Error(ERROR_INVALID_PARAMETER); + ExFreePool(potm); + return 0; + } + } + ExFreePool(potm); + return Size; } + BOOL APIENTRY NtGdiGetRasterizerCaps(