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/wi…
==============================================================================
--- 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/wi…
==============================================================================
--- 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/wi…
==============================================================================
--- 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/wi…
==============================================================================
--- 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/includ…
==============================================================================
--- 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/includ…
==============================================================================
--- 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/subsys…
==============================================================================
--- 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/…
==============================================================================
--- 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