|
|
/******************Module*Header********************************************\
* Module Name: dcquery.c * * * * Client side stubs for functions that query the DC in the server. * * * * Created: 05-Jun-1991 01:43:56 * * Author: Charles Whitmer [chuckwh] * * * * Copyright (c) 1991-1999 Microsoft Corporation * \**************************************************************************/
#include "precomp.h"
#pragma hdrstop
#if DBG
FLONG gflDebug = 0; #endif
// This macro retrieves the current code page, carefully masking off the
// charset:
#define GET_CODE_PAGE(hdc,pDcAttr) \
((!(pDcAttr->ulDirty_ & DIRTY_CHARSET) ? pDcAttr->iCS_CP \ : NtGdiGetCharSet(hdc)) & 0xffff) BOOL bIsDBCSString(LPCSTR psz, int cc);
/******************************Public*Routine******************************\
* vOutlineTextMetricWToOutlineTextMetricA * * Convert from OUTLINETEXTMETRICA (ANSI structure) to OUTLINETEXTMETRICW * (UNICODE structure). * * Note: * This function is capable of converting in place (in and out buffers * can be the same). * * Returns: * TTRUE if successful, FALSE otherwise. * * History: * 02-Mar-1992 -by- Gilman Wong [gilmanw] * Wrote it. \**************************************************************************/
VOID vOutlineTextMetricWToOutlineTextMetricA ( LPOUTLINETEXTMETRICA potma, OUTLINETEXTMETRICW * potmw, TMDIFF * ptmd ) { // Size.
potma->otmSize = potmw->otmSize;
// Convert the textmetrics.
vTextMetricWToTextMetricStrict( &potma->otmTextMetrics, &potmw->otmTextMetrics);
potma->otmTextMetrics.tmFirstChar = ptmd->chFirst; potma->otmTextMetrics.tmLastChar = ptmd->chLast; potma->otmTextMetrics.tmDefaultChar = ptmd->chDefault; potma->otmTextMetrics.tmBreakChar = ptmd->chBreak;
// for Win 64 we need to copy these fields one by one due to alignement difference
potma->otmFiller = potmw->otmFiller; potma->otmPanoseNumber = potmw->otmPanoseNumber; potma->otmfsSelection = potmw->otmfsSelection; potma->otmfsType = potmw->otmfsType; potma->otmsCharSlopeRise = potmw->otmsCharSlopeRise; potma->otmsCharSlopeRun = potmw->otmsCharSlopeRun; potma->otmItalicAngle = potmw->otmItalicAngle; potma->otmEMSquare = potmw->otmEMSquare; potma->otmAscent = potmw->otmAscent; potma->otmDescent = potmw->otmDescent; potma->otmLineGap = potmw->otmLineGap; potma->otmsCapEmHeight = potmw->otmsCapEmHeight; potma->otmsXHeight = potmw->otmsXHeight; potma->otmrcFontBox = potmw->otmrcFontBox; potma->otmMacAscent = potmw->otmMacAscent; potma->otmMacDescent = potmw->otmMacDescent; potma->otmMacLineGap = potmw->otmMacLineGap; potma->otmusMinimumPPEM = potmw->otmusMinimumPPEM; potma->otmptSubscriptSize = potmw->otmptSubscriptSize; potma->otmptSubscriptOffset = potmw->otmptSubscriptOffset; potma->otmptSuperscriptSize = potmw->otmptSuperscriptSize; potma->otmptSuperscriptOffset = potmw->otmptSuperscriptOffset; potma->otmsStrikeoutSize = potmw->otmsStrikeoutSize; potma->otmsStrikeoutPosition = potmw->otmsStrikeoutPosition; potma->otmsUnderscoreSize = potmw->otmsUnderscoreSize; potma->otmsUnderscorePosition = potmw->otmsUnderscorePosition;
// set the offsets to zero for now, this will be changed later if
// the caller wanted strings as well
potma->otmpFamilyName = NULL; potma->otmpFaceName = NULL; potma->otmpStyleName = NULL; potma->otmpFullName = NULL; }
/******************************Public*Routine******************************\
* * vGenerateANSIString * * Effects: Generates Ansi string which consists of consecutive ansi chars * [iFirst, iLast] inclusive. The string is stored in the buffer * puchBuf that the user must ensure is big enough * * * * History: * 24-Feb-1992 -by- Bodin Dresevic [BodinD] * Wrote it. \**************************************************************************/
VOID vGenerateAnsiString(UINT iFirst, UINT iLast, PUCHAR puchBuf) { // Generate string (terminating NULL not needed).
ASSERTGDI((iFirst <= iLast) && (iLast < 256), "gdi!_vGenerateAnsiString\n");
for ( ; iFirst <= iLast; iFirst++) *puchBuf++ = (UCHAR) iFirst; }
/******************************Public*Routine******************************\
* * bSetUpUnicodeString * * Effects: * * Warnings: * * History: * 25-Feb-1992 -by- Bodin Dresevic [BodinD] * Wrote it. \**************************************************************************/
BOOL bSetUpUnicodeString( IN UINT iFirst, // first ansi char
IN UINT iLast, // last char
IN PUCHAR puchTmp, // buffer for an intermediate ansi string
OUT PWCHAR pwc, // output fuffer with a unicode string
IN UINT dwCP // ansi codepage
) { UINT c = iLast - iFirst + 1; vGenerateAnsiString(iFirst,iLast,puchTmp); return MultiByteToWideChar( dwCP, 0, puchTmp,c, pwc, c*sizeof(WCHAR)); }
/******************************Public*Routine******************************\
* GetAspectRatioFilterEx * * GetBrushOrgEx * * * * Client side stubs which all get mapped to GetPoint. * * * * Fri 07-Jun-1991 18:01:50 -by- Charles Whitmer [chuckwh] * * Wrote them. * \**************************************************************************/
BOOL APIENTRY GetAspectRatioFilterEx(HDC hdc,LPSIZE psizl) { FIXUP_HANDLE(hdc);
return(NtGdiGetDCPoint(hdc,DCPT_ASPECTRATIOFILTER,(PPOINTL) psizl)); }
BOOL APIENTRY GetBrushOrgEx(HDC hdc,LPPOINT pptl) { BOOL bRet = FALSE; PDC_ATTR pdcattr;
FIXUP_HANDLE(hdc);
PSHARED_GET_VALIDATE(pdcattr,hdc,DC_TYPE);
if ((pdcattr != NULL) && (pptl != (LPPOINT)NULL)) { *pptl = *((LPPOINT)&pdcattr->ptlBrushOrigin); bRet = TRUE; } else { GdiSetLastError(ERROR_INVALID_PARAMETER); } return(bRet);
}
BOOL APIENTRY GetDCOrgEx(HDC hdc,LPPOINT pptl) { FIXUP_HANDLE(hdc);
return(NtGdiGetDCPoint(hdc,DCPT_DCORG,(PPOINTL)pptl)); }
// The old GetDCOrg is here because it was in the Beta and we are afraid
// to remove it now. It would be nice to remove it.
DWORD APIENTRY GetDCOrg(HDC hdc) { hdc; return(0); }
/******************************Public*Routine******************************\
* Client side stub for GetCurrentPositionEx. * * Wed 02-Sep-1992 -by- J. Andrew Goossen [andrewgo] * Wrote it. \**************************************************************************/
BOOL APIENTRY GetCurrentPositionEx(HDC hdc,LPPOINT pptl) { BOOL bRet = FALSE;
PDC_ATTR pDcAttr;
FIXUP_HANDLE(hdc);
PSHARED_GET_VALIDATE(pDcAttr,hdc,DC_TYPE);
if ((pDcAttr) && (pptl != (LPPOINT)NULL)) { bRet = TRUE;
if (pDcAttr->ulDirty_ & DIRTY_PTLCURRENT) { // If the logical-space version of the current position is invalid,
// then the device-space version of the current position is
// guaranteed to be valid. So we can reverse the current transform
// on that to compute the logical-space version:
*((POINTL*)pptl) = pDcAttr->ptfxCurrent;
pptl->x = FXTOL(pptl->x); pptl->y = FXTOL(pptl->y); bRet = DPtoLP(hdc,pptl,1);
if (bRet) { pDcAttr->ptlCurrent = *((POINTL*)pptl); pDcAttr->ulDirty_ &= ~DIRTY_PTLCURRENT; } } else { *((POINTL*)pptl) = pDcAttr->ptlCurrent; } } else { GdiSetLastError(ERROR_INVALID_PARAMETER); }
return(bRet); }
/******************************Public*Routine******************************\
* GetPixel * * * * Client side stub. * * * * Fri 07-Jun-1991 18:01:50 -by- Charles Whitmer [chuckwh] * * Wrote it. * \**************************************************************************/
DWORD APIENTRY GetPixel(HDC hdc,int x,int y) { PDC_ATTR pdca; COLORREF ColorRet = CLR_INVALID;
FIXUP_HANDLE(hdc); PSHARED_GET_VALIDATE(pdca,hdc,DC_TYPE);
if (pdca) { //
// if the color is not a PaletteIndex and
// ICM is on then translate
//
ColorRet = NtGdiGetPixel(hdc,x,y);
if ( bNeedTranslateColor(pdca) && ( IS_32BITS_COLOR(pdca->lIcmMode) || ((ColorRet != CLR_INVALID) && !(ColorRet & 0x01000000)) ) ) { //
// translate back color to original.
//
COLORREF NewColor;
BOOL bStatus = IcmTranslateCOLORREF(hdc, pdca, ColorRet, &NewColor, ICM_BACKWARD); if (bStatus) { ColorRet = NewColor; } } }
return(ColorRet); }
/******************************Public*Routine******************************\
* GetDeviceCaps * * We store the device caps for primary display dc and its compatible memory dcs * in the shared handle table. * * for printer dcs and meta dcs, we cache the dev info in the LDC structure. * * Fri 07-Jun-1991 18:01:50 -by- Charles Whitmer [chuckwh] * Wrote it. \**************************************************************************/
int APIENTRY GetDeviceCaps(HDC hdc,int iCap) { BOOL bRet = FALSE; PDEVCAPS pCachedDevCaps = NULL;
FIXUP_HANDLE(hdc);
if (IS_ALTDC_TYPE(hdc)) { PLDC pldc;
// For the 16-bit metafile DC, returns only technology. return 0 for win3.1 compat.
if (IS_METADC16_TYPE(hdc)) return(iCap == TECHNOLOGY ? DT_METAFILE : 0);
DC_PLDC(hdc,pldc,bRet);
if (!(pldc->fl & LDC_CACHED_DEVCAPS)) { bRet = NtGdiGetDeviceCapsAll (hdc, &pldc->DevCaps);
if (bRet) { pCachedDevCaps = &pldc->DevCaps; pldc->fl |= LDC_CACHED_DEVCAPS; } } else { pCachedDevCaps = &pldc->DevCaps; bRet = TRUE; } } else { PDC_ATTR pDcAttr;
PSHARED_GET_VALIDATE(pDcAttr,hdc,DC_TYPE);
if (pDcAttr) { ULONG fl = pDcAttr->ulDirty_;
if (!(fl & DC_PRIMARY_DISPLAY)) { return(NtGdiGetDeviceCaps(hdc,iCap)); } else { pCachedDevCaps = pGdiDevCaps; bRet = TRUE; } } }
if (!bRet) { GdiSetLastError(ERROR_INVALID_PARAMETER); return (0); }
// actual code - copied from gre\miscgdi.cxx
switch (iCap) { case DRIVERVERSION: // Version = 0100h for now
return(pCachedDevCaps->ulVersion);
case TECHNOLOGY: // Device classification
return(pCachedDevCaps->ulTechnology);
case HORZSIZE: // Horizontal size in millimeters
return(pCachedDevCaps->ulHorzSizeM);
case VERTSIZE: // Vertical size in millimeters
return(pCachedDevCaps->ulVertSizeM);
case HORZRES: // Horizontal width in pixels
return(pCachedDevCaps->ulHorzRes);
case VERTRES: // Vertical height in pixels
return(pCachedDevCaps->ulVertRes);
case BITSPIXEL: // Number of bits per pixel
return(pCachedDevCaps->ulBitsPixel);
case PLANES: // Number of planes
return(pCachedDevCaps->ulPlanes);
case NUMBRUSHES: // Number of brushes the device has
return(-1);
case NUMPENS: // Number of pens the device has
return(pCachedDevCaps->ulNumPens);
case NUMMARKERS: // Number of markers the device has
return(0);
case NUMFONTS: // Number of fonts the device has
return(pCachedDevCaps->ulNumFonts);
case NUMCOLORS: // Number of colors in color table
return(pCachedDevCaps->ulNumColors);
case PDEVICESIZE: // Size required for the device descriptor
return(0);
case CURVECAPS: // Curves capabilities
return(CC_CIRCLES | CC_PIE | CC_CHORD | CC_ELLIPSES | CC_WIDE | CC_STYLED | CC_WIDESTYLED | CC_INTERIORS | CC_ROUNDRECT);
case LINECAPS: // Line capabilities
return(LC_POLYLINE | LC_MARKER | LC_POLYMARKER | LC_WIDE | LC_STYLED | LC_WIDESTYLED | LC_INTERIORS);
case POLYGONALCAPS: // Polygonal capabilities
return(PC_POLYGON | PC_RECTANGLE | PC_WINDPOLYGON | PC_TRAPEZOID | PC_SCANLINE | PC_WIDE | PC_STYLED | PC_WIDESTYLED | PC_INTERIORS);
case TEXTCAPS: // Text capabilities
return(pCachedDevCaps->ulTextCaps);
case CLIPCAPS: // Clipping capabilities
return(CP_RECTANGLE);
case RASTERCAPS: // Bitblt capabilities
return(pCachedDevCaps->ulRasterCaps);
case SHADEBLENDCAPS: // shade and blend capabilities
return(pCachedDevCaps->ulShadeBlendCaps);
case ASPECTX: // Length of X leg
return(pCachedDevCaps->ulAspectX);
case ASPECTY: // Length of Y leg
return(pCachedDevCaps->ulAspectY);
case ASPECTXY: // Length of hypotenuse
return(pCachedDevCaps->ulAspectXY);
case LOGPIXELSX: // Logical pixels/inch in X
return(pCachedDevCaps->ulLogPixelsX);
case LOGPIXELSY: // Logical pixels/inch in Y
return(pCachedDevCaps->ulLogPixelsY);
case SIZEPALETTE: // # entries in physical palette
return(pCachedDevCaps->ulSizePalette);
case NUMRESERVED: // # reserved entries in palette
return(20);
case COLORRES: return(pCachedDevCaps->ulColorRes);
case PHYSICALWIDTH: // Physical Width in device units
return(pCachedDevCaps->ulPhysicalWidth);
case PHYSICALHEIGHT: // Physical Height in device units
return(pCachedDevCaps->ulPhysicalHeight);
case PHYSICALOFFSETX: // Physical Printable Area x margin
return(pCachedDevCaps->ulPhysicalOffsetX);
case PHYSICALOFFSETY: // Physical Printable Area y margin
return(pCachedDevCaps->ulPhysicalOffsetY);
case VREFRESH: // Vertical refresh rate of the device
return(pCachedDevCaps->ulVRefresh);
case DESKTOPHORZRES: // Width of entire virtual desktop
return(pCachedDevCaps->ulDesktopHorzRes);
case DESKTOPVERTRES: // Height of entire virtual desktop
return(pCachedDevCaps->ulDesktopVertRes);
case BLTALIGNMENT: // Preferred blt alignment
return(pCachedDevCaps->ulBltAlignment);
case COLORMGMTCAPS: // Color Management capabilities
return(pCachedDevCaps->ulColorManagementCaps);
default: return(0); }
}
/******************************Public*Routine******************************\
* GetDeviceCapsP * * Private version to get HORSIZE and VERTSIZE in micrometers * Copied from GetDeviceCaps * * \**************************************************************************/ int GetDeviceCapsP(HDC hdc,int iCap) { BOOL bRet = FALSE; PDEVCAPS pCachedDevCaps = NULL;
FIXUP_HANDLE(hdc);
if (IS_ALTDC_TYPE(hdc)) { PLDC pldc;
DC_PLDC(hdc,pldc,bRet);
if (!(pldc->fl & LDC_CACHED_DEVCAPS)) { bRet = NtGdiGetDeviceCapsAll (hdc, &pldc->DevCaps);
if (bRet) { pCachedDevCaps = &pldc->DevCaps; pldc->fl |= LDC_CACHED_DEVCAPS; } } else { pCachedDevCaps = &pldc->DevCaps; bRet = TRUE; } } else { PDC_ATTR pDcAttr;
PSHARED_GET_VALIDATE(pDcAttr,hdc,DC_TYPE);
if (pDcAttr) { ULONG fl = pDcAttr->ulDirty_;
if (!(fl & DC_PRIMARY_DISPLAY)) { return(NtGdiGetDeviceCaps(hdc,iCap)); } else { pCachedDevCaps = pGdiDevCaps; bRet = TRUE; } } }
if (!bRet) { GdiSetLastError(ERROR_INVALID_PARAMETER); return (0); }
// actual code - copied from gre\miscgdi.cxx
switch (iCap) { case HORZSIZEP: // Horizontal size
return(pCachedDevCaps->ulHorzSize);
case VERTSIZEP: // Vertical size
return(pCachedDevCaps->ulVertSize);
default: return(0); }
}
/******************************Public*Routine******************************\
* GetNearestColor * * * * Client side stub. * * * * Fri 07-Jun-1991 18:01:50 -by- Charles Whitmer [chuckwh] * * Wrote it. * \**************************************************************************/
COLORREF APIENTRY GetNearestColor(HDC hdc,COLORREF color) { FIXUP_HANDLE(hdc);
return(NtGdiGetNearestColor(hdc,color)); }
/******************************Public*Routine******************************\
* GetArcDirection * * Client side stub. * * Fri 09-Apr-1992 -by- J. Andrew Goossen [andrewgo] * Wrote it. \**************************************************************************/
int APIENTRY GetArcDirection(HDC hdc) { FIXUP_HANDLE(hdc);
return(GetDCDWord(hdc,DDW_ARCDIRECTION,0)); }
/******************************Public*Routine******************************\
* GetMiterLimit * * Client side stub. * * Fri 09-Apr-1992 -by- J. Andrew Goossen [andrewgo] * Wrote it. \**************************************************************************/
int APIENTRY GetMiterLimit(HDC hdc, PFLOAT peMiterLimit) { FIXUP_HANDLE(hdc);
return(NtGdiGetMiterLimit(hdc,FLOATPTRARG(peMiterLimit))); }
/******************************Public*Routine******************************\
* GetSystemPaletteUse * * * * Client side stub. * * * * Fri 07-Jun-1991 18:01:50 -by- Charles Whitmer [chuckwh] * * Wrote it. * \**************************************************************************/
UINT APIENTRY GetSystemPaletteUse(HDC hdc) { FIXUP_HANDLE(hdc);
return(NtGdiGetSystemPaletteUse(hdc)); }
/******************************Public*Routine******************************\
* GetClipBox * * * * Client side stub. * * * * Fri 07-Jun-1991 18:01:50 -by- Charles Whitmer [chuckwh] * * Wrote it. * \**************************************************************************/
int APIENTRY GetClipBox(HDC hdc,LPRECT prcl) { FIXUP_HANDLE(hdc);
return(NtGdiGetAppClipBox(hdc,prcl)); }
/******************************Public*Routine******************************\
* * BOOL APIENTRY GetTextMetrics(HDC hdc,LPTEXTMETRIC ptm) * * calls to the unicode version * * History: * 21-Aug-1991 -by- Bodin Dresevic [BodinD] * Wrote it. \**************************************************************************/
BOOL APIENTRY GetTextMetricsA(HDC hdc,LPTEXTMETRICA ptm) { PDC_ATTR pDcAttr; BOOL bRet = FALSE;
FIXUP_HANDLE(hdc);
PSHARED_GET_VALIDATE(pDcAttr,hdc,DC_TYPE);
if (pDcAttr) { CFONT * pcf; TMW_INTERNAL tmw;
ASSERTGDI(pDcAttr->hlfntNew,"GetTextMetricsW - hf is NULL\n");
ENTERCRITICALSECTION(&semLocal);
pcf = pcfLocateCFONT(hdc,pDcAttr,0,(PVOID)NULL,0, TRUE);
bRet = bGetTextMetricsWInternal(hdc,&tmw,sizeof(tmw),pcf);
// pcfLocateCFONT added a reference so now we need to remove it
if (pcf) { DEC_CFONT_REF(pcf); }
LEAVECRITICALSECTION(&semLocal);
if (bRet) { vTextMetricWToTextMetric(ptm, &tmw); } }
return(bRet); }
/******************************Public*Routine******************************\
* * BOOL APIENTRY GetTextMetricsW(HDC hdc,LPTEXTMETRICW ptmw) * * History: * 21-Aug-1991 -by- Bodin Dresevic [BodinD] * Wrote it. \**************************************************************************/
BOOL APIENTRY GetTextMetricsW(HDC hdc,LPTEXTMETRICW ptmw) { PDC_ATTR pDcAttr; BOOL bRet = FALSE;
FIXUP_HANDLE(hdc);
PSHARED_GET_VALIDATE(pDcAttr,hdc,DC_TYPE); if (pDcAttr) { CFONT * pcf;
ASSERTGDI(pDcAttr->hlfntNew,"GetTextMetricsW - hf is NULL\n");
ENTERCRITICALSECTION(&semLocal);
pcf = pcfLocateCFONT(hdc,pDcAttr,0,(PVOID) NULL,0, TRUE);
bRet = bGetTextMetricsWInternal(hdc,(TMW_INTERNAL *)ptmw,sizeof(TEXTMETRICW),pcf);
// pcfLocateCFONT added a reference so now we need to remove it
if (pcf) { DEC_CFONT_REF(pcf); }
LEAVECRITICALSECTION(&semLocal); }
return(bRet); }
/******************************Public*Routine******************************\
* * BOOL APIENTRY GetTextMetricsW(HDC hdc,LPTEXTMETRICW ptmw) * * History: * 21-Aug-1991 -by- Bodin Dresevic [BodinD] * Wrote it. \**************************************************************************/
BOOL bGetTextMetricsWInternal( HDC hdc, TMW_INTERNAL *ptmw, int cjTM, CFONT *pcf ) { BOOL bRet = FALSE;
if (ptmw) { // if no pcf or we havn't cached the metrics
if ((pcf == NULL) || !(pcf->fl & CFONT_CACHED_METRICS)) { TMW_INTERNAL tmw; PDC_ATTR pDcAttr;
PSHARED_GET_VALIDATE(pDcAttr,hdc,DC_TYPE);
bRet = NtGdiGetTextMetricsW(hdc,&tmw,sizeof(tmw));
if (bRet) { memcpy(ptmw,&tmw,cjTM);
if (pcf) { // we succeeded and we have a pcf so cache the data
pcf->tmw = tmw;
pcf->fl |= CFONT_CACHED_METRICS; } } } else { memcpy(ptmw,&pcf->tmw,cjTM); bRet = TRUE; } }
return(bRet); }
/******************************Public*Routine******************************\
* GetTextExtentPoint32A (hdc,psz,c,psizl) * * GetTextExtentPointA (hdc,psz,c,psizl) * * * * Computes the text extent. The new 32 bit version returns the "correct" * * extent without an extra per for bitmap simulations. The other is * * Windows 3.1 compatible. Both just set a flag and pass the call to * * bGetTextExtentA. * * * * History: * * Thu 14-Jan-1993 04:11:26 -by- Charles Whitmer [chuckwh] * * Added code to compute it on the client side. * * * * 07-Aug-1991 -by- Bodin Dresevic [BodinD] * * Wrote it. * \**************************************************************************/
// not in kernel, it is ok to do this much on the stack:
#define CAPTURE_STRING_SIZE 130
BOOL GetTextExtentPointAInternal(HDC hdc,LPCSTR psz,int c,LPSIZE psizl, FLONG fl) { CFONT *pcf; INT bRet; PWSZ pwszCapt; PDC_ATTR pDcAttr; DWORD dwCP; WCHAR awcCaptureBuffer[CAPTURE_STRING_SIZE];
FIXUP_HANDLE(hdc);
if (c <= 0) { // empty string, just return 0 for the extent
if (c == 0) { psizl->cx = 0; psizl->cy = 0; bRet = TRUE; } else { GdiSetLastError(ERROR_INVALID_PARAMETER); bRet = FALSE; } return(bRet); }
PSHARED_GET_VALIDATE(pDcAttr,hdc,DC_TYPE); if (!pDcAttr) { GdiSetLastError(ERROR_INVALID_PARAMETER); bRet = FALSE; return(bRet); }
dwCP = GET_CODE_PAGE(hdc, pDcAttr);
if(guintDBCScp == dwCP) { QueryFontAssocStatus();
if(fFontAssocStatus && ((c == 1) || ((c == 2 && *(psz) && *((LPCSTR)(psz + 1)) == '\0')))) { //
// If this function is called with only 1 char, and font association
// is enabled, we should forcely convert the chars to Unicode with
// codepage 1252.
// This is for enabling to output Latin-1 chars ( > 0x80 in Ansi codepage )
// Because, normally font association is enabled, we have no way to output
// those charactres, then we provide the way, if user call TextOutA() with
// A character and ansi font, we tempotary disable font association.
// This might be Windows 3.1 (Korean/Taiwanese) version compatibility..
//
dwCP = 1252; } }
if((dwCP == CP_ACP) || (dwCP == guintAcp) || (dwCP == guintDBCScp) ) { #ifdef LANGPACK
if (!gbLpk || (*fpLpkUseGDIWidthCache)(hdc, psz, c, pDcAttr->lTextAlign , FALSE)) { #endif
ENTERCRITICALSECTION(&semLocal);
pcf = pcfLocateCFONT(hdc,pDcAttr,0,(PVOID)psz,c,TRUE); if (pcf != NULL) { BOOL bExit = TRUE;
if(dwCP == guintDBCScp) { if (pcf->wd.sDBCSInc) // dbcs fixed pitch base font
{ bRet = bComputeTextExtentDBCS(pDcAttr,pcf,psz,c,fl,psizl); } else if (!bIsDBCSString(psz,c)) { // linked case, base font is a latin font, but linked font
// perhaps is a FE font. We know that base font is a latin font
// because for FE proportional fonts we would never create pcf.
// We are looking for this special case when the application asked
// for Latin Face Name in the logfont, and a FE charset, but the string
// passed in lackily does not contain DBCS glyphs.
bRet = bComputeTextExtent(pDcAttr,pcf,(PVOID) psz,c,fl,psizl,TRUE); } else { bExit = FALSE; } } else { bRet = bComputeTextExtent(pDcAttr,pcf,(PVOID) psz,c,fl,psizl,TRUE); }
DEC_CFONT_REF(pcf);
if(bExit) { LEAVECRITICALSECTION(&semLocal); return(bRet); } }
LEAVECRITICALSECTION(&semLocal); #ifdef LANGPACK
} #endif
}
// Allocate the string buffer
if (c <= CAPTURE_STRING_SIZE) { pwszCapt = awcCaptureBuffer; } else { pwszCapt = LOCALALLOC(c * sizeof(WCHAR)); }
if (pwszCapt) {
c = MultiByteToWideChar(dwCP, 0, psz,c, pwszCapt, c*sizeof(WCHAR));
if (c) { #ifdef LANGPACK
if(gbLpk) { bRet = (*fpLpkGetTextExtentExPoint)(hdc, pwszCapt, c, -1, NULL, NULL, psizl, fl, 0); } else #endif
bRet = NtGdiGetTextExtent(hdc, (LPWSTR)pwszCapt, c, psizl, fl); } else { GdiSetLastError(ERROR_INVALID_PARAMETER); bRet = FALSE; }
if (pwszCapt != awcCaptureBuffer) LOCALFREE(pwszCapt); } else { GdiSetLastError(ERROR_NOT_ENOUGH_MEMORY); bRet = FALSE; }
return(bRet); }
BOOL APIENTRY GetTextExtentPointA(HDC hdc,LPCSTR psz,int c,LPSIZE psizl) { return GetTextExtentPointAInternal(hdc,psz,c,psizl,GGTE_WIN3_EXTENT); }
BOOL APIENTRY GetTextExtentPoint32A(HDC hdc,LPCSTR psz,int c,LPSIZE psizl) { return GetTextExtentPointAInternal(hdc,psz,c,psizl,0); }
/******************************Public*Routine******************************\
* * DWORD WINAPI GetCharacterPlacementA * * Effects: * * Warnings: * * History: * 27-Jul-1995 -by- Bodin Dresevic [BodinD] * Wrote it. \**************************************************************************/
DWORD WINAPI GetCharacterPlacementA ( HDC hdc, LPCSTR psz, int nCount, int nMaxExtent, LPGCP_RESULTSA pgcpa, DWORD dwFlags ) { #define GCP_GLYPHS 80
WCHAR *pwsz = NULL; WCHAR awc[GCP_GLYPHS]; GCP_RESULTSW gcpw; DWORD dwRet; BOOL bOk = TRUE; int nBuffer; SIZE size; DWORD dwCP;
FIXUP_HANDLE(hdc);
size.cx = size.cy = 0;
// nMaxExtent == -1 means that there is no MaxExtent
if (!psz || (nCount <= 0) || ((nMaxExtent < 0) && (nMaxExtent != -1))) { WARNING("gdi!_GetCharactherPlacementA, bad parameters \n"); GdiSetLastError(ERROR_INVALID_PARAMETER); return 0; }
if (!pgcpa) { // just call GetTextExtentA, can usually be done on the client side
if (!GetTextExtentPointA(hdc, psz, nCount, &size)) { WARNING("GetCharacterPlacementW, GetTextExtentPointA failed\n"); return 0; }
// now backwards compatible win95 hack, chop off 32 bit values to 16 bits
return (DWORD)((USHORT)size.cx) | (DWORD)(size.cy << 16); }
// chop off nCount, win95 does it
if (nCount > (int)pgcpa->nGlyphs) nCount = (int)pgcpa->nGlyphs;
// unicode string buffer will at least be this many WCHAR's long:
nBuffer = nCount;
// now go on to compute the size of the GCP_RESULTSW that is required
// to receive the results. If lpOutString is not NULL the structures
// will have different pointers else they will be the same.
gcpw.lpOrder = pgcpa->lpOrder ; gcpw.lpDx = pgcpa->lpDx ; gcpw.lpCaretPos = pgcpa->lpCaretPos; gcpw.lpClass = pgcpa->lpClass ; gcpw.lpGlyphs = pgcpa->lpGlyphs ; gcpw.nGlyphs = pgcpa->nGlyphs ; gcpw.nMaxFit = pgcpa->nMaxFit ;
if (pgcpa->lpOutString) { nBuffer += nBuffer; // take into account space for gcpw.lpOutString
} else { gcpw.lpOutString = NULL; gcpw.lStructSize = pgcpa->lStructSize; }
// now allocate memory (if needed) for the unicode string and for
// gcpw.lpOutString if needed.
if (nBuffer <= GCP_GLYPHS) pwsz = awc; else pwsz = LOCALALLOC(nBuffer * sizeof(WCHAR));
if (pwsz) { if (pgcpa->lpOutString) { gcpw.lpOutString = &pwsz[nCount];
// we have replaced the ansi string by unicode string, this adds
// nCount bytes to the size of the structure.
gcpw.lStructSize = pgcpa->lStructSize + nCount; }
// convert Ansi To Unicode based on the code page of the font selected in DC
if ( gcpw.nGlyphs = MultiByteToWideChar((dwCP = GetCodePage(hdc)), 0, psz, nCount, pwsz, nCount*sizeof(WCHAR)) ) {
// If this is a DBCS font then we need to patch up the DX array since
// there will be two DX values for each DBCS character. It is okay
// to do this in place since GetCharacterPlacement modifies the DX
// array anyway.
if((dwFlags & GCP_JUSTIFYIN) && (gcpw.lpDx) && IS_ANY_DBCS_CODEPAGE(dwCP)) { INT *pDxNew, *pDxOld; const char *pDBCSString;
for(pDxNew = pDxOld = gcpw.lpDx, pDBCSString = psz; pDBCSString < psz + nCount; pDBCSString++ ) { if(IsDBCSLeadByteEx(dwCP,*pDBCSString)) { pDBCSString++; pDxOld++; } *pDxNew++ = *pDxOld++; } }
#ifdef LANGPACK
if (gbLpk) { // If the LPK is loaded then pass the caller nGlyphs because it may generate
// Glyphs more than nCount.
gcpw.nGlyphs = pgcpa->nGlyphs; dwRet = (*fpLpkGetCharacterPlacement)(hdc, pwsz, nCount,nMaxExtent, &gcpw, dwFlags, 0); } else #endif
{ dwRet = NtGdiGetCharacterPlacementW(hdc,pwsz,nCount,nMaxExtent, &gcpw, dwFlags); }
if (dwRet) { // copy out the data.... we use the original value of nCount
// when specifying an output buffer size for the lpOutString buffer
// since nCount on return will be Unicode character count which
// may not be the same as DBCS character count
int nOriginalCount = nCount;
pgcpa->nGlyphs = nCount = gcpw.nGlyphs; pgcpa->nMaxFit = gcpw.nMaxFit; if (pgcpa->lpOutString) { if ( !WideCharToMultiByte( (UINT)dwCP, // UINT CodePage
0, // DWORD dwFlags
gcpw.lpOutString, // LPWSTR lpWideCharStr
gcpw.nMaxFit, // int cchWideChar
pgcpa->lpOutString, // LPSTR lpMultiByteStr
nOriginalCount, // int cchMultiByte
NULL, // LPSTR lpDefaultChar
NULL) // LPBOOL lpUsedDefaultChar
) { bOk = FALSE; } } } else { bOk = FALSE; } } else { GdiSetLastError(ERROR_INVALID_PARAMETER); bOk = FALSE; }
if (pwsz != awc) LOCALFREE(pwsz); } else { bOk = FALSE; }
return (bOk ? dwRet : 0); }
/******************************Public*Routine******************************\
* * DWORD WINAPI GetCharacterPlacementW * look at gdi32.def, just points to NtGdiGetCharacterPlacementW * * History: * 26-Jul-1995 -by- Bodin Dresevic [BodinD] * Wrote it. \**************************************************************************/
#if LANGPACK
DWORD WINAPI GetCharacterPlacementW ( HDC hdc, LPCWSTR pwsz, int nCount, int nMaxExtent, LPGCP_RESULTSW pgcpw, DWORD dwFlags ) { SIZE size;
FIXUP_HANDLE(hdc);
size.cx = size.cy = 0;
// nMaxExtent == -1 means that there is no MaxExtent
if (!pwsz || (nCount <= 0) || ((nMaxExtent < 0) && (nMaxExtent != -1))) { WARNING("gdi!_GetCharactherPlacementW, bad parameters \n"); GdiSetLastError(ERROR_INVALID_PARAMETER); return 0; }
if (!pgcpw) { // just call GetTextExtentW, can usually be done on the client side
if (!GetTextExtentPointW(hdc, pwsz, nCount, &size)) { WARNING("GetCharacterPlacementW, GetTextExtentPointW failed\n"); return 0; }
// now backwards compatible win95 hack, chop off 32 bit values to 16 bits
return (DWORD)((USHORT)size.cx) | (DWORD)(size.cy << 16); }
// chop off nCount, win95 does it
if (nCount > (int)pgcpw->nGlyphs) nCount = (int)pgcpw->nGlyphs;
if(gbLpk) { return((*fpLpkGetCharacterPlacement)(hdc,pwsz,nCount,nMaxExtent,pgcpw, dwFlags,-1)); } else {
return NtGdiGetCharacterPlacementW(hdc, (LPWSTR) pwsz, nCount, nMaxExtent, pgcpw, dwFlags); } }
#endif
/******************************Public*Routine******************************\
* BOOL bGetCharWidthA * * * * Client side stub for the various GetCharWidth*A functions. * * * * History: * * Sat 16-Jan-1993 03:08:42 -by- Charles Whitmer [chuckwh] * * Added code to do it on the client side. * * * * 28-Aug-1991 -by- Bodin Dresevic [BodinD] * * Wrote it. * \**************************************************************************/
#define GCW_WIN3_INT (GCW_WIN3 | GCW_INT)
#define GCW_WIN3_16INT (GCW_WIN3 | GCW_INT | GCW_16BIT)
#define GCW_SIZE(fl) ((fl >> 16) & 0xffff)
#define GCWFL(fltype,szType) (fltype | (sizeof(szType) << 16))
BOOL bGetCharWidthA ( HDC hdc, UINT iFirst, UINT iLast, ULONG fl, PVOID pvBuf ) { PDC_ATTR pDcAttr; LONG cwc; CFONT *pcf = NULL; PUCHAR pch; PWCHAR pwc; BOOL bRet = FALSE; ULONG cjWidths; DWORD dwCP; BOOL bDBCSCodePage; WCHAR awc[MAX_PATH]; PVOID pvResultBuffer;
PSHARED_GET_VALIDATE(pDcAttr,hdc,DC_TYPE);
if (!pDcAttr) { GdiSetLastError(ERROR_INVALID_PARAMETER); return(bRet); }
dwCP = GET_CODE_PAGE(hdc, pDcAttr);
bDBCSCodePage = IS_ANY_DBCS_CODEPAGE(dwCP);
// do parameter validation, check that in chars are indeed ascii
if ((bDBCSCodePage && !IsValidDBCSRange(iFirst,iLast)) || (!bDBCSCodePage && ((iFirst > iLast) || (iLast & 0xffffff00))) || (pvBuf == NULL)) { WARNING("gdi!_bGetCharWidthA parameters \n"); GdiSetLastError(ERROR_INVALID_PARAMETER); return(bRet); } cwc = (LONG)(iLast - iFirst + 1);
ENTERCRITICALSECTION(&semLocal);
if ((dwCP == CP_ACP) || (dwCP == guintAcp) || (dwCP == guintDBCScp) )
{ pcf = pcfLocateCFONT(hdc,pDcAttr,iFirst,(PVOID) NULL,(UINT) cwc, TRUE); }
if (pcf != (CFONT *) NULL) { BOOL bExit = TRUE;
if(dwCP == guintDBCScp) { if (pcf->wd.sDBCSInc) // dbcs fixed pitch base font
{ bRet = bComputeCharWidthsDBCS (pcf,iFirst,iLast,fl,pvBuf); } else if (iLast < 0x80) { // linked case, base font is a latin font, but linked font
// perhaps is a FE font. We know that base font is a latin font
// because for FE proportional fonts we would never create pcf.
// We are looking for this special case when the application asked
// for Latin Face Name in the logfont, and a FE charset, but the string
// passed in lackily does not contain DBCS glyphs.
bRet = bComputeCharWidths(pcf,iFirst,iLast,fl,pvBuf); } else { bExit = FALSE; } } else { bRet = bComputeCharWidths(pcf,iFirst,iLast,fl,pvBuf); }
DEC_CFONT_REF(pcf);
if(bExit) { LEAVECRITICALSECTION(&semLocal); return(bRet); } }
LEAVECRITICALSECTION(&semLocal);
// Let the server do it.
cjWidths = cwc * GCW_SIZE(fl);
//
// Non kernel mode call
//
// What if user's buffer is set up for 16 bit return?? Then we need
// to allocate buffer for 32 bit date and convert to user's buffer after
// the call
pvResultBuffer = pvBuf;
if (fl & GCW_16BIT) { // User's buffer is 16 bit, make 32 a bit
// temp buffer
pvResultBuffer = LOCALALLOC(cwc * sizeof(LONG)); if (pvResultBuffer == NULL) { GdiSetLastError(ERROR_NOT_ENOUGH_MEMORY); return(bRet); } }
// Kernel mode, use users buffer for return data
// convert to unicode
if(bDBCSCodePage) { bRet = bSetUpUnicodeStringDBCS(iFirst, iLast, (PUCHAR) pvResultBuffer, awc, dwCP, GetCurrentDefaultChar(hdc)); } else { bRet = bSetUpUnicodeString(iFirst,iLast,pvResultBuffer,awc,dwCP); }
if(bRet) { bRet = NtGdiGetCharWidthW(hdc, 0, cwc, awc, (LONG)(fl & (GCW_INT | GCW_WIN3)), pvResultBuffer); }
if (bRet) { //
// May need to convert to 16 bit user buffer
//
if (fl & GCW_16BIT) {
PWORD pw = pvBuf; PDWORD pi = (int *)pvResultBuffer; PDWORD piEnd = pi + cwc;
ASSERTGDI(pvResultBuffer != pvBuf, "Local buffer not allocated properly");
while (pi != piEnd) { *pw++ = (WORD)(*pi++); }
LOCALFREE(pvResultBuffer);
} }
return(bRet); }
/******************************Public*Routine******************************\
* * BOOL APIENTRY GetCharWidthA * * History: * 25-Feb-1992 -by- Bodin Dresevic [BodinD] * Wrote it. \**************************************************************************/
BOOL APIENTRY GetCharWidthA ( IN HDC hdc, IN UINT iFirst, IN UINT iLast, OUT LPINT lpWidths ) { FIXUP_HANDLE(hdc); return bGetCharWidthA(hdc,iFirst,iLast,GCWFL(GCW_WIN3_INT,int),(PVOID)lpWidths); }
BOOL APIENTRY GetCharWidth32A ( IN HDC hdc, IN UINT iFirst, IN UINT iLast, OUT LPINT lpWidths ) { FIXUP_HANDLE(hdc);
return bGetCharWidthA(hdc,iFirst,iLast,GCWFL(GCW_INT,int),(PVOID)lpWidths); }
/******************************Public*Routine******************************\
* * GetCharWidthFloatA * * History: * 22-Feb-1992 -by- Bodin Dresevic [BodinD] * Wrote it. \**************************************************************************/
BOOL APIENTRY GetCharWidthFloatA ( IN HDC hdc, IN UINT iFirst, IN UINT iLast, OUT PFLOAT lpWidths ) { FIXUP_HANDLE(hdc); return bGetCharWidthA(hdc,iFirst,iLast,GCWFL(0,FLOAT),(PVOID)lpWidths); }
/******************************Public*Routine******************************\
* * BOOL bGetCharWidthW * * GetCharWidthW and GetCharWidthFloatW * * History: * 28-Aug-1991 -by- Bodin Dresevic [BodinD] * Wrote it. \**************************************************************************/
BOOL bGetCharWidthW ( HDC hdc, UINT iFirst, // unicode value
UINT iLast, // unicode value
ULONG fl, PVOID pvBuf ) { LONG cwc; BOOL bRet = FALSE;
// do parameter validation, check that in chars are indeed unicode
if ((pvBuf == (PVOID)NULL) || (iFirst > iLast) || (iLast & 0xffff0000)) { WARNING("gdi!_bGetCharWidthW parameters \n"); GdiSetLastError(ERROR_INVALID_PARAMETER); return(bRet); }
cwc = (LONG)(iLast - iFirst + 1);
if(iLast < 0x80) { CFONT *pcf = NULL; PDC_ATTR pDcAttr; DWORD dwCP;
PSHARED_GET_VALIDATE(pDcAttr,hdc,DC_TYPE);
if (!pDcAttr) { GdiSetLastError(ERROR_INVALID_PARAMETER); return(FALSE); }
dwCP = GET_CODE_PAGE(hdc, pDcAttr);
ENTERCRITICALSECTION(&semLocal);
if ((dwCP == CP_ACP) || (dwCP == guintAcp) || (dwCP == guintDBCScp) )
{ pcf = pcfLocateCFONT(hdc,pDcAttr,iFirst,(PVOID) NULL,(UINT) cwc, TRUE); }
if (pcf != NULL) { bRet = bComputeCharWidths(pcf,iFirst,iLast,fl,pvBuf);
DEC_CFONT_REF(pcf);
if(bRet) { LEAVECRITICALSECTION(&semLocal); return (bRet); } }
LEAVECRITICALSECTION(&semLocal); }
//
// kernel mode
//
bRet = NtGdiGetCharWidthW( hdc, iFirst, cwc, NULL, (LONG)(fl & (GCW_INT | GCW_WIN3)), pvBuf);
return(bRet);
}
/******************************Public*Routine******************************\
* * BOOL APIENTRY GetCharWidthFloatW * * History: * 22-Feb-1992 -by- Bodin Dresevic [BodinD] * Wrote it. \**************************************************************************/
BOOL APIENTRY GetCharWidthFloatW ( HDC hdc, UINT iFirst, UINT iLast, PFLOAT lpWidths ) { FIXUP_HANDLE(hdc); return bGetCharWidthW(hdc,iFirst,iLast,0,(PVOID)lpWidths); }
/******************************Public*Routine******************************\
* * BOOL APIENTRY GetCharWidthW * * History: * 25-Feb-1992 -by- Bodin Dresevic [BodinD] * Wrote it. \**************************************************************************/
BOOL APIENTRY GetCharWidthW ( HDC hdc, UINT iFirst, UINT iLast, LPINT lpWidths ) { FIXUP_HANDLE(hdc); return bGetCharWidthW(hdc,iFirst,iLast,GCW_WIN3_INT,(PVOID)lpWidths); }
BOOL APIENTRY GetCharWidth32W ( HDC hdc, UINT iFirst, UINT iLast, LPINT lpWidths ) { FIXUP_HANDLE(hdc); return bGetCharWidthW(hdc,iFirst,iLast,GCW_INT,(PVOID)lpWidths); }
/******************************Public*Routine******************************\
* * WINGDIAPI BOOL WINAPI GetCharWidthI(HDC, UINT, UINT, PWCHAR, LPINT); * * if pgi == NULL use the consecutive range * giFirst, giFirst + 1, ...., giFirst + cgi - 1 * * if pgi != NULL ignore giFirst and use cgi indices pointed to by pgi * * History: * 28-Aug-1996 -by- Bodin Dresevic [BodinD] * Wrote it. \**************************************************************************/
BOOL WINAPI GetCharWidthI( HDC hdc, UINT giFirst, UINT cgi, LPWORD pgi, LPINT piWidths ) { BOOL bRet = FALSE;
// do parameter validation
if (!piWidths || (!pgi && (giFirst & 0xffff0000))) { WARNING("gdi! GetCharWidthI parameters \n"); GdiSetLastError(ERROR_INVALID_PARAMETER); return(bRet); }
if (!cgi) return TRUE; // quick exit
// kernel mode
bRet = NtGdiGetCharWidthW( hdc, giFirst, cgi, (PWCHAR)pgi, (GCW_INT | GCW_GLYPH_INDEX), (PVOID)piWidths);
return bRet; }
/******************************Public*Routine******************************\
* * BOOL APIENTRY GetTextExtentPointW(HDC hdc,LPWSTR pwsz,DWORD cwc,LPSIZE psizl) * * * History: * 07-Aug-1991 -by- Bodin Dresevic [BodinD] * Wrote it. \**************************************************************************/
#define QUICK_BUFSIZE 0xFF
BOOL GetTextExtentPointWInternal( HDC hdc,LPCWSTR pwsz,int cwc,LPSIZE psizl, FLONG fl ) { WCHAR *pwc; CFONT *pcf; INT bRet; PDC_ATTR pDcAttr; BOOL bCache; INT i; WCHAR wcTest = 0; int ii = cwc;
FIXUP_HANDLE(hdc);
if (cwc <= 0) {
// empty string, just return 0 for the extent
if (cwc == 0) { psizl->cx = 0; psizl->cy = 0; return(TRUE); } else { GdiSetLastError(ERROR_INVALID_PARAMETER); return(FALSE); } }
// Let's see if we can take advantage of the ANSI client side GetTextExtent
// code. If we can convert everything from Unicode to ANSI by ignoring the
// high byte and it fits into our quick buffer then we can. In the future
// we will probably want to do a quick Unicode to ANSI conversion using
// something other than sign extension so we don't mess up non 1252 CP locales
// by making them go through the slow code all the time.
// We need to use this performance optimization if an LPK is installed
// and some condiditions are met (LTR text alignment, ..etc)
pwc = (WCHAR *) pwsz;
unroll_here: switch(ii) { default: wcTest |= pwc[9]; case 9: wcTest |= pwc[8]; case 8: wcTest |= pwc[7]; case 7: wcTest |= pwc[6]; case 6: wcTest |= pwc[5]; case 5: wcTest |= pwc[4]; case 4: wcTest |= pwc[3]; case 3: wcTest |= pwc[2]; case 2: wcTest |= pwc[1]; case 1: wcTest |= pwc[0]; }
if ((ii > 10) && !(wcTest & 0xFF80)) { ii -= 10; pwc += 10; goto unroll_here; }
if (!(wcTest & 0xFF80)) { PSHARED_GET_VALIDATE(pDcAttr,hdc,DC_TYPE); if (!pDcAttr) { GdiSetLastError(ERROR_INVALID_PARAMETER); return(FALSE); } #ifdef LANGPACK
if (!gbLpk || (*fpLpkUseGDIWidthCache)(hdc, (LPCSTR) pwsz,cwc, pDcAttr->lTextAlign , TRUE)) { #endif
ENTERCRITICALSECTION(&semLocal);
pcf = pcfLocateCFONT(hdc,pDcAttr,0,(PVOID)pwsz,cwc, FALSE);
if (pcf != NULL) { bRet = bComputeTextExtent(pDcAttr,pcf,(PVOID) pwsz,cwc,fl,psizl,FALSE);
DEC_CFONT_REF(pcf);
if(bRet) { LEAVECRITICALSECTION(&semLocal); return (bRet); } }
LEAVECRITICALSECTION(&semLocal); #ifdef LANGPACK
} #endif
}
#ifdef LANGPACK
if(gbLpk) { return(*fpLpkGetTextExtentExPoint)(hdc, pwsz, cwc, -1, NULL, NULL, psizl, fl, -1); } #endif
return NtGdiGetTextExtent(hdc, (LPWSTR)pwsz, cwc, psizl, fl);
}
BOOL APIENTRY GetTextExtentPointW(HDC hdc,LPCWSTR pwsz,int cwc,LPSIZE psizl) { return GetTextExtentPointWInternal(hdc, pwsz, cwc, psizl, GGTE_WIN3_EXTENT); }
BOOL APIENTRY GetTextExtentPoint32W(HDC hdc,LPCWSTR pwsz,int cwc,LPSIZE psizl) { return GetTextExtentPointWInternal(hdc, pwsz, cwc, psizl, 0); }
/******************************Public*Routine******************************\
* * GetTextExtentPointI, index version * * History: * 28-Aug-1996 -by- Bodin Dresevic [BodinD] * Wrote it. \**************************************************************************/
BOOL APIENTRY GetTextExtentPointI(HDC hdc, LPWORD pgiIn, int cgi, LPSIZE psize) { return NtGdiGetTextExtent(hdc, (LPWSTR)pgiIn, cgi , psize, GGTE_GLYPH_INDEX); }
/******************************Public*Routine******************************\
* * GetFontUnicodeRanges(HDC, LPGLYPHSET) * * return Unicode content of the font. * * History: * 28-Aug-1996 -by- Bodin Dresevic [BodinD] * Wrote it. \**************************************************************************/
#if 0
DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET pgs) { return NtGdiGetFontUnicodeRanges(hdc, pgs); }
#endif
/******************************Public*Routine******************************\
* * GetGlyphIndicesA(HDC, LPCSTR, int, LPWORD, DWORD mode); * * cmap based conversion, if (mode) indicate that glyph is not supported in the * font by putting FFFF in the output array * * If successfull, the function returns the number of indicies in pgi buffer. * * History: * 28-Aug-1996 -by- Bodin Dresevic [BodinD] * Wrote it. \**************************************************************************/
DWORD WINAPI GetGlyphIndicesA( HDC hdc, LPCSTR psz, int c, LPWORD pgi, DWORD iMode) { DWORD dwRet = GDI_ERROR; PWSZ pwszCapt; PDC_ATTR pDcAttr; DWORD dwCP; WCHAR awcCaptureBuffer[CAPTURE_STRING_SIZE];
FIXUP_HANDLE(hdc);
if (c <= 0) { // empty string, just return 0 for the extent
if (c == 0) { dwRet = 0; } else { GdiSetLastError(ERROR_INVALID_PARAMETER); dwRet = GDI_ERROR; } return(dwRet); }
PSHARED_GET_VALIDATE(pDcAttr,hdc,DC_TYPE); if (!pDcAttr) { GdiSetLastError(ERROR_INVALID_PARAMETER); dwRet = GDI_ERROR; return dwRet; }
dwCP = GET_CODE_PAGE(hdc, pDcAttr);
if(guintDBCScp == dwCP) { QueryFontAssocStatus();
if(fFontAssocStatus && ((c == 1) || ((c == 2 && *(psz) && *((LPCSTR)(psz + 1)) == '\0')))) { //
// If this function is called with only 1 char, and font association
// is enabled, we should forcely convert the chars to Unicode with
// codepage 1252.
// This is for enabling to output Latin-1 chars ( > 0x80 in Ansi codepage )
// Because, normally font association is enabled, we have no way to output
// those charactres, then we provide the way, if user call TextOutA() with
// A character and ansi font, we tempotary disable font association.
// This might be Windows 3.1 (Korean/Taiwanese) version compatibility..
//
dwCP = 1252; } }
// Allocate the string buffer
if (c <= CAPTURE_STRING_SIZE) { pwszCapt = awcCaptureBuffer; } else { pwszCapt = LOCALALLOC(c * sizeof(WCHAR)); }
if (pwszCapt) {
c = MultiByteToWideChar(dwCP, 0, psz,c, pwszCapt, c*sizeof(WCHAR));
if (c) { dwRet = NtGdiGetGlyphIndicesW(hdc, (LPWSTR)pwszCapt, c, pgi, iMode); } else { GdiSetLastError(ERROR_INVALID_PARAMETER); dwRet = GDI_ERROR; }
if (pwszCapt != awcCaptureBuffer) LOCALFREE(pwszCapt); } else { GdiSetLastError(ERROR_NOT_ENOUGH_MEMORY); dwRet = GDI_ERROR; }
return dwRet; }
/******************************Public*Routine******************************\
* * GetGlyphIndicesW(HDC, LPCSTR, int, LPWORD, DWORD); * * cmap based conversion, if (mode) indicate that glyph is not supported in the * font by putting FFFF in the output array * * History: * 28-Aug-1996 -by- Bodin Dresevic [BodinD] * Wrote it. \**************************************************************************/
#if 0
DWORD WINAPI GetGlyphIndicesW( HDC hdc, LPCWSTR pwc, int cwc, LPWORD pgi, DWORD iMode) { return NtGdiGetGlyphIndicesW(hdc, pwc, cwc, pgi, iMode); }
#endif
/******************************Public*Routine******************************\
* * int APIENTRY GetTextFaceA(HDC hdc,int c,LPSTR psz) * * History: * 30-Aug-1991 -by- Bodin Dresevic [BodinD] * Wrote it. \**************************************************************************/
int APIENTRY GetTextFaceA(HDC hdc,int c,LPSTR psz) { ULONG cRet = 0; ULONG cbAnsi = 0;
FIXUP_HANDLE(hdc);
if ( (psz != (LPSTR) NULL) && (c <= 0) ) { WARNING("gdi!GetTextFaceA(): invalid parameter\n"); GdiSetLastError(ERROR_INVALID_PARAMETER); return cRet; }
{ //
// Kernel mode, allocate a buffer for WCAHR return
//
// WINBUG #82833 2-7-2000 bhouse Possible cleanup work in GetTextFaceA
// Old Comment:
// - This allocates a temp buffer, then NtGdi does it again
//
PWCHAR pwch = (PWCHAR)NULL;
if (c > 0) { pwch = (WCHAR *)LOCALALLOC(c * sizeof(WCHAR)); if (pwch == (WCHAR *)NULL) { WARNING("gdi!GetTextFaceA(): Memory allocation error\n"); cRet = 0; return(cRet); } }
cRet = NtGdiGetTextFaceW(hdc,c,(LPWSTR)pwch,FALSE);
if(cRet && (guintDBCScp != 0xFFFFFFFF) && !psz ) { WCHAR *pwcTmp;
// now we need to actually need to get the string for DBCS code pages
// so that we can compute the proper multi-byte length
if(pwcTmp = (WCHAR*)LOCALALLOC(cRet*sizeof(WCHAR))) { UINT cwTmp;
cwTmp = NtGdiGetTextFaceW(hdc,cRet,pwcTmp, FALSE);
RtlUnicodeToMultiByteSize(&cbAnsi,pwcTmp,cwTmp*sizeof(WCHAR)); LOCALFREE(pwcTmp); } else { WARNING("gdi!GetTextFaceA(): UNICODE to ANSI conversion failed\n"); cRet = 0; } } else { cbAnsi = cRet; }
//
// If successful and non-NULL buffer, convert back to ANSI.
//
if ( (cRet != 0) && (psz != (LPSTR) NULL) && (pwch != (WCHAR*)NULL)) {
if(!(cbAnsi = WideCharToMultiByte(CP_ACP,0,pwch,cRet,psz,c,NULL,NULL))) { WARNING("gdi!GetTextFaceA(): UNICODE to ANSI conversion failed\n"); cRet = 0; } }
if (pwch != (PWCHAR)NULL) { LOCALFREE(pwch); }
}
//
// return for user and kernel mode
//
return( ((cRet == 0 ) || (psz == NULL) || psz[cbAnsi-1] != 0 ) ? cbAnsi : cbAnsi-1 );
}
/******************************Public*Routine******************************\
* * DWORD APIENTRY GetTextFaceAliasW(HDC hdc,DWORD c,LPWSTR pwsz) * * History: * 24-Feb-1998 -by- Yung-Jen Tony Tsai [YungT] * Wrote it. \**************************************************************************/
int APIENTRY GetTextFaceAliasW(HDC hdc,int c,LPWSTR pwsz) { int cRet = 0;
FIXUP_HANDLE(hdc);
if ( (pwsz != (LPWSTR) NULL) && (c == 0) ) { WARNING("gdi!GetTextFaceAliasW(): invalid parameter\n"); GdiSetLastError(ERROR_INVALID_PARAMETER); return cRet; }
cRet = NtGdiGetTextFaceW(hdc,c,pwsz,TRUE);
return(cRet); }
/******************************Public*Routine******************************\
* * DWORD APIENTRY GetTextFaceW(HDC hdc,DWORD c,LPWSTR pwsz) * * History: * 13-Aug-1991 -by- Bodin Dresevic [BodinD] * Wrote it. \**************************************************************************/
int APIENTRY GetTextFaceW(HDC hdc,int c,LPWSTR pwsz) { int cRet = 0;
FIXUP_HANDLE(hdc);
if ( (pwsz != (LPWSTR) NULL) && (c <= 0) ) { WARNING("gdi!GetTextFaceW(): invalid parameter\n"); GdiSetLastError(ERROR_INVALID_PARAMETER); return cRet; }
cRet = NtGdiGetTextFaceW(hdc,c,pwsz,FALSE);
return(cRet); }
/******************************Public*Routine******************************\
* * vTextMetricWToTextMetricStrict (no char conversion) * * Effects: return FALSE if UNICODE chars have no ASCI equivalents * * * History: * 20-Aug-1991 -by- Bodin Dresevic [BodinD] * Wrote it. \**************************************************************************/
VOID FASTCALL vTextMetricWToTextMetricStrict ( LPTEXTMETRICA ptm, LPTEXTMETRICW ptmw ) {
ptm->tmHeight = ptmw->tmHeight ; // DWORD
ptm->tmAscent = ptmw->tmAscent ; // DWORD
ptm->tmDescent = ptmw->tmDescent ; // DWORD
ptm->tmInternalLeading = ptmw->tmInternalLeading ; // DWORD
ptm->tmExternalLeading = ptmw->tmExternalLeading ; // DWORD
ptm->tmAveCharWidth = ptmw->tmAveCharWidth ; // DWORD
ptm->tmMaxCharWidth = ptmw->tmMaxCharWidth ; // DWORD
ptm->tmWeight = ptmw->tmWeight ; // DWORD
ptm->tmOverhang = ptmw->tmOverhang ; // DWORD
ptm->tmDigitizedAspectX = ptmw->tmDigitizedAspectX ; // DWORD
ptm->tmDigitizedAspectY = ptmw->tmDigitizedAspectY ; // DWORD
ptm->tmItalic = ptmw->tmItalic ; // BYTE
ptm->tmUnderlined = ptmw->tmUnderlined ; // BYTE
ptm->tmStruckOut = ptmw->tmStruckOut ; // BYTE
ptm->tmPitchAndFamily = ptmw->tmPitchAndFamily ; // BYTE
ptm->tmCharSet = ptmw->tmCharSet ; // BYTE
}
VOID FASTCALL vTextMetricWToTextMetric ( LPTEXTMETRICA ptma, TMW_INTERNAL *ptmi ) { vTextMetricWToTextMetricStrict(ptma,&ptmi->tmw);
ptma->tmFirstChar = ptmi->tmdTmw.chFirst ; ptma->tmLastChar = ptmi->tmdTmw.chLast ; ptma->tmDefaultChar = ptmi->tmdTmw.chDefault; ptma->tmBreakChar = ptmi->tmdTmw.chBreak ; }
/******************************Public*Routine******************************\
* GetTextExtentExPointA * * History: * 06-Jan-1992 -by- Gilman Wong [gilmanw] * Wrote it. \**************************************************************************/
BOOL APIENTRY GetTextExtentExPointA ( HDC hdc, LPCSTR lpszString, int cchString, int nMaxExtent, LPINT lpnFit, LPINT lpnDx, LPSIZE lpSize ) { WCHAR *pwsz = NULL; WCHAR awc[GCP_GLYPHS]; INT aiDx[GCP_GLYPHS]; INT *pDx; BOOL bRet = FALSE; DWORD dwCP; BOOL bZeroSize = FALSE;
FIXUP_HANDLE(hdc);
// some parameter checking. In a single check we will both make sure that
// cchString is not negative and if positive, that it is not bigger than
// ULONG_MAX / (sizeof(ULONG) + sizeof(WCHAR)). This restriction is necessary
// for one of the memory allocations in ntgdi.c allocates
// cchString * (sizeof(ULONG) + sizeof(WCHAR)).
// Clearly, the result of this multiplication has to fit in ULONG for the
// alloc to make sense:
// also there is a validity check to be performed on nMaxExtent. -1 is the only
// legal negative value of nMaxExtent, this basically means
// that nMaxExtent can be ignored. All other negative values of nMaxExtent are
// not considered legal input.
if ( ((ULONG)cchString > (ULONG_MAX / (sizeof(ULONG)+sizeof(WCHAR)))) || (nMaxExtent < -1) ) { GdiSetLastError(ERROR_INVALID_PARAMETER); return bRet; }
if(cchString == 0) bZeroSize = TRUE;
// now allocate memory (if needed) for the unicode string if needed
if (cchString <= GCP_GLYPHS) { pwsz = awc; pDx = aiDx; } else { pwsz = LOCALALLOC((cchString+1) * (sizeof(WCHAR) + sizeof(INT))); pDx = (INT*) &pwsz[(cchString+1)&~1]; }
if (pwsz) { UINT cwcWideChars;
// convert Ansi To Unicode based on the code page of the font selected in DC
dwCP = GetCodePage(hdc); if( bZeroSize || ( cwcWideChars = MultiByteToWideChar(dwCP, 0, lpszString, cchString, pwsz, cchString*sizeof(WCHAR))) ) { BOOL bDBCSFont = IS_ANY_DBCS_CODEPAGE(dwCP) ? TRUE : FALSE;
if(bZeroSize){ cwcWideChars = 0; pwsz[0] = (WCHAR) 0x0; }
#ifdef LANGPACK
if(gbLpk) { bRet = (*fpLpkGetTextExtentExPoint)(hdc, pwsz, cwcWideChars, nMaxExtent, lpnFit, bDBCSFont ? pDx : lpnDx, lpSize, 0, 0); } else #endif
bRet = NtGdiGetTextExtentExW(hdc, pwsz, cwcWideChars, nMaxExtent, lpnFit, bDBCSFont ? pDx : lpnDx, lpSize, 0);
if (bDBCSFont && bRet) { // if this is a DBCS font then we need to make some adjustments
int i, j; int cchFit, cwc;
// first compute return the proper fit in multi byte characters
if (lpnFit) { cwc = *lpnFit; cchFit = WideCharToMultiByte(dwCP, 0, pwsz, cwc, NULL, 0, NULL, NULL); *lpnFit = cchFit; } else { cwc = cwcWideChars; cchFit = cchString; }
// next copy the dx array. we duplicate the dx value for the high
// and low byte of DBCS characters.
if(lpnDx) { for(i = 0, j = 0; i < cchFit; j++) { if(IsDBCSLeadByteEx(dwCP,lpszString[i])) { lpnDx[i++] = pDx[j]; lpnDx[i++] = pDx[j]; } else { lpnDx[i++] = pDx[j]; } }
// I claim that we should be at exactly at the end of the Unicode
// string once we are here if not we need to examine the above loop
// to make sure it works properly [gerritv]
ASSERTGDI(j == cwc, "GetTextExtentExPointA: problem converting DX array\n"); } } } else { GdiSetLastError(ERROR_INVALID_PARAMETER); }
if (pwsz != awc) LOCALFREE(pwsz);
}
return bRet; }
/******************************Public*Routine******************************\
* GetTextExtentExPointW * * History: * 06-Jan-1992 -by- Gilman Wong [gilmanw] * Wrote it. \**************************************************************************/
BOOL APIENTRY GetTextExtentExPointW ( HDC hdc, LPCWSTR lpwszString, int cwchString, int nMaxExtent, LPINT lpnFit, LPINT lpnDx, LPSIZE lpSize ) {
#ifdef LANGPACK
if(gbLpk) { return (*fpLpkGetTextExtentExPoint)(hdc, lpwszString, cwchString, nMaxExtent, lpnFit, lpnDx, lpSize, 0, -1); } else #endif
return NtGdiGetTextExtentExW(hdc, (LPWSTR)lpwszString, cwchString, nMaxExtent, lpnFit, lpnDx, lpSize, 0);
}
/******************************Public*Routine******************************\
* * GetTextExtentExPointWPri, * The same as GetTextExtentExPointW, the only difference is that * lpk is bypassed, whether installed or not. This routine is actually called * by lpk when it is installed. * * History: * 03-Jun-1997 -by- Bodin Dresevic [BodinD] * Wrote it. \**************************************************************************/
BOOL APIENTRY GetTextExtentExPointWPri ( HDC hdc, LPCWSTR lpwszString, int cwchString, int nMaxExtent, LPINT lpnFit, LPINT lpnDx, LPSIZE lpSize ) {
return NtGdiGetTextExtentExW(hdc, (LPWSTR)lpwszString, cwchString, nMaxExtent, lpnFit, lpnDx, lpSize, 0);
}
/******************************Public*Routine******************************\
* * BOOL APIENTRY GetTextExtentExPointI * * * History: * 09-Sep-1996 -by- Bodin Dresevic [BodinD] * Wrote it. \**************************************************************************/
BOOL APIENTRY GetTextExtentExPointI ( HDC hdc, LPWORD lpwszString, int cwchString, int nMaxExtent, LPINT lpnFit, LPINT lpnDx, LPSIZE lpSize ) { return NtGdiGetTextExtentExW(hdc, (LPWSTR)lpwszString, cwchString, nMaxExtent, lpnFit, lpnDx, lpSize, GTEEX_GLYPH_INDEX); }
/******************************Public*Routine******************************\
* * bGetCharABCWidthsA * * works for both floating point and integer version depending on bInt * * History: * 24-Feb-1992 -by- Bodin Dresevic [BodinD] * Wrote it. \**************************************************************************/
BOOL bGetCharABCWidthsA ( HDC hdc, UINT wFirst, UINT wLast, FLONG fl, PVOID pvBuf // if (fl & GCABCW_INT) pabc else pabcf,
) { BOOL bRet = FALSE; ULONG cjData, cjWCHAR, cjABC; ULONG cChar = wLast - wFirst + 1; DWORD dwCP = GetCodePage(hdc); BOOL bDBCSCodePage;
bDBCSCodePage = IS_ANY_DBCS_CODEPAGE(dwCP);
// Parameter checking.
FIXUP_HANDLE(hdc);
if((pvBuf == (PVOID) NULL) || (bDBCSCodePage && !IsValidDBCSRange(wFirst,wLast)) || (!bDBCSCodePage && ((wFirst > wLast) || (wLast > 255)))) { WARNING("gdi!_GetCharABCWidthsA(): bad parameter\n"); GdiSetLastError(ERROR_INVALID_PARAMETER); return(FALSE); }
// Compute buffer space needed in memory window.
// Buffer will be input array of WCHAR followed by output arrary of ABC.
// Because ABC need 32-bit alignment, cjWCHAR is rounded up to DWORD boundary.
cjABC = cChar * ((fl & GCABCW_INT) ? sizeof(ABC) : sizeof(ABCFLOAT)); cjWCHAR = ALIGN4(cChar * sizeof(WCHAR)); cjData = cjWCHAR + cjABC;
//
// WINBUG 82840 2-7-2000 bhouse Possible cleanup in bGetCharABCWidthsA
// Old Comment:
// - if vSetUpUnicodeString,x could be moved to ntgdi,
// we wouldn't need to allocated temp buffers twice
//
// Allocate memory for temp buffer, fill in with proper char values
//
// Write the unicode string [wFirst,wLast] at the top of the buffer.
// vSetUpUnicodeString requires a tmp CHAR buffer; we'll cheat a little
// and use the ABC return buffer (this assumes that ABC is bigger
// than a CHAR or USHORT in the case of DBCS). We can get away with this b
// because this memory is an output buffer for the server call.
//
{ PUCHAR pjTempBuffer = LOCALALLOC(cjData); PUCHAR pwcABC = pjTempBuffer + cjWCHAR; PWCHAR pwcCHAR = (PWCHAR)pjTempBuffer;
if (pjTempBuffer == (PUCHAR)NULL) { bRet = FALSE; } else {
if(bDBCSCodePage) { bRet = bSetUpUnicodeStringDBCS(wFirst, wLast, pwcABC, pwcCHAR, dwCP, GetCurrentDefaultChar(hdc)); } else { bRet = bSetUpUnicodeString(wFirst, wLast, pwcABC, pwcCHAR, dwCP); }
//
// call GDI
//
if(bRet) { bRet = NtGdiGetCharABCWidthsW(hdc, wFirst, cChar, (PWCHAR)pwcCHAR, (fl & GCABCW_INT), (PVOID)pwcABC); }
//
// If OK, then copy return data out of window.
//
if (bRet) { RtlCopyMemory((PBYTE) pvBuf,pwcABC, cjABC); }
LOCALFREE(pjTempBuffer); } } return bRet; }
/******************************Public*Routine******************************\
* BOOL APIENTRY GetCharABCWidthsA ( * * We want to get ABC spaces * for a contiguous set of input codepoints (that range from wFirst to wLast). * The set of corresponding UNICODE codepoints is not guaranteed to be * contiguous. Therefore, we will translate the input codepoints here and * pass the server a buffer of UNICODE codepoints. * * History: * 20-Jan-1992 -by- Gilman Wong [gilmanw] * Wrote it. \**************************************************************************/
BOOL APIENTRY GetCharABCWidthsA ( HDC hdc, UINT wFirst, UINT wLast, LPABC lpABC ) { return bGetCharABCWidthsA(hdc,wFirst,wLast,GCABCW_INT,(PVOID)lpABC); }
/******************************Public*Routine******************************\
* * GetCharABCWidthsFloatA * * History: * 22-Feb-1992 -by- Bodin Dresevic [BodinD] * Wrote it. \**************************************************************************/
BOOL APIENTRY GetCharABCWidthsFloatA ( IN HDC hdc, IN UINT iFirst, IN UINT iLast, OUT LPABCFLOAT lpABCF ) { return bGetCharABCWidthsA(hdc,iFirst,iLast,0,(PVOID)lpABCF); }
/******************************Public*Routine******************************\
* * bGetCharABCWidthsW * * History: * 22-Feb-1992 -by- Bodin Dresevic [BodinD] * Wrote it. \**************************************************************************/
BOOL bGetCharABCWidthsW ( IN HDC hdc, IN UINT wchFirst, IN UINT wchLast, IN FLONG fl, OUT PVOID pvBuf ) { BOOL bRet = FALSE; ULONG cwch = wchLast - wchFirst + 1;
// Parameter checking.
FIXUP_HANDLE(hdc);
if ( (pvBuf == (PVOID)NULL) || (wchFirst > wchLast) ) { WARNING("gdi!GetCharABCWidthsW(): bad parameter\n"); GdiSetLastError(ERROR_INVALID_PARAMETER); return(FALSE); }
//
// kernel mode
//
bRet = NtGdiGetCharABCWidthsW( hdc, wchFirst, cwch, (PWCHAR)NULL, fl, (PVOID)pvBuf);
return(bRet);
}
/******************************Public*Routine******************************\
* BOOL APIENTRY GetCharABCWidthsW ( * IN HDC hdc, * IN WORD wchFirst, * IN WORD wchLast, * OUT LPABC lpABC * ) * * For this case, we can truly assume that we want to get ABC character * widths for a contiguous set of UNICODE codepoints from wchFirst to * wchLast (inclusive). So we will call the server using wchFirst, but * with an empty input buffer. * * History: * 20-Jan-1992 -by- Gilman Wong [gilmanw] * Wrote it. \**************************************************************************/
BOOL APIENTRY GetCharABCWidthsW ( HDC hdc, UINT wchFirst, UINT wchLast, LPABC lpABC ) { return bGetCharABCWidthsW(hdc,wchFirst,wchLast,GCABCW_INT,(PVOID)lpABC); }
/******************************Public*Routine******************************\
* * GetCharABCWidthsFloatW * * Effects: * * Warnings: * * History: * 22-Feb-1992 -by- Bodin Dresevic [BodinD] * Wrote it. \**************************************************************************/
BOOL APIENTRY GetCharABCWidthsFloatW ( HDC hdc, UINT iFirst, UINT iLast, LPABCFLOAT lpABCF ) { return bGetCharABCWidthsW(hdc,iFirst,iLast,0,(PVOID)lpABCF); }
/******************************Public*Routine******************************\
* * GetCharABCWidthsI, index version * * if pgi == NULL use the consecutive range * giFirst, giFirst + 1, ...., giFirst + cgi - 1 * * if pgi != NULL ignore giFirst and use cgi indices pointed to by pgi * * History: * 28-Aug-1996 -by- Bodin Dresevic [BodinD] * Wrote it. \**************************************************************************/
BOOL APIENTRY GetCharABCWidthsI( HDC hdc, UINT giFirst, UINT cgi, LPWORD pgi, LPABC pabc ) { return NtGdiGetCharABCWidthsW(hdc, giFirst, cgi, pgi, GCABCW_INT | GCABCW_GLYPH_INDEX, pabc ); }
/******************************Public*Routine******************************\
* GetFontData * * Client side stub to GreGetFontData. * * History: * 17-Feb-1992 -by- Gilman Wong [gilmanw] * Wrote it. \**************************************************************************/
DWORD APIENTRY GetFontData ( HDC hdc, DWORD dwTable, DWORD dwOffset, PVOID pvBuffer, DWORD cjBuffer ) { DWORD dwRet = (DWORD) -1;
FIXUP_HANDLE(hdc);
// if there is no buffer to copy data to, ignore possibly different
// from zero cjBuffer parameter. This is what win95 is doing.
if (cjBuffer && (pvBuffer == NULL)) cjBuffer = 0;
dwRet = NtGdiGetFontData( hdc, dwTable, dwOffset, pvBuffer, cjBuffer);
return(dwRet); }
/******************************Public*Routine******************************\
* GetGlyphOutline * * Client side stub to GreGetGlyphOutline. * * History: * 17-Feb-1992 -by- Gilman Wong [gilmanw] * Wrote it. \**************************************************************************/
DWORD GetGlyphOutlineInternalW ( HDC hdc, UINT uChar, UINT fuFormat, LPGLYPHMETRICS lpgm, DWORD cjBuffer, LPVOID pvBuffer, CONST MAT2 *lpmat2, BOOL bIgnoreRotation ) { DWORD dwRet = (DWORD) -1;
// Parameter validation.
FIXUP_HANDLE(hdc);
if ( (lpmat2 == (LPMAT2) NULL) || (lpgm == (LPGLYPHMETRICS) NULL) ) { WARNING("gdi!GetGlyphOutlineW(): bad parameter\n"); return (dwRet); }
if (pvBuffer == NULL) cjBuffer = 0;
// Compute buffer space needed in memory window.
dwRet = NtGdiGetGlyphOutline( hdc, (WCHAR)uChar, fuFormat, lpgm, cjBuffer, pvBuffer, (LPMAT2)lpmat2, bIgnoreRotation);
return(dwRet); }
DWORD APIENTRY GetGlyphOutlineW ( HDC hdc, UINT uChar, UINT fuFormat, LPGLYPHMETRICS lpgm, DWORD cjBuffer, LPVOID pvBuffer, CONST MAT2 *lpmat2 ) {
return( GetGlyphOutlineInternalW( hdc, uChar, fuFormat, lpgm, cjBuffer, pvBuffer, lpmat2, FALSE ) ); }
DWORD APIENTRY GetGlyphOutlineInternalA ( HDC hdc, UINT uChar, UINT fuFormat, LPGLYPHMETRICS lpgm, DWORD cjBuffer, LPVOID pvBuffer, CONST MAT2 *lpmat2, BOOL bIgnoreRotation ) { WCHAR wc; BOOL bRet;
FIXUP_HANDLE(hdc);
// The ANSI interface is compatible with Win 3.1 and is intended
// to take a 2 byte uChar. Since we are 32-bit, this 16-bit UINT
// is now 32-bit. So we are only interested in the least significant
// word of the uChar passed into the 32-bit interface.
if (!(fuFormat & GGO_GLYPH_INDEX)) { // the conversion needs to be done based on
// the current code page of the font selected in the dc
UCHAR Mbcs[2]; UINT Convert; DWORD dwCP = GetCodePage(hdc);
if(IS_ANY_DBCS_CODEPAGE(dwCP) && IsDBCSLeadByteEx(dwCP, (char) (uChar >> 8))) { Mbcs[0] = (uChar >> 8) & 0xFF; Mbcs[1] = uChar & 0xFF; Convert = 2; } else { Mbcs[0] = uChar & 0xFF; Convert = 1; }
if(!(bRet = MultiByteToWideChar(dwCP, 0, (LPCSTR)Mbcs,Convert, &wc, sizeof(WCHAR)))) { GdiSetLastError(ERROR_INVALID_PARAMETER); }
} else { // The uChar value is to be interpreted as glyph index and
// no conversion is necessary
wc = (WCHAR)uChar; bRet = TRUE; }
if (bRet) { bRet = GetGlyphOutlineInternalW( hdc, (UINT) wc, fuFormat, lpgm, cjBuffer, pvBuffer, lpmat2, bIgnoreRotation); }
return bRet; }
DWORD APIENTRY GetGlyphOutlineA ( HDC hdc, UINT uChar, UINT fuFormat, LPGLYPHMETRICS lpgm, DWORD cjBuffer, LPVOID pvBuffer, CONST MAT2 *lpmat2 ) {
return( GetGlyphOutlineInternalA( hdc, uChar, fuFormat, lpgm, cjBuffer, pvBuffer, lpmat2, FALSE ) ); }
DWORD APIENTRY GetGlyphOutlineWow ( HDC hdc, UINT uChar, UINT fuFormat, LPGLYPHMETRICS lpgm, DWORD cjBuffer, LPVOID pvBuffer, CONST MAT2 *lpmat2 ) {
return( GetGlyphOutlineInternalA( hdc, uChar, fuFormat, lpgm, cjBuffer, pvBuffer, lpmat2, TRUE ) ); }
/******************************Public*Routine******************************\
* GetOutlineTextMetricsW * * Client side stub to GreGetOutlineTextMetrics. * * History: * * Tue 20-Apr-1993 -by- Gerrit van Wingerden [gerritv] * update: added bTTOnly stuff for Aldus escape in the WOW layer * * Thu 28-Jan-1993 -by- Bodin Dresevic [BodinD] * update: added TMDIFF * stuff * * 17-Feb-1992 -by- Gilman Wong [gilmanw] * Wrote it. \**************************************************************************/
UINT APIENTRY GetOutlineTextMetricsWInternal ( HDC hdc, UINT cjCopy, // refers to OTMW_INTERNAL, not to OUTLINETEXTMETRICSW
OUTLINETEXTMETRICW * potmw, TMDIFF * ptmd ) { DWORD cjRet = (DWORD) 0;
FIXUP_HANDLE(hdc);
if (potmw == (OUTLINETEXTMETRICW *) NULL) cjCopy = 0;
cjRet = NtGdiGetOutlineTextMetricsInternalW( hdc, cjCopy, potmw, ptmd);
return(cjRet);
}
/******************************Public*Routine******************************\
* * UINT APIENTRY GetOutlineTextMetricsW ( * * wrote the wrapper to go around the corresponding internal routine * * History: * 28-Jan-1993 -by- Bodin Dresevic [BodinD] * Wrote it. \**************************************************************************/
UINT APIENTRY GetOutlineTextMetricsW ( HDC hdc, UINT cjCopy, LPOUTLINETEXTMETRICW potmw ) { TMDIFF tmd;
return GetOutlineTextMetricsWInternal(hdc, cjCopy, potmw, &tmd); }
#define bAnsiSize(a,b,c) (NT_SUCCESS(RtlUnicodeToMultiByteSize((a),(b),(c))))
// vAnsiSize macro should only be used within GetOTMA, where bAnsiSize
// is not supposed to fail [bodind]
#if DBG
#define vAnsiSize(a,b,c) \
{ \ BOOL bTmp = bAnsiSize(&cjString, pwszSrc, sizeof(WCHAR) * cwc); \ ASSERTGDI(bTmp, "gdi32!GetOTMA: bAnsiSize failed \n"); \ }
#else
#define vAnsiSize(a,b,c) bAnsiSize(a,b,c)
#endif //, non debug version
/******************************Public*Routine******************************\
* GetOutlineTextMetricsInternalA * * Client side stub to GreGetOutlineTextMetrics. * * History: * * 20-Apr-1993 -by- Gerrit van Wingerden [gerritv] * Changed to GetOutlineTextMetricsInternalA from GetOutlineTextMetricsA * to support all fonts mode for Aldus escape. * * 17-Feb-1992 -by- Gilman Wong [gilmanw] * Wrote it. \**************************************************************************/
UINT APIENTRY GetOutlineTextMetricsInternalA ( HDC hdc, UINT cjCopy, LPOUTLINETEXTMETRICA potma ) { UINT cjRet = 0; UINT cjotma, cjotmw;
TMDIFF tmd; OUTLINETEXTMETRICW *potmwTmp; OUTLINETEXTMETRICA otmaTmp; // tmp buffer on the stack
FIXUP_HANDLE(hdc);
// Because we need to be able to copy cjCopy bytes of data from the
// OUTLINETEXTMETRICA structure, we need to allocate a temporary buffer
// big enough for the entire structure. This is because the UNICODE and
// ANSI versions of OUTLINETEXTMETRIC have mismatched offsets to their
// corresponding fields.
// Determine size of the buffer.
if ((cjotmw = GetOutlineTextMetricsWInternal(hdc, 0, NULL,&tmd)) == 0 ) { WARNING("gdi!GetOutlineTextMetricsInternalA(): unable to determine size of buffer needed\n"); return (cjRet); }
// get cjotma from tmd.
cjotma = (UINT)tmd.cjotma;
// if cjotma == 0, this is HONEST to God unicode font, can not convert
// strings to ansi
if (cjotma == 0) { WARNING("gdi!GetOutlineTextMetricsInternalA(): unable to determine cjotma\n"); return (cjRet); }
// Early out. If NULL buffer, then just return the size.
if (potma == (LPOUTLINETEXTMETRICA) NULL) return (cjotma);
// Allocate temporary buffers.
if ((potmwTmp = (OUTLINETEXTMETRICW*) LOCALALLOC(cjotmw)) == (OUTLINETEXTMETRICW*)NULL) { WARNING("gdi!GetOutlineTextMetricA(): memory allocation error OUTLINETEXTMETRICW buffer\n"); GdiSetLastError(ERROR_NOT_ENOUGH_MEMORY); return (cjRet); }
// Call the UNICODE version of the call.
if (GetOutlineTextMetricsWInternal(hdc, cjotmw, potmwTmp,&tmd) == 0 ) { WARNING("gdi!GetOutlineTextMetricsInternalA(): call to GetOutlineTextMetricsW() failed\n"); LOCALFREE(potmwTmp); return (cjRet); }
// Convert from OUTLINETEXTMETRICW to OUTLINETEXTMETRICA
vOutlineTextMetricWToOutlineTextMetricA(&otmaTmp, potmwTmp,&tmd);
// Copy data into return buffer. Do not copy strings.
cjRet = min(cjCopy, sizeof(OUTLINETEXTMETRICA)); RtlMoveMemory(potma,&otmaTmp,cjRet);
// Note that if
// offsetof(OUTLINETEXTMETRICA,otmpFamilyName) < cjCopy <= sizeof(OUTLINETEXTMETRICA)
// the offsets to strings have been set to zero [BodinD]
// If strings wanted, convert the strings to ANSI.
if (cjCopy > sizeof(OUTLINETEXTMETRICA)) { ULONG cjString,cwc; ULONG_PTR dpString; ULONG_PTR dpStringEnd; PWSZ pwszSrc;
// first have to make sure that we will not overwrite the end
// of the caller's buffer, if that is the case
if (cjCopy < cjotma) { // Win 31 spec is ambiguous about this case
// and by looking into the source code, it seems that
// they just overwrite the end of the buffer without
// even doing this check.
GdiSetLastError(ERROR_CAN_NOT_COMPLETE); cjRet = 0; goto GOTMA_clean_up; }
// now we know that all the strings can fit, moreover we know that
// all string operations will succeed since we have called
// cjOTMA to do these same operations on the server side to give us
// cjotma [bodind]
// Note: have to do the backwards compatible casting below because Win 3.1 insists
// on using a PSTR as PTRDIFF (i.e., an offset).
// FAMILY NAME ------------------------------------------------------------
pwszSrc = (PWSZ) (((PBYTE) potmwTmp) + (ULONG_PTR) potmwTmp->otmpFamilyName); cwc = wcslen(pwszSrc) + 1; vAnsiSize(&cjString, pwszSrc, sizeof(WCHAR) * cwc);
// Convert from Unicode to ASCII.
dpString = sizeof(OUTLINETEXTMETRICA); dpStringEnd = dpString + cjString;
ASSERTGDI(dpStringEnd <= cjCopy, "gdi32!GetOTMA: string can not fit1\n");
if (!bToASCII_N ((PBYTE)potma + dpString,cjString,pwszSrc,cwc)) { WARNING("gdi!GetOutlineTextMetricsInternalA(): UNICODE->ASCII conv error \n"); cjRet = 0; goto GOTMA_clean_up; }
// Store string offset in the return structure.
potma->otmpFamilyName = (PSTR) dpString;
// FACE NAME --------------------------------------------------------------
pwszSrc = (PWSZ) (((PBYTE) potmwTmp) + (ULONG_PTR) potmwTmp->otmpFaceName); cwc = wcslen(pwszSrc) + 1; vAnsiSize(&cjString, pwszSrc, sizeof(WCHAR) * cwc);
dpString = dpStringEnd; dpStringEnd = dpString + cjString;
ASSERTGDI(dpStringEnd <= cjCopy, "gdi32!GetOTMA: string can not fit2\n");
// Convert from Unicode to ASCII.
if (!bToASCII_N ((PBYTE)potma + dpString,cjString,pwszSrc,cwc)) { WARNING("gdi!GetOutlineTextMetricsInternalA(): UNICODE->ASCII conv error \n"); cjRet = 0; goto GOTMA_clean_up; }
// Store string offset in return structure. Move pointers to next string.
potma->otmpFaceName = (PSTR) dpString;
// STYLE NAME -------------------------------------------------------------
pwszSrc = (PWSZ) (((PBYTE) potmwTmp) + (ULONG_PTR) potmwTmp->otmpStyleName); cwc = wcslen(pwszSrc) + 1; vAnsiSize(&cjString, pwszSrc, sizeof(WCHAR) * cwc);
dpString = dpStringEnd; dpStringEnd = dpString + cjString;
ASSERTGDI(dpStringEnd <= cjCopy, "gdi32!GetOTMA: string can not fit3\n");
// Convert from Unicode to ASCII.
if (!bToASCII_N ((PBYTE)potma + dpString,cjString,pwszSrc,cwc)) { WARNING("gdi!GetOutlineTextMetricsInternalA(): UNICODE->ASCII conv error \n"); cjRet = 0; goto GOTMA_clean_up; }
// Store string offset in return structure. Move pointers to next string.
potma->otmpStyleName = (PSTR)dpString;
// FULL NAME --------------------------------------------------------------
pwszSrc = (PWSZ) (((PBYTE) potmwTmp) + (ULONG_PTR) potmwTmp->otmpFullName); cwc = wcslen(pwszSrc) + 1; vAnsiSize(&cjString, pwszSrc, sizeof(WCHAR) * cwc);
dpString = dpStringEnd; dpStringEnd = dpString + cjString;
ASSERTGDI(dpStringEnd <= cjCopy, "gdi32!GetOTMA: string can not fit4\n");
// Convert from Unicode to ASCII.
if (!bToASCII_N ((PBYTE)potma + dpString,cjString,pwszSrc,cwc)) { WARNING("gdi!GetOutlineTextMetricsInternalA(): UNICODE->ASCII conv error \n"); cjRet = 0; goto GOTMA_clean_up; }
// Store string offset in return structure.
potma->otmpFullName = (PSTR) dpString;
//Sundown: safe to truncate ULONG
cjRet = (ULONG)dpStringEnd; ASSERTGDI(cjRet == cjotma, "gdi32!GetOTMA: cjRet != dpStringEnd\n");
}
GOTMA_clean_up:
// Free temporary buffer.
LOCALFREE(potmwTmp);
// Fixup size field.
if (cjCopy >= sizeof(UINT)) // if it is possible to store otmSize
potma->otmSize = cjRet;
// Successful, so return size.
return (cjRet); }
/******************************Public*Routine******************************\
* GetOutlineTextMetricsA * * Client side stub to GreGetOutlineTextMetrics. * * History: * Tue 02-Nov-1993 -by- Bodin Dresevic [BodinD] \**************************************************************************/
UINT APIENTRY GetOutlineTextMetricsA ( HDC hdc, UINT cjCopy, LPOUTLINETEXTMETRICA potma ) { return GetOutlineTextMetricsInternalA(hdc, cjCopy, potma); }
/******************************Public*Routine******************************\
* * * GetKerningPairs * * * * History: * * Sun 23-Feb-1992 09:48:55 by Kirk Olynyk [kirko] * * Wrote it. * \**************************************************************************/
DWORD APIENTRY GetKerningPairsW( IN HDC hdc, // handle to application's DC
IN DWORD nPairs, // max no. KERNINGPAIR to be returned
OUT LPKERNINGPAIR lpKernPair // pointer to receiving buffer
) { ULONG sizeofMsg; DWORD cRet = 0;
FIXUP_HANDLE(hdc);
if (nPairs == 0 && lpKernPair != (KERNINGPAIR*) NULL) { GdiSetLastError(ERROR_INVALID_PARAMETER); return(0); }
cRet = NtGdiGetKerningPairs( hdc, nPairs, lpKernPair);
return(cRet); }
/******************************Public*Routine******************************\
* GetKerningPairsA * * filters out pairs that are not contained in the code page of the font * selected in DC * * History: * 14-Mar-1996 -by- Xudong Wu [TessieW] * Wrote it. \**************************************************************************/
DWORD APIENTRY GetKerningPairsA ( HDC hdc, // handle to application's DC
DWORD nPairs, // max no. KERNINGPAIR to be returned
LPKERNINGPAIR lpKernPair // pointer to receiving buffer
) { #define MAXKERNPAIR 300
DWORD i; DWORD dwCP; KERNINGPAIR tmpKernPair[MAXKERNPAIR]; DWORD cRet, cRet1; KERNINGPAIR *pkp, *pkrn; KERNINGPAIR UNALIGNED *pkrnLast; BOOL bDBCS;
FIXUP_HANDLE(hdc);
if ((nPairs == 0) && (lpKernPair != (KERNINGPAIR*) NULL)) { GdiSetLastError(ERROR_INVALID_PARAMETER); return(0); }
cRet = NtGdiGetKerningPairs(hdc, 0, NULL);
if (cRet == 0) return(cRet);
if (cRet <= MAXKERNPAIR) pkrn = tmpKernPair; else pkrn = LOCALALLOC(cRet * sizeof(KERNINGPAIR));
if (!pkrn) { GdiSetLastError(ERROR_NOT_ENOUGH_MEMORY); return 0; }
cRet1 = NtGdiGetKerningPairs(hdc, cRet, pkrn);
if (cRet1 == 0 || cRet1 != cRet) { ASSERTGDI(FALSE, "NtGdiGetKerningPairs returns different values\n"); cRet = 0; goto Cleanup; }
pkp = pkrn; pkrnLast = lpKernPair; cRet = 0;
// GDI has returned iFirst and iSecond of the KERNINGPAIR structure in Unicode
// It is at this point that we translate them to the current code page
dwCP = GetCodePage(hdc);
bDBCS = IS_ANY_DBCS_CODEPAGE(dwCP);
for (i = 0; i < cRet1; i++,pkp++) { UCHAR ach[2], ach2[2]; BOOL bUsedDef[2];
ach[0] = ach[1] = 0; // insure zero extension
WideCharToMultiByte(dwCP, 0, &(pkp->wFirst), 1, ach, sizeof(ach), NULL, &bUsedDef[0]); if (!bUsedDef[0]) { ach2[0] = ach2[1] = 0;
WideCharToMultiByte(dwCP, 0, &(pkp->wSecond), 1, ach2, sizeof(ach2), NULL, &bUsedDef[1]);
if (!bUsedDef[1]) { if (lpKernPair) { // do not overwrite the end of the buffer if it is provided
if (cRet >= nPairs) break;
if (bDBCS) { if (IsDBCSLeadByteEx(dwCP,ach[0])) { pkrnLast->wFirst = (WORD)(ach[0] << 8 | ach[1]); } else { pkrnLast->wFirst = ach[0]; }
if (IsDBCSLeadByteEx(dwCP,ach2[0])) { pkrnLast->wSecond = (WORD)(ach2[0] << 8 | ach2[1]); } else { pkrnLast->wSecond = ach2[0]; } } else { pkrnLast->wFirst = ach[0]; pkrnLast->wSecond = ach2[0]; }
pkrnLast->iKernAmount = pkp->iKernAmount; pkrnLast++;
} cRet++; } } } Cleanup: if (pkrn != tmpKernPair) LOCALFREE(pkrn);
return cRet; }
/*****************************Public*Routine******************************\
* FixBrushOrgEx * * for win32s * * History: * 04-Jun-1992 -by- Eric Kutter [erick] * Wrote it. \**************************************************************************/
BOOL FixBrushOrgEx(HDC hdc, int x, int y, LPPOINT ptl) { return(FALSE); }
/******************************Public*Function*****************************\
* GetColorAdjustment * * Get the color adjustment data for a given DC. * * History: * 07-Aug-1992 -by- Wendy Wu [wendywu] * Wrote it. \**************************************************************************/
BOOL APIENTRY GetColorAdjustment(HDC hdc, LPCOLORADJUSTMENT pclradj) { FIXUP_HANDLE(hdc);
return(NtGdiGetColorAdjustment(hdc,pclradj)); }
/******************************Public*Routine******************************\
* GetETM * * Aldus Escape support * * History: * 20-Oct-1993 -by- Bodin Dresevic [BodinD] * Wrote it. \**************************************************************************/
BOOL APIENTRY GetETM (HDC hdc, EXTTEXTMETRIC * petm) { BOOL bRet = FALSE;
FIXUP_HANDLE(hdc);
bRet = NtGdiGetETM(hdc,petm);
// path up the number of KerningPairs to match GetKerningPairsA
if (bRet && petm) { petm->etmNKernPairs = (WORD)GetKerningPairsA(hdc, 0, NULL); }
return(bRet); }
#if 0
/****************************Public*Routine********************************\
* GetCharWidthInfo * * Get the lMaxNegA lMaxNegC and lMinWidthD * * History: * 09-Feb-1996 -by- Xudong Wu [tessiew] * Wrote it \***************************************************************************/
BOOL APIENTRY GetCharWidthInfo (HDC hdc, PCHWIDTHINFO pChWidthInfo) { return ( NtGdiGetCharWidthInfo(hdc, pChWidthInfo) ); } #endif
#ifdef LANGPACK
/******************************Public*Routine******************************\
* * bGetRealizationInfoInternal * * Retreives the realization_info from kernel, if not cached in shared * memory * * History: * 18-Aug-1997 -by- Samer Arafeh [SamerA] * Wrote it. \**************************************************************************/
BOOL bGetRealizationInfoInternal( HDC hdc, REALIZATION_INFO *pri, CFONT *pcf ) { BOOL bRet = FALSE;
if (pri) { // if no pcf or we havn't cached the metrics
if ((pcf == NULL) || !(pcf->fl & CFONT_CACHED_RI) || pcf->timeStamp != pGdiSharedMemory->timeStamp) { REALIZATION_INFO ri; PDC_ATTR pDcAttr;
PSHARED_GET_VALIDATE(pDcAttr,hdc,DC_TYPE);
if( pcf != NULL && (pcf->fl & CFONT_PUBLIC) ) bRet = NtGdiGetRealizationInfo(hdc,&ri, pcf->hf); else bRet = NtGdiGetRealizationInfo(hdc,&ri, 0);
if (bRet) { *pri = ri;
if (pcf && !(pcf->fl & CFONT_PUBLIC)) { // we succeeded and we have a pcf so cache the data
pcf->ri = ri;
pcf->fl |= CFONT_CACHED_RI;
pcf->timeStamp = pGdiSharedMemory->timeStamp; } } } else { *pri = pcf->ri; bRet = TRUE; }
}
return(bRet); }
/******************************Public*Routine******************************\
* * GdiRealizationInfo * * Try retreive the RealizationInfo from shared memory * * History: * 18-Aug-1997 -by- Samer Arafeh [SamerA] * Wrote it. \**************************************************************************/
BOOL APIENTRY GdiRealizationInfo(HDC hdc,REALIZATION_INFO *pri) { BOOL bRet = FALSE; PDC_ATTR pDcAttr;
FIXUP_HANDLE(hdc);
PSHARED_GET_VALIDATE(pDcAttr,hdc,DC_TYPE);
if (pDcAttr) { CFONT * pcf;
ENTERCRITICALSECTION(&semLocal);
pcf = pcfLocateCFONT(hdc,pDcAttr,0,(PVOID) NULL,0,TRUE);
bRet = bGetRealizationInfoInternal(hdc,pri,pcf);
// pcfLocateCFONT added a reference so now we need to remove it
if (pcf) { DEC_CFONT_REF(pcf); }
LEAVECRITICALSECTION(&semLocal); } else { // it could a public DC -OBJECT_OWNER_PUBLIC- (in which gpGdiShareMemory[hDC].pUser=NULL)
// so let's do it the expensive way by doing the kernel-transition...
bRet = NtGdiGetRealizationInfo(hdc,pri,0); }
return(bRet); }
#endif
|