Author: jimtabor Date: Mon Jul 31 08:54:21 2006 New Revision: 23385
URL: http://svn.reactos.org/svn/reactos?rev=23385&view=rev Log: Sync Gdi32.
Modified: branches/ros-branch-0_3_0/reactos/dll/win32/gdi32/misc/stubs.c branches/ros-branch-0_3_0/reactos/dll/win32/gdi32/misc/stubsa.c branches/ros-branch-0_3_0/reactos/dll/win32/gdi32/misc/stubsw.c branches/ros-branch-0_3_0/reactos/dll/win32/gdi32/objects/font.c branches/ros-branch-0_3_0/reactos/include/reactos/win32k/ntgdibad.h branches/ros-branch-0_3_0/reactos/include/wingdi.h branches/ros-branch-0_3_0/reactos/subsystems/win32/win32k/objects/text.c branches/ros-branch-0_3_0/reactos/tools/nci/w32ksvc.db
Modified: branches/ros-branch-0_3_0/reactos/dll/win32/gdi32/misc/stubs.c URL: http://svn.reactos.org/svn/reactos/branches/ros-branch-0_3_0/reactos/dll/win... ============================================================================== --- branches/ros-branch-0_3_0/reactos/dll/win32/gdi32/misc/stubs.c (original) +++ branches/ros-branch-0_3_0/reactos/dll/win32/gdi32/misc/stubs.c Mon Jul 31 08:54:21 2006 @@ -251,9 +251,7 @@ HDC hDc ) { - UNIMPLEMENTED; - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return 0; + return NtGdiGetSetTextCharExtra( hDc, 0, FALSE); }
@@ -390,13 +388,11 @@ int STDCALL SetTextCharacterExtra( - HDC a0, - int a1 - ) -{ - UNIMPLEMENTED; - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return 0; + HDC hDC, + int CharExtra + ) +{ + return NtGdiGetSetTextCharExtra( hDC, CharExtra, TRUE); }
Modified: branches/ros-branch-0_3_0/reactos/dll/win32/gdi32/misc/stubsa.c URL: http://svn.reactos.org/svn/reactos/branches/ros-branch-0_3_0/reactos/dll/win... ============================================================================== --- branches/ros-branch-0_3_0/reactos/dll/win32/gdi32/misc/stubsa.c (original) +++ branches/ros-branch-0_3_0/reactos/dll/win32/gdi32/misc/stubsa.c Mon Jul 31 08:54:21 2006 @@ -32,22 +32,6 @@ return 0; }
-/* - * @unimplemented - */ -UINT -APIENTRY -GetOutlineTextMetricsA( - HDC hdc, - UINT cbData, - LPOUTLINETEXTMETRICA lpOTM - ) -{ - UNIMPLEMENTED; - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return 0; -} -
/* * @unimplemented
Modified: branches/ros-branch-0_3_0/reactos/dll/win32/gdi32/misc/stubsw.c URL: http://svn.reactos.org/svn/reactos/branches/ros-branch-0_3_0/reactos/dll/win... ============================================================================== --- branches/ros-branch-0_3_0/reactos/dll/win32/gdi32/misc/stubsw.c (original) +++ branches/ros-branch-0_3_0/reactos/dll/win32/gdi32/misc/stubsw.c Mon Jul 31 08:54:21 2006 @@ -40,22 +40,6 @@ #endif }
-/* - * @unimplemented - */ -UINT -APIENTRY -GetOutlineTextMetricsW( - HDC hdc, - UINT cbData, - LPOUTLINETEXTMETRICW lpOTM - ) -{ - UNIMPLEMENTED; - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return 0; -} -
/* * @unimplemented
Modified: branches/ros-branch-0_3_0/reactos/dll/win32/gdi32/objects/font.c URL: http://svn.reactos.org/svn/reactos/branches/ros-branch-0_3_0/reactos/dll/win... ============================================================================== --- branches/ros-branch-0_3_0/reactos/dll/win32/gdi32/objects/font.c (original) +++ branches/ros-branch-0_3_0/reactos/dll/win32/gdi32/objects/font.c Mon Jul 31 08:54:21 2006 @@ -14,6 +14,33 @@ #include <debug.h>
#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) @@ -538,6 +565,160 @@ return NtGdiGetGlyphOutline ( hdc, uChar, uFormat, lpgm, cbBuffer, lpvBuffer, (CONST LPMAT2)lpmat2, TRUE); }
+ +/* + * @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); +}
/*
Modified: branches/ros-branch-0_3_0/reactos/include/reactos/win32k/ntgdibad.h URL: http://svn.reactos.org/svn/reactos/branches/ros-branch-0_3_0/reactos/include... ============================================================================== --- branches/ros-branch-0_3_0/reactos/include/reactos/win32k/ntgdibad.h (original) +++ branches/ros-branch-0_3_0/reactos/include/reactos/win32k/ntgdibad.h Mon Jul 31 08:54:21 2006 @@ -682,6 +682,11 @@ /* Should be done in user-mode using shared GDI Objects. */ INT STDCALL NtGdiGetStretchBltMode(HDC hDC);
+/* Should be done in user-mode using shared GDI Objects. */ +INT +STDCALL +NtGdiGetSetTextCharExtra( HDC hDC, INT CharExtra, BOOL Set); + /* Use NtGdiDoPalette with GdiPalSetSystemEntries. */ UINT STDCALL
Modified: branches/ros-branch-0_3_0/reactos/include/wingdi.h URL: http://svn.reactos.org/svn/reactos/branches/ros-branch-0_3_0/reactos/include... ============================================================================== --- branches/ros-branch-0_3_0/reactos/include/wingdi.h (original) +++ branches/ros-branch-0_3_0/reactos/include/wingdi.h Mon Jul 31 08:54:21 2006 @@ -1128,6 +1128,7 @@ #define TT_POLYGON_TYPE 24 #define TT_PRIM_LINE 1 #define TT_PRIM_QSPLINE 2 +#define TT_PRIM_CSPLINE 3 #define FONTMAPPER_MAX 10 #define ENHMETA_STOCK_OBJECT 0x80000000 #define WGL_FONT_LINES 0
Modified: branches/ros-branch-0_3_0/reactos/subsystems/win32/win32k/objects/text.c URL: http://svn.reactos.org/svn/reactos/branches/ros-branch-0_3_0/reactos/subsyst... ============================================================================== --- branches/ros-branch-0_3_0/reactos/subsystems/win32/win32k/objects/text.c (original) +++ branches/ros-branch-0_3_0/reactos/subsystems/win32/win32k/objects/text.c Mon Jul 31 08:54:21 2006 @@ -29,6 +29,10 @@ #include <ft2build.h> #include FT_FREETYPE_H #include <freetype/tttables.h> +#include <freetype/fttrigon.h> +#include <freetype/ftglyph.h> +#include <freetype/ftoutln.h> +#include <freetype/ftwinfnt.h>
#define NDEBUG #include <debug.h> @@ -1973,42 +1977,7 @@ UINT LastChar, LPABC abc) { - DPRINT1("NtGdiGetCharABCWidths Is unimplemented, keep going anyway\n"); - return 1; -} - -BOOL -STDCALL -NtGdiGetCharABCWidthsFloat(HDC hDC, - UINT FirstChar, - UINT LastChar, - LPABCFLOAT abcF) -{ - UNIMPLEMENTED; - return FALSE; -} - -DWORD -STDCALL -NtGdiGetCharacterPlacement(HDC hDC, - LPCWSTR String, - int Count, - int MaxExtent, - LPGCP_RESULTSW Results, - DWORD Flags) -{ - UNIMPLEMENTED; - return 0; -} - -BOOL -STDCALL -NtGdiGetCharWidth32(HDC hDC, - UINT FirstChar, - UINT LastChar, - LPINT Buffer) -{ - LPINT SafeBuffer; + LPABC SafeBuffer; PDC dc; PTEXTOBJ TextObj; PFONTGDI FontGDI; @@ -2016,6 +1985,7 @@ FT_CharMap charmap, found = NULL; UINT i, glyph_index, BufferSize; HFONT hFont = 0; + NTSTATUS Status;
if (LastChar < FirstChar) { @@ -2023,7 +1993,7 @@ return FALSE; }
- BufferSize = (LastChar - FirstChar + 1) * sizeof(INT); + BufferSize = (LastChar - FirstChar + 1) * sizeof(ABC); SafeBuffer = ExAllocatePoolWithTag(PagedPool, BufferSize, TAG_GDITEXT); if (SafeBuffer == NULL) { @@ -2081,6 +2051,150 @@ FT_Set_Pixel_Sizes(face, TextObj->logfont.lfWidth, /* FIXME should set character height if neg */ + (TextObj->logfont.lfHeight < 0 ? - TextObj->logfont.lfHeight : + TextObj->logfont.lfHeight == 0 ? 11 : TextObj->logfont.lfHeight)); + + for (i = FirstChar; i <= LastChar; i++) + { + int adv, lsb, bbx, left, right; + + glyph_index = FT_Get_Char_Index(face, i); + FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT); + + left = (INT)face->glyph->metrics.horiBearingX & -64; + right = (INT)((face->glyph->metrics.horiBearingX + face->glyph->metrics.width) + 63) & -64; + adv = (face->glyph->advance.x + 32) >> 6; + +// int test = (INT)(face->glyph->metrics.horiAdvance + 63) >> 6; +// DPRINT1("Advance Wine %d and Advance Ros %d\n",test, adv ); /* It's the same!*/ + + lsb = left >> 6; + bbx = (right - left) >> 6; +/* + DPRINT1("lsb %d and bbx %d\n", lsb, bbx ); + */ + SafeBuffer[i - FirstChar].abcA = lsb; + SafeBuffer[i - FirstChar].abcB = bbx; + SafeBuffer[i - FirstChar].abcC = adv - lsb - bbx; + } + IntUnLockFreeType; + TEXTOBJ_UnlockText(TextObj); + Status = MmCopyToCaller(abc, SafeBuffer, BufferSize); + if (! NT_SUCCESS(Status)) + { + SetLastNtError(Status); + ExFreePool(SafeBuffer); + return FALSE; + } + ExFreePool(SafeBuffer); + DPRINT("NtGdiGetCharABCWidths Worked!\n"); + return TRUE; +} + +BOOL +STDCALL +NtGdiGetCharABCWidthsFloat(HDC hDC, + UINT FirstChar, + UINT LastChar, + LPABCFLOAT abcF) +{ + UNIMPLEMENTED; + return FALSE; +} + +DWORD +STDCALL +NtGdiGetCharacterPlacement(HDC hDC, + LPCWSTR String, + int Count, + int MaxExtent, + LPGCP_RESULTSW Results, + DWORD Flags) +{ + UNIMPLEMENTED; + return 0; +} + +BOOL +STDCALL +NtGdiGetCharWidth32(HDC hDC, + UINT FirstChar, + UINT LastChar, + LPINT Buffer) +{ + LPINT SafeBuffer; + PDC dc; + PTEXTOBJ TextObj; + PFONTGDI FontGDI; + FT_Face face; + FT_CharMap charmap, found = NULL; + UINT i, glyph_index, BufferSize; + HFONT hFont = 0; + + if (LastChar < FirstChar) + { + SetLastWin32Error(ERROR_INVALID_PARAMETER); + return FALSE; + } + + BufferSize = (LastChar - FirstChar + 1) * sizeof(INT); + SafeBuffer = ExAllocatePoolWithTag(PagedPool, BufferSize, TAG_GDITEXT); + if (SafeBuffer == NULL) + { + SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + + dc = DC_LockDc(hDC); + if (dc == NULL) + { + ExFreePool(SafeBuffer); + SetLastWin32Error(ERROR_INVALID_HANDLE); + return FALSE; + } + hFont = dc->w.hFont; + TextObj = TEXTOBJ_LockText(hFont); + DC_UnlockDc(dc); + + if (TextObj == NULL) + { + ExFreePool(SafeBuffer); + SetLastWin32Error(ERROR_INVALID_HANDLE); + return FALSE; + } + + FontGDI = ObjToGDI(TextObj->Font, FONT); + + face = FontGDI->face; + if (face->charmap == NULL) + { + for (i = 0; i < face->num_charmaps; i++) + { + charmap = face->charmaps[i]; + if (charmap->encoding != 0) + { + found = charmap; + break; + } + } + + if (!found) + { + DPRINT1("WARNING: Could not find desired charmap!\n"); + ExFreePool(SafeBuffer); + SetLastWin32Error(ERROR_INVALID_HANDLE); + return FALSE; + } + + IntLockFreeType; + FT_Set_Charmap(face, found); + IntUnLockFreeType; + } + + IntLockFreeType; + FT_Set_Pixel_Sizes(face, + TextObj->logfont.lfWidth, + /* FIXME should set character height if neg */ (TextObj->logfont.lfHeight < 0 ? - TextObj->logfont.lfHeight : TextObj->logfont.lfHeight == 0 ? 11 : TextObj->logfont.lfHeight)); @@ -2117,6 +2231,44 @@ return 0; }
+static +void +FTVectorToPOINTFX(FT_Vector *vec, POINTFX *pt) +{ + pt->x.value = vec->x >> 6; + pt->x.fract = (vec->x & 0x3f) << 10; + pt->x.fract |= ((pt->x.fract >> 6) | (pt->x.fract >> 12)); + pt->y.value = vec->y >> 6; + pt->y.fract = (vec->y & 0x3f) << 10; + pt->y.fract |= ((pt->y.fract >> 6) | (pt->y.fract >> 12)); + return; +} + +/* + This function builds an FT_Fixed from a float. It puts the integer part + in the highest 16 bits and the decimal part in the lowest 16 bits of the FT_Fixed. + It fails if the integer part of the float number is greater than SHORT_MAX. +*/ +static inline FT_Fixed FT_FixedFromFloat(float f) +{ + short value = f; + unsigned short fract = (f - value) * 0xFFFF; + return (FT_Fixed)((long)value << 16 | (unsigned long)fract); +} + +/* + This function builds an FT_Fixed from a FIXED. It simply put f.value + in the highest 16 bits and f.fract in the lowest 16 bits of the FT_Fixed. +*/ +static inline FT_Fixed FT_FixedFromFIXED(FIXED f) +{ + return (FT_Fixed)((long)f.value << 16 | (unsigned long)f.fract); +} + +/* + * Based on WineEngGetGlyphOutline + * + */ ULONG APIENTRY NtGdiGetGlyphOutline( @@ -2125,12 +2277,631 @@ IN UINT iFormat, OUT LPGLYPHMETRICS pgm, IN ULONG cjBuf, - OUT OPTIONAL PVOID pvBuf, + OUT OPTIONAL PVOID UnsafeBuf, IN LPMAT2 pmat2, IN BOOL bIgnoreRotation) { - UNIMPLEMENTED; - return 0; + static const FT_Matrix identityMat = {(1 << 16), 0, 0, (1 << 16)}; + PDC dc; + PTEXTOBJ TextObj; + PFONTGDI FontGDI; + HFONT hFont = 0; + NTSTATUS Status; + GLYPHMETRICS gm; + ULONG Size; + FT_Face ft_face; + FT_UInt glyph_index; + DWORD width, height, pitch, needed = 0; + FT_Bitmap ft_bitmap; + FT_Error error; + INT left, right, top = 0, bottom = 0; + FT_Angle angle = 0; + FT_Int load_flags = FT_LOAD_DEFAULT | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH; + FLOAT eM11, widthRatio = 1.0; + FT_Matrix transMat = identityMat; + BOOL needsTransform = FALSE; + INT orientation; + LONG aveWidth; + INT adv, lsb, bbx; /* These three hold to widths of the unrotated chars */ + OUTLINETEXTMETRICW *potm; + PVOID pvBuf = NULL; + + DPRINT("%p, %d, %08x, %p, %08lx, %p, %p\n", hdc, wch, iFormat, pgm, + cjBuf, UnsafeBuf, pmat2); + + dc = DC_LockDc(hdc); + if (!dc) + { + SetLastWin32Error(ERROR_INVALID_HANDLE); + return GDI_ERROR; + } + eM11 = dc->w.xformWorld2Vport.eM11; + hFont = dc->w.hFont; + TextObj = TEXTOBJ_LockText(hFont); + DC_UnlockDc(dc); + if (!TextObj) + { + SetLastWin32Error(ERROR_INVALID_HANDLE); + return GDI_ERROR; + } + FontGDI = ObjToGDI(TextObj->Font, FONT); + ft_face = FontGDI->face; + + aveWidth = FT_IS_SCALABLE(ft_face) ? TextObj->logfont.lfWidth: 0; + orientation = FT_IS_SCALABLE(ft_face) ? TextObj->logfont.lfOrientation: 0; + + Size = IntGetOutlineTextMetrics(FontGDI, 0, NULL); + potm = ExAllocatePoolWithTag(PagedPool, Size, TAG_GDITEXT); + if (!potm) + { + SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); + TEXTOBJ_UnlockText(TextObj); + return GDI_ERROR; + } + IntGetOutlineTextMetrics(FontGDI, Size, potm); + + IntLockFreeType; + + /* During testing, I never saw this used. In here just incase.*/ + if (ft_face->charmap == NULL) + { + DPRINT("WARNING: No charmap selected!\n"); + DPRINT("This font face has %d charmaps\n", ft_face->num_charmaps); + int n; + FT_CharMap found = 0, charmap; + + for (n = 0; n < ft_face->num_charmaps; n++) + { + charmap = ft_face->charmaps[n]; + DPRINT("found charmap encoding: %u\n", charmap->encoding); + if (charmap->encoding != 0) + { + found = charmap; + break; + } + } + if (!found) + { + DPRINT1("WARNING: Could not find desired charmap!\n"); + } + error = FT_Set_Charmap(ft_face, found); + if (error) + { + DPRINT1("WARNING: Could not set the charmap!\n"); + } + } + +// FT_Set_Pixel_Sizes(ft_face, +// TextObj->logfont.lfWidth, + /* FIXME should set character height if neg */ +// (TextObj->logfont.lfHeight < 0 ? - TextObj->logfont.lfHeight : +// TextObj->logfont.lfHeight == 0 ? 11 : TextObj->logfont.lfHeight)); + + TEXTOBJ_UnlockText(TextObj); + + if (iFormat & GGO_GLYPH_INDEX) + { + glyph_index = wch; + iFormat &= ~GGO_GLYPH_INDEX; + } + else glyph_index = FT_Get_Char_Index(ft_face, wch); + + if (orientation || (iFormat != GGO_METRICS && iFormat != GGO_BITMAP) || aveWidth || pmat2) + load_flags |= FT_LOAD_NO_BITMAP; + + error = FT_Load_Glyph(ft_face, glyph_index, load_flags); + if (error) + { + DPRINT1("WARNING: Failed to load and render glyph! [index: %u]\n", glyph_index); + IntUnLockFreeType; + if (potm) ExFreePool(potm); + return GDI_ERROR; + } + IntUnLockFreeType; + + if (aveWidth && potm) + { + widthRatio = (FLOAT)aveWidth * eM11 / + (FLOAT) potm->otmTextMetrics.tmAveCharWidth; + } + + left = (INT)(ft_face->glyph->metrics.horiBearingX * widthRatio) & -64; + right = (INT)((ft_face->glyph->metrics.horiBearingX + + ft_face->glyph->metrics.width) * widthRatio + 63) & -64; + + adv = (INT)((ft_face->glyph->metrics.horiAdvance * widthRatio) + 63) >> 6; + lsb = left >> 6; + bbx = (right - left) >> 6; + + DPRINT("Advance = %d, lsb = %d, bbx = %d\n",adv, lsb, bbx); + + IntLockFreeType; + + /* Scaling transform */ + if (aveWidth) + { + FT_Matrix scaleMat; + DPRINT("Scaling Trans!\n"); + scaleMat.xx = FT_FixedFromFloat(widthRatio); + scaleMat.xy = 0; + scaleMat.yx = 0; + scaleMat.yy = (1 << 16); + FT_Matrix_Multiply(&scaleMat, &transMat); + needsTransform = TRUE; + } + + /* Slant transform */ + if (potm->otmTextMetrics.tmItalic) + { + FT_Matrix slantMat; + DPRINT("Slant Trans!\n"); + slantMat.xx = (1 << 16); + slantMat.xy = ((1 << 16) >> 2); + slantMat.yx = 0; + slantMat.yy = (1 << 16); + FT_Matrix_Multiply(&slantMat, &transMat); + needsTransform = TRUE; + } + + /* Rotation transform */ + if (orientation) + { + FT_Matrix rotationMat; + FT_Vector vecAngle; + DPRINT("Rotation Trans!\n"); + angle = FT_FixedFromFloat((float)orientation / 10.0); + FT_Vector_Unit(&vecAngle, angle); + rotationMat.xx = vecAngle.x; + rotationMat.xy = -vecAngle.y; + rotationMat.yx = -rotationMat.xy; + rotationMat.yy = rotationMat.xx; + FT_Matrix_Multiply(&rotationMat, &transMat); + needsTransform = TRUE; + } + + /* Extra transformation specified by caller */ + if (pmat2) + { + FT_Matrix extraMat; + DPRINT("MAT2 Matrix Trans!\n"); + extraMat.xx = FT_FixedFromFIXED(pmat2->eM11); + extraMat.xy = FT_FixedFromFIXED(pmat2->eM21); + extraMat.yx = FT_FixedFromFIXED(pmat2->eM12); + extraMat.yy = FT_FixedFromFIXED(pmat2->eM22); + FT_Matrix_Multiply(&extraMat, &transMat); + needsTransform = TRUE; + } + + if (potm) ExFreePool(potm); /* It looks like we are finished with potm ATM.*/ + + if (!needsTransform) + { + DPRINT("No Need to be Transformed!\n"); + top = (ft_face->glyph->metrics.horiBearingY + 63) & -64; + bottom = (ft_face->glyph->metrics.horiBearingY - + ft_face->glyph->metrics.height) & -64; + gm.gmCellIncX = adv; + gm.gmCellIncY = 0; + } + else + { + INT xc, yc; + FT_Vector vec; + for(xc = 0; xc < 2; xc++) + { + for(yc = 0; yc < 2; yc++) + { + vec.x = (ft_face->glyph->metrics.horiBearingX + + xc * ft_face->glyph->metrics.width); + vec.y = ft_face->glyph->metrics.horiBearingY - + yc * ft_face->glyph->metrics.height; + DPRINT("Vec %ld,%ld\n", vec.x, vec.y); + FT_Vector_Transform(&vec, &transMat); + if(xc == 0 && yc == 0) + { + left = right = vec.x; + top = bottom = vec.y; + } + else + { + if(vec.x < left) left = vec.x; + else if(vec.x > right) right = vec.x; + if(vec.y < bottom) bottom = vec.y; + else if(vec.y > top) top = vec.y; + } + } + } + left = left & -64; + right = (right + 63) & -64; + bottom = bottom & -64; + top = (top + 63) & -64; + + DPRINT("transformed box: (%d,%d - %d,%d)\n", left, top, right, bottom); + vec.x = ft_face->glyph->metrics.horiAdvance; + vec.y = 0; + FT_Vector_Transform(&vec, &transMat); + gm.gmCellIncX = (vec.x+63) >> 6; + gm.gmCellIncY = -((vec.y+63) >> 6); + } + gm.gmBlackBoxX = (right - left) >> 6; + gm.gmBlackBoxY = (top - bottom) >> 6; + gm.gmptGlyphOrigin.x = left >> 6; + gm.gmptGlyphOrigin.y = top >> 6; + + DPRINT("CX %d CY %d BBX %d BBY %d GOX %d GOY %d\n", + gm.gmCellIncX, gm.gmCellIncY, + gm.gmBlackBoxX, gm.gmBlackBoxY, + gm.gmptGlyphOrigin.x, gm.gmptGlyphOrigin.y); + + IntUnLockFreeType; + + if (pgm) + { + Status = MmCopyToCaller(pgm, &gm, sizeof(GLYPHMETRICS)); + if (! NT_SUCCESS(Status)) + { + SetLastWin32Error(ERROR_INVALID_PARAMETER); + return GDI_ERROR; + } + DPRINT("Copied GLYPHMETRICS to User!\n"); + } + + if (iFormat == GGO_METRICS) + { + DPRINT("GGO_METRICS Exit!\n"); + return 1; /* FIXME */ + } + + if (ft_face->glyph->format != ft_glyph_format_outline && iFormat != GGO_BITMAP) + { + DPRINT1("loaded a bitmap\n"); + return GDI_ERROR; + } + + if (UnsafeBuf && cjBuf) + { + pvBuf = ExAllocatePoolWithTag(PagedPool, cjBuf, TAG_GDITEXT); + if (pvBuf == NULL) + { + SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); + return GDI_ERROR; + } + RtlZeroMemory(pvBuf, cjBuf); + } + + + switch(iFormat) + { + case GGO_BITMAP: + width = gm.gmBlackBoxX; + height = gm.gmBlackBoxY; + pitch = ((width + 31) >> 5) << 2; + needed = pitch * height; + + if(!pvBuf || !cjBuf) break; + + switch(ft_face->glyph->format) + { + case ft_glyph_format_bitmap: + { + BYTE *src = ft_face->glyph->bitmap.buffer, *dst = pvBuf; + INT w = (ft_face->glyph->bitmap.width + 7) >> 3; + INT h = ft_face->glyph->bitmap.rows; + while(h--) + { + RtlCopyMemory(dst, src, w); + src += ft_face->glyph->bitmap.pitch; + dst += pitch; + } + break; + } + + case ft_glyph_format_outline: + ft_bitmap.width = width; + ft_bitmap.rows = height; + ft_bitmap.pitch = pitch; + ft_bitmap.pixel_mode = ft_pixel_mode_mono; + ft_bitmap.buffer = pvBuf; + + IntLockFreeType; + if(needsTransform) + { + FT_Outline_Transform(&ft_face->glyph->outline, &transMat); + } + FT_Outline_Translate(&ft_face->glyph->outline, -left, -bottom ); + /* Note: FreeType will only set 'black' bits for us. */ + RtlZeroMemory(pvBuf, needed); + FT_Outline_Get_Bitmap(library, &ft_face->glyph->outline, &ft_bitmap); + IntUnLockFreeType; + break; + + default: + DPRINT1("loaded glyph format %x\n", ft_face->glyph->format); + if(pvBuf) ExFreePool(pvBuf); + return GDI_ERROR; + } + break; + + case GGO_GRAY2_BITMAP: + case GGO_GRAY4_BITMAP: + case GGO_GRAY8_BITMAP: + { + unsigned int mult, row, col; + BYTE *start, *ptr; + + width = gm.gmBlackBoxX; + height = gm.gmBlackBoxY; + pitch = (width + 3) / 4 * 4; + needed = pitch * height; + + if(!pvBuf || !cjBuf) break; + + ft_bitmap.width = width; + ft_bitmap.rows = height; + ft_bitmap.pitch = pitch; + ft_bitmap.pixel_mode = ft_pixel_mode_grays; + ft_bitmap.buffer = pvBuf; + + IntLockFreeType; + if(needsTransform) + { + FT_Outline_Transform(&ft_face->glyph->outline, &transMat); + } + FT_Outline_Translate(&ft_face->glyph->outline, -left, -bottom ); + RtlZeroMemory(ft_bitmap.buffer, cjBuf); + FT_Outline_Get_Bitmap(library, &ft_face->glyph->outline, &ft_bitmap); + IntUnLockFreeType; + + if(iFormat == GGO_GRAY2_BITMAP) + mult = 4; + else if(iFormat == GGO_GRAY4_BITMAP) + mult = 16; + else if(iFormat == GGO_GRAY8_BITMAP) + mult = 64; + else + { + ASSERT(0); + break; + } + + start = pvBuf; + for(row = 0; row < height; row++) + { + ptr = start; + for(col = 0; col < width; col++, ptr++) + { + *ptr = (((int)*ptr) * mult + 128) / 256; + } + start += pitch; + } + break; + } + + case GGO_NATIVE: + { + int contour, point = 0, first_pt; + FT_Outline *outline = &ft_face->glyph->outline; + TTPOLYGONHEADER *pph; + TTPOLYCURVE *ppc; + DWORD pph_start, cpfx, type; + + if(cjBuf == 0) pvBuf = NULL; /* This is okay, need cjBuf to allocate. */ + + IntLockFreeType; + if (needsTransform && pvBuf) FT_Outline_Transform(outline, &transMat); + + for(contour = 0; contour < outline->n_contours; contour++) + { + pph_start = needed; + pph = (TTPOLYGONHEADER *)((char *)pvBuf + needed); + first_pt = point; + if(pvBuf) + { + pph->dwType = TT_POLYGON_TYPE; + FTVectorToPOINTFX(&outline->points[point], &pph->pfxStart); + } + needed += sizeof(*pph); + point++; + while(point <= outline->contours[contour]) + { + ppc = (TTPOLYCURVE *)((char *)pvBuf + needed); + type = (outline->tags[point] & FT_Curve_Tag_On) ? + TT_PRIM_LINE : TT_PRIM_QSPLINE; + cpfx = 0; + do + { + if(pvBuf) + FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]); + cpfx++; + point++; + } while(point <= outline->contours[contour] && + (outline->tags[point] & FT_Curve_Tag_On) == + (outline->tags[point-1] & FT_Curve_Tag_On)); + + /* At the end of a contour Windows adds the start point, but + only for Beziers */ + if(point > outline->contours[contour] && + !(outline->tags[point-1] & FT_Curve_Tag_On)) + { + if(pvBuf) + FTVectorToPOINTFX(&outline->points[first_pt], &ppc->apfx[cpfx]); + cpfx++; + } + else if(point <= outline->contours[contour] && + outline->tags[point] & FT_Curve_Tag_On) + { + /* add closing pt for bezier */ + if(pvBuf) + FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]); + cpfx++; + point++; + } + if(pvBuf) + { + ppc->wType = type; + ppc->cpfx = cpfx; + } + needed += sizeof(*ppc) + (cpfx - 1) * sizeof(POINTFX); + } + if(pvBuf) pph->cb = needed - pph_start; + } + IntUnLockFreeType; + break; + } + case GGO_BEZIER: + { + /* Convert the quadratic Beziers to cubic Beziers. + The parametric eqn for a cubic Bezier is, from PLRM: + r(t) = at^3 + bt^2 + ct + r0 + with the control points: + r1 = r0 + c/3 + r2 = r1 + (c + b)/3 + r3 = r0 + c + b + a + + A quadratic Beizer has the form: + p(t) = (1-t)^2 p0 + 2(1-t)t p1 + t^2 p2 + + So equating powers of t leads to: + r1 = 2/3 p1 + 1/3 p0 + r2 = 2/3 p1 + 1/3 p2 + and of course r0 = p0, r3 = p2 + */ + + int contour, point = 0, first_pt; + FT_Outline *outline = &ft_face->glyph->outline; + TTPOLYGONHEADER *pph; + TTPOLYCURVE *ppc; + DWORD pph_start, cpfx, type; + FT_Vector cubic_control[4]; + if(cjBuf == 0) pvBuf = NULL; + + if (needsTransform && pvBuf) + { + IntLockFreeType; + FT_Outline_Transform(outline, &transMat); + IntUnLockFreeType; + } + + for(contour = 0; contour < outline->n_contours; contour++) + { + pph_start = needed; + pph = (TTPOLYGONHEADER *)((char *)pvBuf + needed); + first_pt = point; + if(pvBuf) + { + pph->dwType = TT_POLYGON_TYPE; + FTVectorToPOINTFX(&outline->points[point], &pph->pfxStart); + } + needed += sizeof(*pph); + point++; + while(point <= outline->contours[contour]) + { + ppc = (TTPOLYCURVE *)((char *)pvBuf + needed); + type = (outline->tags[point] & FT_Curve_Tag_On) ? + TT_PRIM_LINE : TT_PRIM_CSPLINE; + cpfx = 0; + do + { + if(type == TT_PRIM_LINE) + { + if(pvBuf) + FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]); + cpfx++; + point++; + } + else + { + /* Unlike QSPLINEs, CSPLINEs always have their endpoint + so cpfx = 3n */ + + /* FIXME: Possible optimization in endpoint calculation + if there are two consecutive curves */ + cubic_control[0] = outline->points[point-1]; + if(!(outline->tags[point-1] & FT_Curve_Tag_On)) + { + cubic_control[0].x += outline->points[point].x + 1; + cubic_control[0].y += outline->points[point].y + 1; + cubic_control[0].x >>= 1; + cubic_control[0].y >>= 1; + } + if(point+1 > outline->contours[contour]) + cubic_control[3] = outline->points[first_pt]; + else + { + cubic_control[3] = outline->points[point+1]; + if(!(outline->tags[point+1] & FT_Curve_Tag_On)) + { + cubic_control[3].x += outline->points[point].x + 1; + cubic_control[3].y += outline->points[point].y + 1; + cubic_control[3].x >>= 1; + cubic_control[3].y >>= 1; + } + } + /* r1 = 1/3 p0 + 2/3 p1 + r2 = 1/3 p2 + 2/3 p1 */ + cubic_control[1].x = (2 * outline->points[point].x + 1) / 3; + cubic_control[1].y = (2 * outline->points[point].y + 1) / 3; + cubic_control[2] = cubic_control[1]; + cubic_control[1].x += (cubic_control[0].x + 1) / 3; + cubic_control[1].y += (cubic_control[0].y + 1) / 3; + cubic_control[2].x += (cubic_control[3].x + 1) / 3; + cubic_control[2].y += (cubic_control[3].y + 1) / 3; + if(pvBuf) + { + FTVectorToPOINTFX(&cubic_control[1], &ppc->apfx[cpfx]); + FTVectorToPOINTFX(&cubic_control[2], &ppc->apfx[cpfx+1]); + FTVectorToPOINTFX(&cubic_control[3], &ppc->apfx[cpfx+2]); + } + cpfx += 3; + point++; + } + } + while(point <= outline->contours[contour] && + (outline->tags[point] & FT_Curve_Tag_On) == + (outline->tags[point-1] & FT_Curve_Tag_On)); + /* At the end of a contour Windows adds the start point, + but only for Beziers and we've already done that. + */ + if(point <= outline->contours[contour] && + outline->tags[point] & FT_Curve_Tag_On) + { + /* This is the closing pt of a bezier, but we've already + added it, so just inc point and carry on */ + point++; + } + if(pvBuf) + { + ppc->wType = type; + ppc->cpfx = cpfx; + } + needed += sizeof(*ppc) + (cpfx - 1) * sizeof(POINTFX); + } + if(pvBuf) pph->cb = needed - pph_start; + } + break; + } + + default: + DPRINT1("Unsupported format %d\n", iFormat); + if(pvBuf) ExFreePool(pvBuf); + return GDI_ERROR; + } + + if (pvBuf) + { + Status = MmCopyToCaller(UnsafeBuf, pvBuf, cjBuf); + if (! NT_SUCCESS(Status)) + { + SetLastWin32Error(ERROR_INVALID_PARAMETER); + ExFreePool(pvBuf); + return GDI_ERROR; + } + DPRINT("NtGdiGetGlyphOutline K -> U worked!\n"); + ExFreePool(pvBuf); + } + + DPRINT("NtGdiGetGlyphOutline END and needed %d\n", needed); + return needed; }
DWORD @@ -2143,15 +2914,68 @@ 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 @@ -3104,4 +3928,25 @@ return sizeof(LOGFONTW); }
+ +/* Remove this HAX! after the below function is done in GDI32.DLL! */ +INT +STDCALL +NtGdiGetSetTextCharExtra( HDC hDC, INT CharExtra, BOOL Set) +{ + /* Ulta-Ugly Hax! */ + INT Ret = 0x80000000; + DPRINT("TextCharacterExtra %d", CharExtra); + PDC dc = DC_LockDc ( hDC ); + if (!dc) + { + SetLastWin32Error(ERROR_INVALID_HANDLE); + return Ret; + } + Ret = dc->w.charExtra; + if( Set ) dc->w.charExtra = CharExtra; + DC_UnlockDc(dc); + return (Ret); +} + /* EOF */
Modified: branches/ros-branch-0_3_0/reactos/tools/nci/w32ksvc.db URL: http://svn.reactos.org/svn/reactos/branches/ros-branch-0_3_0/reactos/tools/n... ============================================================================== --- branches/ros-branch-0_3_0/reactos/tools/nci/w32ksvc.db (original) +++ branches/ros-branch-0_3_0/reactos/tools/nci/w32ksvc.db Mon Jul 31 08:54:21 2006 @@ -150,6 +150,7 @@ NtGdiGetRelAbs 1 NtGdiGetRegionData 3 NtGdiGetRgnBox 2 +NtGdiGetSetTextCharExtra 3 NtGdiGetStockObject 1 NtGdiGetStretchBltMode 1 NtGdiGetSystemPaletteEntries 4