// $Id: bshadow.cpp 1282 2006-06-09 09:46:49Z alex $ /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE ================================XARAHEADERSTART=========================== Xara LX, a vector drawing and manipulation program. Copyright (C) 1993-2006 Xara Group Ltd. Copyright on certain contributions may be held in joint with their respective authors. See AUTHORS file for details. LICENSE TO USE AND MODIFY SOFTWARE ---------------------------------- This file is part of Xara LX. Xara LX is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. Xara LX and its component source files are distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Xara LX (see the file GPL in the root directory of the distribution); if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ADDITIONAL RIGHTS ----------------- Conditional upon your continuing compliance with the GNU General Public License described above, Xara Group Ltd grants to you certain additional rights. The additional rights are to use, modify, and distribute the software together with the wxWidgets library, the wxXtra library, and the "CDraw" library and any other such library that any version of Xara LX relased by Xara Group Ltd requires in order to compile and execute, including the static linking of that library to XaraLX. In the case of the "CDraw" library, you may satisfy obligation under the GNU General Public License to provide source code by providing a binary copy of the library concerned and a copy of the license accompanying it. Nothing in this section restricts any of the rights you have under the GNU General Public License. SCOPE OF LICENSE ---------------- This license applies to this program (XaraLX) and its constituent source files only, and does not necessarily apply to other Xara products which may in part share the same code base, and are subject to their own licensing terms. This license does not apply to files in the wxXtra directory, which are built into a separate library, and are subject to the wxWindows license contained within that directory in the file "WXXTRA-LICENSE". This license does not apply to the binary libraries (if any) within the "libs" directory, which are subject to a separate license contained within that directory in the file "LIBS-LICENSE". ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS ---------------------------------------------- Subject to the terms of the GNU Public License (see above), you are free to do whatever you like with your modifications. However, you may (at your option) wish contribute them to Xara's source tree. You can find details of how to do this at: http://www.xaraxtreme.org/developers/ Prior to contributing your modifications, you will need to complete our contributor agreement. This can be found at: http://www.xaraxtreme.org/developers/contribute/ Please note that Xara will not accept modifications which modify any of the text between the start and end of this header (marked XARAHEADERSTART and XARAHEADEREND). MARKS ----- Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara designs are registered or unregistered trademarks, design-marks, and/or service marks of Xara Group Ltd. All rights in these marks are reserved. Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK. http://www.xara.com/ =================================XARAHEADEREND============================ */ #include "camtypes.h" #ifdef BUILDSHADOWS #include "bshadow.h" //#include "gconsts.h" - in camtypes.h [AUTOMATICALLY REMOVED] //#include "dibutil.h" - in camtypes.h [AUTOMATICALLY REMOVED] //#include "bitmap.h" - in camtypes.h [AUTOMATICALLY REMOVED] //#include "fillattr.h" - in camtypes.h [AUTOMATICALLY REMOVED] #include "gdraw.h" #include "camprofile.h" #if _DEBUG #include "oilbitmap.h" #endif //#define MMX //#define SSE2 #define UNALIGNED #pragma warning ( disable : 4554 ) /******************************************************************************************************/ // Declare smart memory handling in Debug builds #define new CAM_DEBUG_NEW // CC_IMPLEMENT_DYNCREATE(CBitmapShadow, CCObject) // CC_IMPLEMENT_DYNCREATE(ShadowBitmap, CCObject) /******************************************************************************************************/ const double Pi = 3.1415926535897932384626433832795 ; /******************************************************************************************************/ // shrink or extend a bitmap in the y direction only (will have same width) // uses resampling to produce more accurate shrunken bitmap replications. // Assumes buffers for source and Dest are already defined and of the given dimensions. // Merges (resamples) just the alpha channels, colour taken from a spot check bool CBitmapShadow::ProjectShadow(BYTE* pSBitmap, BYTE* pDBitmap, UINT32 nWidth, UINT32 nSHeight, UINT32 nDHeight) { const UINT32 nWidth0 = DIBUtil::ScanlineSize(nWidth,8) ; UINT32 j = 0; UINT32 k = 0; UINT32 i = 0; UINT64 nPos = 0; BYTE* pDPtr = NULL; BYTE* pSPtr = NULL; BYTE* pEPtr = NULL; UINT32 t = 0; UINT32 nEnd = 0; UINT32 nStart = 0; UINT32 nLow = 0; UINT32 nHgh = 0; if ( nSHeight==nDHeight ) memcpy(pDBitmap,pSBitmap,nWidth0*nSHeight) ; else if ( nSHeight>nDHeight ) { const UINT64 nStep = (((UINT64)nSHeight<<32)-1)/((UINT64)nDHeight) ; const UINT32 nScale = (nDHeight<<16)/nSHeight ; for ( j=0 ; j>32)*nWidth0 ; pDPtr = pDBitmap ; nStart = UINT32(nPos>>32) ; nLow = ~UINT32(nPos)>>16 ; nPos += nStep ; nHgh = UINT32(nPos)>>16 ; nEnd = UINT32(nPos>>32) ; for ( i=0 ; i>32) ; pSPtr++ ; } pDBitmap += nWidth0 ; } } else { const UINT64 nStep = ((UINT64)(nSHeight-1)<<32)/((UINT64)(nDHeight-1)) ; memcpy(pDBitmap,pSBitmap,nWidth0) ; pDBitmap += nWidth0 ; UINT32 nScale = 0; for ( j=2 ; j>32)*nWidth0 ; pDPtr = pDBitmap ; nScale = UINT32(nPos)>>8 ; for ( i=0 ; i>24)) ; pSPtr++ ; } pDBitmap += nWidth0 ; } memcpy(pDBitmap,pSBitmap+(nSHeight-1)*nWidth0,nWidth0) ; } return TRUE; } CBitmapShadow::CBitmapShadow() { m_bIsWallShadow =0; m_dProjection =0.0; m_dTiltAngle =0.0; m_dBlurriness =0.0; m_dDarknessCoeff =0.0; m_dPositionX =0.0; m_dPositionY =0.0; m_OffsetX =0; m_OffsetY =0; } BOOL CBitmapShadow::MakeWallShadow (const UINT32* pForegroundBits, const CNativeSize ForegroundSize, const INT32 nXPosition, const INT32 nYPosition, const double fBlur, INT32 *pOffsetX, INT32 *pOffsetY, const double dDarknessCoeff/*=1.0*/) { // if the required blur is too small, then just copy the existing bitmap into an 8 bit bitmap. if ( fBlur < MIN_BLUR_DIAMETER ) { // set up my bitmap to shadow into /*HRESULT Result =*/ CreateFilled( ForegroundSize.x,ForegroundSize.y,0xff,8 ) ; UINT32 DestWidth = DIBUtil::ScanlineSize(ForegroundSize.x,8); BYTE* pSrc0 = (BYTE *)pForegroundBits + 3; BYTE* pDest0 = GetBytes(); BYTE* pDest0NextLine = NULL; INT32 x = 0; for (INT32 y = 0; y < ForegroundSize.y; y++) { pDest0NextLine = pDest0 + DestWidth; for (x = 0; x < ForegroundSize.x; x++) { *pDest0++ = *pSrc0; pSrc0 += 4; } pDest0 = pDest0NextLine; } return TRUE; } double fNewBlur = fBlur/2.0 ; if ( fNewBlur>MAX_SHADOW_BLUR ) fNewBlur = MAX_SHADOW_BLUR ; // UINT32 uBlur = (UINT32)fNewBlur ; UINT32 uBlur = (UINT32)(2*fNewBlur+0.5) - 1; // Create the bitmap to pass into gavin's routine // must be Width + nNewBlur * 4, Height + nNewBlur * 4 in size and each scanline must be DWORD adjusted UINT32 uBitmapToShadowWidth = DIBUtil::ScanlineSize(ForegroundSize.x+uBlur*2,8); UINT32 uBitmapToShadowSize = uBitmapToShadowWidth*(ForegroundSize.y+uBlur*2) ; BYTE* pBitmapToShadow = new BYTE[uBitmapToShadowSize]; // Now, set up the pointers to do the transfer of bits from one bitmap to the other // and move the destination pointer into position BYTE* pSrc = (BYTE *)pForegroundBits+3 ; BYTE* pDest = (BYTE *)pBitmapToShadow+(uBitmapToShadowWidth+1)*uBlur; memset(pBitmapToShadow, 0xff, uBitmapToShadowSize); UINT32 ForegroundScanlineSize = ForegroundSize.x * 4; // transfer the source bitmap into this larger bitmap to be shadowed UINT32 j = 0; BYTE* pNextDstLine = NULL; BYTE* pNextSrcLine = NULL; for ( UINT32 i=0 ; i<(UINT32)ForegroundSize.y ; i++ ) { pNextSrcLine = pSrc +ForegroundScanlineSize; pNextDstLine = pDest+uBitmapToShadowWidth; for ( j=0 ; j<(UINT32)ForegroundSize.x ; j++ ) { *pDest++ = *pSrc; pSrc += 4; } pSrc = pNextSrcLine; pDest = pNextDstLine; } // Set up my bitmap to shadow into /*HRESULT Result =*/ CreateFilled( ForegroundSize.x+uBlur, ForegroundSize.y+uBlur, 0xff , 8); // set up the bitmap info headers BITMAPINFOHEADER SourceBI; SourceBI.biBitCount = 8; SourceBI.biWidth = ForegroundSize.x+uBlur*2; SourceBI.biHeight = ForegroundSize.y+uBlur*2; SourceBI.biPlanes = 1; BITMAPINFOHEADER DestBI; DestBI.biBitCount = 8; DestBI.biWidth = ForegroundSize.x+uBlur; DestBI.biHeight = ForegroundSize.y+uBlur; DestBI.biPlanes = 1; // blur the bitmap. Blur8BppBitmap( &SourceBI, pBitmapToShadow, &DestBI, GetBytes(), uBitmapToShadowWidth, fNewBlur ); // don't forget to discard the source bitmap. delete [] pBitmapToShadow; *pOffsetX = nXPosition - (uBlur>>1); *pOffsetY = nYPosition - (uBlur>>1); return true; } /******************************************************************************************** > static LPBITMAPINFO CBitmapShadow::Feather8BppBitmap( const double fBlur, LPBITMAPINFO pSrcInfo, LPBYTE pSrcBits8, LPBYTE* ppDestBits ) Author: Karim_MacDonald (Xara Group Ltd) Created: 08/08/2000 Inputs: fBlur the blur diameter - may have a fractional part. pSrcInfo bitmap info for the source bitmap. pSrcBits8 the source bitmap bits. ppDestBits ptr to receive the address of the destination bitmap bits. Returns: ptr to the destination bitmap's info structure, or NULL if unsuccessful. Purpose: Convolve the given bitmap with a circular patch of the given blur diameter. Notes: Creates a new bitmap to contain the result of the convolution. ********************************************************************************************/ LPBITMAPINFO CBitmapShadow::Feather8BppBitmap( const double fBlur, LPBITMAPINFO pSrcInfo, LPBYTE pSrcBits8, LPBYTE* ppDestBits) { // shout out loud if the blur size is <= zero, // as we needn't do any feathering in this case. ERROR3IF(fBlur <= 0, "CBitmapShadow::Feather8BppBitmap; Feathering code used for zero blur size!"); // if the blur size is too small, then just return a copy of the passed in bitmap. if ( fBlur < MIN_BLUR_DIAMETER ) { // Phil 02/08/2004 // Don't copy vast amounts of memory around, just return the pointers to the input bitmap! *ppDestBits = pSrcBits8; return pSrcInfo; // LPBITMAPINFO pDestInfo = NULL; // BOOL bCopied = DIBUtil::CopyBitmap( pSrcInfo, pSrcBits8, // &pDestInfo, ppDestBits ); // if (bCopied) // return pDestInfo; // else // return NULL; } // work out the appropriate blur radius, and cap it at our max allowed blur size. double fNewBlur = fBlur / 2.0; if (fNewBlur > MAX_SHADOW_BLUR) fNewBlur = MAX_SHADOW_BLUR; const UINT32 uBlur = UINT32(2*fNewBlur+0.5) ; // Size of the source bitmap. CNativeSize SrcBmpSize(pSrcInfo->bmiHeader.biWidth, pSrcInfo->bmiHeader.biHeight); // size of the destination bitmap. CNativeSize DestBmpSize(SrcBmpSize.x - uBlur + 1, SrcBmpSize.y - uBlur + 1); // the source bitmap must be 8 bits-per-pixel. ERROR2IF( pSrcInfo->bmiHeader.biBitCount != 8, NULL, "CBitmapShadow::Shadow8BppBitmap; You must pass an 8bpp bitmap!"); // the destination bitmap must have a positive width and height. ERROR2IF( DestBmpSize.x <= 0 || DestBmpSize.y <= 0, NULL, "CBitmapShadow::Feather8BppBitmap; Blur patch bigger than source bitmap!"); // the source bitmap must also be DWORD aligned. // DIBUtil::Alloc actually does give DWORD aligned bmp's, // although the bitmap info header does not reflect this. UINT32 DWordWidth = DIBUtil::ScanlineSize(SrcBmpSize.x, 8); ///////////////////////////////////////////////////////////////////////////////// // Allocate dib for convolved bmp and set up info to pass to convolution function. ///////////////////////////////////////////////////////////////////////////////// // Source bitmap info-header. BITMAPINFOHEADER SourceBI; SourceBI.biBitCount = 8; SourceBI.biWidth = SrcBmpSize.x; SourceBI.biHeight = SrcBmpSize.y; SourceBI.biPlanes = 1; // Alloc a destination DIB for the convolution. LPBITMAPINFO pDestInfo = AllocDIB(DestBmpSize.x, DestBmpSize.y, 8, ppDestBits, NULL, TRUE); ERROR2IF( pDestInfo == NULL, NULL, "CBitmapShadow::Shadow8BppBitmap; Failed to allocate space for new bitmap."); pDestInfo->bmiHeader.biXPelsPerMeter = pSrcInfo->bmiHeader.biXPelsPerMeter; pDestInfo->bmiHeader.biYPelsPerMeter = pSrcInfo->bmiHeader.biYPelsPerMeter; Blur8BppBitmap(&SourceBI, pSrcBits8, &pDestInfo->bmiHeader, *ppDestBits, DWordWidth, fNewBlur); return pDestInfo; } /******************************************************************************************** > static void CBitmapShadow::Blur8BppBitmap( LPBITMAPINFOHEADER pSrcBMIHeader, LPBYTE pSrcBits, LPBITMAPINFOHEADER pDestBMIHeader, LPBYTE pDestBits, const UINT32 SWordBitmapWidth, const double fBlur ) Author: Karim_MacDonald (Xara Group Ltd) Created: 08/08/2000 Inputs: pSrcBMIHeader ptr to a bmiHeader for the source bitmap. pSrcBits ptr to the source bitmap bits. pDestBMIHeader ptr to a bmiHeader for the destination bitmap. pDestBits ptr to the destination bitmap bits. SWordBitmapWidth the width of the bitmap, which must be DWord-aligned. fBlur the blur radius - can be non-integer. Outputs: pDestBits gets the result of blurring the bitmap stored in pSrcBits. Purpose: Blur the given source bitmap and, putting the result into the destination bitmap, by convolving the source with a circular patch of the given blur radius. Errors: See also: ********************************************************************************************/ void CBitmapShadow::Blur8BppBitmap( LPBITMAPINFOHEADER pSrcBMIHeader, LPBYTE pSrcBits, LPBITMAPINFOHEADER pDestBMIHeader, LPBYTE pDestBits, const UINT32 SWordBitmapWidth, const double fBlur ) { //////////////////////////////////////////////////////////////// // set up the row & columns for the circular convolution mask // //////////////////////////////////////////////////////////////// UINT32 aLeft [MAX_ROW_OFFSETS] ; UINT32 aRight[MAX_ROW_OFFSETS] ; UINT32 aLow [MAX_ROW_OFFSETS] ; UINT32 aHigh [MAX_ROW_OFFSETS] ; // UINT32 uBlur = (UINT32)fBlur; // UINT32 uSize = 1 + 2*uBlur; // double S = uBlur ; // UINT32 uLine = 0 ; const UINT32 uSize = (UINT32)(2*fBlur+0.5) ; const double R = (uSize+1)*0.5 ; double S = (uSize-1)*0.5 ; const double R2 = fBlur*fBlur; UINT32 uLine = 0 ; UINT32 uArea = 0 ; UINT32 uRows = 0 ; for ( UINT32 r=0 ; r=0 ) { fRadius = sqrt(fRadius) ; const UINT32 uLeft = UINT32(R-fRadius) ; // const UINT32 uRight = UINT32(R+fRadius) ; const UINT32 uRight = uSize-uLeft ; if ( uLeft=TABLE_SIZE ) { uTableSize >>= 1 ; uShift++ ; } uInc <<= uShift ; BYTE* pTranslationTable = new BYTE[uTableSize+1] ; UINT32 uCount = 0 ; for ( UINT32 i=0 ; i<=uTableSize ; ++i ) { pTranslationTable[i] = uCount>>24 ; uCount += uInc ; } ///////////////////////////////////////////////////////////////////////////////// // call gavin's routine to do the shadowing. ///////////////////////////////////////////////////////////////////////////////// CamProfile cp(CAMPROFILE_SHADOW); ::GenerateWallShadow( pSrcBMIHeader, pSrcBits, pDestBMIHeader, pDestBits, uRows, aLeft,aRight, uRows, aLow ,aHigh , uShift,pTranslationTable ) ; ///////////////////////////////////////////////////////////////////////////////// // clean up the translation table. ///////////////////////////////////////////////////////////////////////////////// delete [] pTranslationTable; } // Same as the MakeShadow function above // only this produces a cast floor shadow // angle is in degrees - leans left + leans right // DestHeight lenghtens or shortens the shadow // make DestHeight = SourceHeight for 100% projection BOOL CBitmapShadow::MakeCastShadow (UINT32* pForegroundBits, const CNativeSize ForegroundSize, const double fBlur, const double dTiltAngle, const double dProjection, const double dDarknessCoeff/*=1.0*/ ) { m_OffsetX = 0; m_OffsetY = 0; // Convert the bitmap down from 32bpp to 8bpp. UINT32 nForegroundWidth = DIBUtil::ScanlineSize(ForegroundSize.x,8) ; BYTE* p8BitBitmap = new BYTE[nForegroundWidth*ForegroundSize.y] ; CONST BYTE* pSrc = (BYTE*)pForegroundBits+3 ; BYTE* pDst = p8BitBitmap ; BYTE* pDPtr = NULL; UINT32 i=0; UINT32 j; for( j = 0 ; j<(UINT32)ForegroundSize.y ; j++ ) { pDPtr = pDst ; for ( i=0 ; i<(UINT32)ForegroundSize.x ; i++ ) { *pDPtr++ = *pSrc ; pSrc += 4 ; } pDst += nForegroundWidth ; } double fNewBlur = fBlur/2.0 ; if ( fNewBlur>MAX_SHADOW_BLUR ) fNewBlur = MAX_SHADOW_BLUR ; UINT32 uBlur = (UINT32)fNewBlur ; CNativeSize ProjectedSize; ProjectedSize.x = ForegroundSize.x ; ProjectedSize.y = (INT32)( ForegroundSize.y*dProjection+0.5 ); if ( ProjectedSize.y==0 ) ProjectedSize.y = 1 ; if ( ProjectedSize.y+uBlur<2 ) ProjectedSize.y = 2-uBlur ; // Create a stretched bitmap, for the projection by // shrinking/stretching the shadow to the correct projection height. const INT32 nProjectedSize = nForegroundWidth*ProjectedSize.y; BYTE* pProjected = new BYTE[nProjectedSize]; ProjectShadow( p8BitBitmap, pProjected, ForegroundSize.x,ForegroundSize.y, ProjectedSize.y) ; delete [] p8BitBitmap; #if 0 KernelBitmap *pBitmap0 = new KernelBitmap(ProjectedSize.x,ProjectedSize.y,8,0,TRUE) ; memcpy( pBitmap0->GetBitmapBits(),pProjected,nProjectedSize ) ; LPRGBQUAD pPalette0 = pBitmap0->GetPaletteForBitmap(); for ( i=0 ; i<256 ; i++ ) { pPalette0[i].rgbRed = pPalette0[i].rgbGreen = pPalette0[i].rgbBlue = i; } BitmapTranspFillAttribute* pTranspBitmapFill0 = new BitmapTranspFillAttribute; pTranspBitmapFill0->AttachBitmap(pBitmap0); #endif UINT32 uBitmapToShadowWidth = DIBUtil::ScanlineSize(ProjectedSize.x+uBlur*4,8) ; UINT32 uBitmapToShadowSize = uBitmapToShadowWidth*(ProjectedSize.y+uBlur*2) ; BYTE* pBitmapToShadow = new BYTE[uBitmapToShadowSize] ; memset( pBitmapToShadow, 0xff, uBitmapToShadowSize ) ; pSrc = pProjected; pDst = pBitmapToShadow+uBlur*2; for ( j=0 ; j<(UINT32)ProjectedSize.y ; j++ ) { memcpy(pDst,pSrc,ProjectedSize.x) ; pSrc += nForegroundWidth; pDst += uBitmapToShadowWidth; } #if 0 KernelBitmap *pBitmap1 = new KernelBitmap(ProjectedSize.x+uBlur*4,ProjectedSize.y+uBlur*2,8,0,TRUE) ; memcpy( pBitmap1->GetBitmapBits(),pBitmapToShadow,uBitmapToShadowSize ) ; LPRGBQUAD pPalette1 = pBitmap1->GetPaletteForBitmap(); for ( i=0 ; i<256 ; i++ ) { pPalette1[i].rgbRed = pPalette1[i].rgbGreen = pPalette1[i].rgbBlue = i; } BitmapTranspFillAttribute* pTranspBitmapFill1 = new BitmapTranspFillAttribute; pTranspBitmapFill1->AttachBitmap(pBitmap1); #endif delete [] pProjected; UINT32 nShadowWidth = DIBUtil::ScanlineSize(ProjectedSize.x+uBlur*2,8) ; const INT32 nShadowSize = nShadowWidth*(ProjectedSize.y+uBlur); BYTE* pShadowBitmap = new BYTE[nShadowSize]; memset(pShadowBitmap,0xff,nShadowSize); // Set up the bitmap info headers BITMAPINFOHEADER SourceBI; SourceBI.biBitCount = 8; SourceBI.biWidth = ProjectedSize.x+uBlur*4; SourceBI.biPlanes = 1; BITMAPINFOHEADER DestBI; DestBI.biBitCount = 8; DestBI.biWidth = ProjectedSize.x+uBlur*2; DestBI.biHeight = 1; DestBI.biPlanes = 1; #if defined(MMX) || defined(SSE2) BYTE aCode[40*MAX_ROW_OFFSETS] ; #else BYTE aCode[20*MAX_ROW_OFFSETS] ; #endif BYTE aTranslationTable[TABLE_SIZE+1] ; UINT32 uLastArea = 0 ; UINT32 uLastRows = 0 ; UINT32 uLastBlur = 0 ; UINT32 uShift = 0 ; const BYTE* pSLine = pBitmapToShadow ; BYTE* pDLine = pShadowBitmap ; for ( j=0 ; jj ) uThisBlur = j ; if ( uThisBlur>uBlur ) uThisBlur = uBlur ; UINT32 uSize = uThisBlur*2+1 ; double S = uThisBlur ; double R2 = fBlur2*fBlur2 ; INT32 nLine = uThisBlur-INT32(uThisBlur*uBitmapToShadowWidth) ; UINT32 uArea = 0 ; UINT32 uRows = 0 ; for ( UINT32 r=0 ; r=0 ) { UINT32 uRadius = (UINT32)sqrt(Radius2) ; aLeft[uRows] = nLine-uRadius ; aRight[uRows] = nLine+uRadius+1 ; uArea += aRight[uRows]-aLeft[uRows] ; uRows++ ; } S-- ; nLine += uBitmapToShadowWidth ; } if ( uRows==0 || uArea==1 ) memcpy( pDLine+uBlur,pSLine+uBlur*2,ProjectedSize.x ) ; else { if ( uLastArea!=uArea || uLastRows!=uRows ) { UINT32 uTableSize = uArea*255 ; UINT32 uInc = 0xffffffffu/uTableSize ; uShift = 0 ; while ( uTableSize>=TABLE_SIZE ) { uTableSize >>= 1 ; uShift++ ; } uInc <<= uShift ; UINT32 uCount = 0 ; for ( i=0 ; i<=uTableSize ; ++i ) { aTranslationTable[i] = uCount>>24 ; uCount += uInc ; } } if ( uLastArea!=uArea || uLastRows!=uRows || uLastBlur!=uThisBlur ) { uLastArea = uArea ; uLastRows = uRows ; uLastBlur = uThisBlur ; #if 0 && defined(__WXMSW__) ::CompileShadowCode( aCode, ProjectedSize.x+uThisBlur*2, uRows,aLeft,aRight, uShift,aTranslationTable ) ; #endif } // Call Gavin's routine to do the shadowing for a single scanline CamProfile cp(CAMPROFILE_SHADOW); ::GenerateFloorShadow( aCode, &SourceBI,pSLine+(uBlur-uThisBlur)*2, &DestBI,pDLine+uBlur-uThisBlur, uRows, aLeft,aRight, uShift, aTranslationTable ) ; } pSLine += uBitmapToShadowWidth ; pDLine += nShadowWidth ; } delete [] pBitmapToShadow; #if 0 KernelBitmap *pBitmap2 = new KernelBitmap(ProjectedSize.x+uBlur*2,ProjectedSize.y+uBlur,8,0,TRUE) ; memcpy( pBitmap2->GetBitmapBits(),pShadowBitmap,nShadowSize ) ; LPRGBQUAD pPalette2 = pBitmap2->GetPaletteForBitmap(); for ( INT32 i=0 ; i<256 ; i++ ) { pPalette2[i].rgbRed = pPalette2[i].rgbGreen = pPalette2[i].rgbBlue = i; } BitmapTranspFillAttribute* pTranspBitmapFill2 = new BitmapTranspFillAttribute; pTranspBitmapFill2->AttachBitmap(pBitmap2); #endif Tilt(pShadowBitmap, ProjectedSize.x+uBlur*2,ProjectedSize.y+uBlur, dTiltAngle); m_OffsetX -= uBlur; delete [] pShadowBitmap; return true; } BOOL CBitmapShadow::CreateShadow(const BOOL bIsWallShadow, const double dProjection, const double dTiltAngle, const double dBlurriness, const double dDarknessCoeff, const double dPositionX, const double dPositionY, UINT32* pForegroundBits, const CNativeSize ForegroundSize ) { RECT ShadowRect; ShadowRect.left =0; ShadowRect.right =0; ShadowRect.top =0; ShadowRect.bottom =0; if(bIsWallShadow) MakeWallShadow (pForegroundBits, ForegroundSize, (INT32)(dPositionX + 0.5), (INT32)(dPositionY + 0.5), dBlurriness, &m_OffsetX, &m_OffsetY, dDarknessCoeff); else MakeCastShadow (pForegroundBits, ForegroundSize, dBlurriness, dTiltAngle, dProjection, dDarknessCoeff); m_bIsWallShadow = bIsWallShadow; m_dBlurriness = dBlurriness; m_dDarknessCoeff = dDarknessCoeff; if(bIsWallShadow) { m_dPositionX = dPositionX; m_dPositionY = dPositionY; } else { m_dPositionX = 0; m_dPositionY = 0; } return true; } //Allocates a bitmap, and returns a pointer to it. //the returned bitmap is black with transparancy values from the specified source sheared by the //specified angle //Modifies the XOffset members to maintain the position of the larger returned bitmap with respect to the source ShadowBitmap* CBitmapShadow::Tilt(BYTE* pSourceBits, const INT32 nSourceWidth, const INT32 nSourceHeight, const double dTiltDegrees) { //Convert the given tilt angle to radians, then get it's tangent const double dTanTiltAngle = tan(dTiltDegrees*2*Pi/360) ; //Find the X offset at the top of the bitmap, this gives the width increase of the //destination bitmap over the source const INT32 nMaxOffset = (INT32)ceil((nSourceHeight-1)*fabs(dTanTiltAngle)) ; //Create the destination bitmap // ShadowBitmap* pDestBitmap = NULL ; CreateFilled(nSourceWidth+nMaxOffset,nSourceHeight,0xff,8); const UINT32 nSWidth = DIBUtil::ScanlineSize(nSourceWidth ,8) ; const UINT32 nDWidth = DIBUtil::ScanlineSize(nSourceWidth+nMaxOffset,8) ; BYTE* pSLine = pSourceBits ; BYTE* pDLine = GetBytes() ; double fXOffset = dTanTiltAngle>0 ? 0 : nMaxOffset ; INT32 nXOffset = 0; UINT32 nXShift = 0; BYTE* pSPtr = NULL; BYTE* pDPtr = NULL; INT32 X=1 ; for ( INT32 Y=0 ; Y> 24) ; for( X=1 ; X> 24) ; pSPtr++ ; } *pDPtr++ = 0xff+((pSPtr[0]-0xff)*nXShift >> 24) ; } else memcpy(pDLine+nXOffset,pSLine,nSWidth) ; pSLine += nSWidth ; pDLine += nDWidth ; fXOffset += dTanTiltAngle ; } if ( dTanTiltAngle<0 ) m_OffsetX -= nMaxOffset; return this ; } /*************************************************************************************************************************** > static bool CBitmapShadow::ContourBitmap( const LPBITMAPINFO pSrcInfo32, const LPBYTE pSrcBits32, const double fContour, const BYTE uThreshold, LPBITMAPINFO* ppDestInfo32, LPBYTE* ppDestBits32, INT32* pnOffsetX, INT32* pnOffsetY ) Author: Gavin_Theobald (Xara Group Ltd) Created: 24/11/2004 Inputs: pSrcInfo32 Ptr to 32bpp source bitmap info. pSrcBits32 Ptr to 32bpp source bitmap bits. fContour Contour size, in pixels. uThreshold Grey levels greater than or equal to this are considered transparent. ppDestInfo8 Ptr to ptr to 32bpp destination bitmap info. ppDestBits8 Ptr to ptr to 32bpp destination bitmap bits. pnOffsetX,pnOffsetY On return, set to amount by which the destination bitmap must be offset in comparison to the source bitmap. Outputs: true if succesful. Purpose: Contour the given source bitmap and, putting the result into the destination bitmap. Transparency is removed from the source bitmap, although antialiasing is retained. Errors: See also: **************************************************************************************************************************/ //#define DISPLAY_CONTOUR #define ALLOW_HALF_OFFSET bool CBitmapShadow::ContourBitmap( const LPBITMAPINFO pSrcInfo32, const LPBYTE pSrcBits32, #if _DEBUG double fContour, #else const double fContour, #endif const BYTE uThreshold, LPBITMAPINFO* ppDestInfo32, LPBYTE* ppDestBits32, double* pfOffsetX, double* pfOffsetY ) { #if _DEBUG if ( fContour>MAX_CONTOUR ) fContour = MAX_CONTOUR ; else if ( fContour<0.1 ) fContour = 0.1 ; #else if ( fContour>MAX_CONTOUR ) return false ; #endif #ifdef ALLOW_HALF_OFFSET const UINT32 uContour = UINT32(ceil(2*fContour)) ; #else const UINT32 uContour = UINT32(ceil(fContour)*2) ; #endif UINT32 uSrcWidth32 = pSrcInfo32->bmiHeader.biWidth ; UINT32 uSrcHeight32 = pSrcInfo32->bmiHeader.biHeight ; /*UINT32 uSrcByteWidth32 =*/ DIBUtil::ScanlineSize(uSrcWidth32,32) ; // // Create bitmap that is copy of the source T channel but with // a 1 pixel transparent surround. // // All pixels greater than uThreshold are made fully transparent. // LPBYTE pSBits8 ; LPBITMAPINFO pSInfo8 = ::AllocDIB(uSrcWidth32+2,uSrcHeight32+2,8,&pSBits8) ; if ( !pSInfo8 ) return false ; UINT32 uSWidth8 = pSInfo8->bmiHeader.biWidth ; UINT32 uSHeight8 = pSInfo8->bmiHeader.biHeight ; UINT32 uSByteWidth8 = DIBUtil::ScanlineSize(uSWidth8,8) ; memset(pSBits8,0xff,uSByteWidth8*uSHeight8) ; LPBYTE pSrc = pSrcBits32+3 ; LPBYTE pDst = pSBits8+uSByteWidth8+1 ; UINT32 i,j ; for ( j=0 ; jGetPaletteForBitmap(); for ( i=0 ; i<0x100 ; i++ ) (UINT32&)pPalette[i] = i*0x010101 ; pkbmpSBitmap->AttachDebugCopyToCurrentDocument("Contour bitmap 1") ; pwbmpSBitmap->BMBytes = ((WinBitmap*)OILBitmap::Default)->BMBytes ; delete pkbmpSBitmap ; } #endif // // Create bitmap that is the size of the source but with // a 1 pixel surround. Pixels are set if they have four non-transparent // neighbours. // LPBYTE pNBits8 ; LPBITMAPINFO pNInfo8 = ::AllocDIB(uSWidth8,uSHeight8,8,&pNBits8) ; if ( !pNInfo8 ) { ::FreeDIB(pSInfo8,pSBits8) ; return false ; } memset(pNBits8,0x00,uSByteWidth8*uSHeight8) ; pSrc = pSBits8+uSByteWidth8+1 ; pDst = pNBits8+uSByteWidth8+1 ; for ( j=0 ; jGetPaletteForBitmap(); (UINT32&)pPalette[0x00] = 0x00000000 ; (UINT32&)pPalette[0xff] = 0x00ffffff ; for ( i=0x01 ; i<0xff ; i++ ) (UINT32&)pPalette[i] = 0x000000ff ; pkbmpSBitmap->AttachDebugCopyToCurrentDocument("Contour bitmap 2"); pwbmpSBitmap->BMBytes = ((WinBitmap*)OILBitmap::Default)->BMBytes ; delete pkbmpSBitmap ; } #endif // // Now create bitmap that is the size of the source bitmap but with a border of // uContour-1 transparent pixels around it. Insert the last bitmap but make // semi-transparent areas opaque but preserve antialiasing. We recognise semi-transparent // areas as having 4 non-transparent neighbours and antialiasing as having from 1 to 3 // non-transparent neighbours. // LPBYTE pBits8 ; LPBITMAPINFO pInfo8 = ::AllocDIB(uSrcWidth32+uContour*2,uSrcHeight32+uContour*2,8,&pBits8) ; if ( !pInfo8 ) { ::FreeDIB(pSInfo8,pSBits8) ; ::FreeDIB(pNInfo8,pNBits8) ; return false ; } UINT32 uWidth8 = pInfo8->bmiHeader.biWidth ; UINT32 uHeight8 = pInfo8->bmiHeader.biHeight ; UINT32 uByteWidth8 = DIBUtil::ScanlineSize(uWidth8,8) ; memset(pBits8,0xff,uByteWidth8*uHeight8) ; LPBYTE pSSrc = pSBits8+uSByteWidth8+1 ; LPBYTE pNSrc = pNBits8+uSByteWidth8+1 ; pDst = pBits8+(uByteWidth8+1)*uContour ; for ( j=0 ; j0xff ) b = 0x00 ; } } } } pSBits++ ; pNBits++ ; pDst[i] = b ; } pSSrc += uSByteWidth8 ; pNSrc += uSByteWidth8 ; pDst += uByteWidth8 ; } ::FreeDIB(pSInfo8,pSBits8) ; ::FreeDIB(pNInfo8,pNBits8) ; #if defined(_DEBUG) && defined(DISPLAY_CONTOUR) { WinBitmap* pwbmpSBitmap = new WinBitmap(pInfo8,pBits8) ; KernelBitmap* pkbmpSBitmap = new KernelBitmap(pwbmpSBitmap,TRUE) ; LPRGBQUAD pPalette = pkbmpSBitmap->GetPaletteForBitmap(); for ( i=0 ; i<0x100 ; i++ ) (UINT32&)pPalette[i] = i*0x010101 ; pkbmpSBitmap->AttachDebugCopyToCurrentDocument("Contour bitmap 3"); pwbmpSBitmap->BMBytes = ((WinBitmap*)OILBitmap::Default)->BMBytes ; delete pkbmpSBitmap ; } #endif #if 0 *ppDestInfo8 = pInfo8 ; *ppDestBits8 = pBits8 ; *pfOffsetX = -uContour ; *pfOffsetY = -uContour ; #else // // Now create bitmap that is the size of the source but with a border of half the // contour size. This is the bitmap in which we will create the contoured image. // LPBYTE pDBits8 ; LPBITMAPINFO pDInfo8 = ::AllocDIB(uSrcWidth32+uContour,uSrcHeight32+uContour,8,&pDBits8) ; if ( !pDInfo8 ) { ::FreeDIB(pInfo8,pBits8) ; return false ; } { CamProfile cp(CAMPROFILE_SHADOW); ::ContourBitmap(pBits8,uByteWidth8, pDBits8,pDInfo8, fContour,uContour); } ::FreeDIB(pInfo8,pBits8) ; #if defined(_DEBUG) && defined(DISPLAY_CONTOUR) { WinBitmap* pwbmpSBitmap = new WinBitmap(pDInfo8,pDBits8) ; KernelBitmap* pkbmpSBitmap = new KernelBitmap(pwbmpSBitmap,TRUE) ; LPRGBQUAD pPalette = pkbmpSBitmap->GetPaletteForBitmap(); for ( i=0 ; i<0x100 ; i++ ) (UINT32&)pPalette[i] = i*0x010101 ; pkbmpSBitmap->AttachDebugCopyToCurrentDocument("Contour bitmap 4"); pwbmpSBitmap->BMBytes = ((WinBitmap*)OILBitmap::Default)->BMBytes ; delete pkbmpSBitmap ; } #endif // // Now create final bitmap. This is simply a 32bpp copy of the last bitmap. // UINT32 uDWidth8 = pDInfo8->bmiHeader.biWidth ; UINT32 uDHeight8 = pDInfo8->bmiHeader.biHeight ; UINT32 uDByteWidth8 = DIBUtil::ScanlineSize(uDWidth8,8) ; LPBYTE pDBits32 ; LPBITMAPINFO pDInfo32 = ::AllocDIB(uDWidth8,uDHeight8,32,&pDBits32) ; if ( !pDInfo32 ) { ::FreeDIB(pDInfo8,pDBits8) ; return false ; } memset(pDBits32,0x00,uDWidth8*uDHeight8<<2) ; pSrc = pDBits8 ; pDst = pDBits32+3 ; for ( j=0 ; j static bool CBitmapShadow::ContourBitmap( const LPBITMAPINFO pSrcInfo8, const LPBYTE pSrcBits8, double fContour, const bool bInside, const BYTE uThreshold, LPBITMAPINFO* ppDestInfo8, LPBYTE* ppDestBits8, INT32* pnOffsetX, INT32* pnOffsetY ) Author: Gavin_Theobald (Xara Group Ltd) Created: 20/04/2005 Inputs: pSrcInfo8 Ptr to 8bpp source bitmap info. pSrcBits8 Ptr to 8bpp source bitmap bits. fContour Contour size, in pixels. bInside Set to contour inside rather than outside the image uThreshold Grey levels greater than or equal to this are considered transparent. ppDestInfo8 Ptr to ptr to 8bpp destination bitmap info. ppDestBits8 Ptr to ptr to 8bpp destination bitmap bits. pnOffsetX,pnOffsetY On return, set to amount by which the destination bitmap must be offset in comparison to the source bitmap. Outputs: true if succesful. Purpose: Contour the given source bitmap and, putting the result into the destination bitmap. Transparency is removed from the source bitmap, although antialiasing is retained. Even if successful the destination info and bitmap may be returned as NULL if the result is empty. This is only possible if contouring inside. Errors: See also: **************************************************************************************************************************/ //#define DISPLAY_CONTOUR #define ALLOW_HALF_OFFSET bool CBitmapShadow::ContourBitmap( const LPBITMAPINFO pSrcInfo8, const LPBYTE pSrcBits8, #if _DEBUG double fContour, #else const double fContour, #endif const bool bInside, const BYTE uThreshold, LPBITMAPINFO* ppDestInfo8, LPBYTE* ppDestBits8, double* pfOffsetX, double* pfOffsetY ) { #if _DEBUG if ( fContour>MAX_CONTOUR ) fContour = MAX_CONTOUR ; else if ( fContour<0.1 ) fContour = 0.1 ; #else if ( fContour>MAX_CONTOUR ) return false ; #endif #ifdef ALLOW_HALF_OFFSET const UINT32 uContour = UINT32(ceil(2*fContour)) ; #else const UINT32 uContour = UINT32(ceil(fContour)*2) ; #endif #if defined(_DEBUG) && defined(DISPLAY_CONTOUR) && 0 { WinBitmap* pwbmpSBitmap = new WinBitmap(pSrcInfo8,pSrcBits8) ; KernelBitmap* pkbmpSBitmap = new KernelBitmap(pwbmpSBitmap,TRUE) ; LPRGBQUAD pPalette = pkbmpSBitmap->GetPaletteForBitmap(); for ( UINT32 i=0 ; i<0x100 ; i++ ) (UINT32&)pPalette[i] = i*0x010101 ; pkbmpSBitmap->AttachDebugCopyToCurrentDocument("Contour bitmap source"); pwbmpSBitmap->BMBytes = ((WinBitmap*)OILBitmap::Default)->BMBytes ; delete pkbmpSBitmap ; } #endif UINT32 uSrcWidth8 = pSrcInfo8->bmiHeader.biWidth ; UINT32 uSrcHeight8 = pSrcInfo8->bmiHeader.biHeight ; UINT32 uSrcByteWidth8 = DIBUtil::ScanlineSize(uSrcWidth8,8) ; if ( bInside && (uSrcWidth8<=uContour || uSrcHeight8<=uContour) ) { *ppDestInfo8 = NULL ; *ppDestBits8 = NULL ; *pfOffsetX = 0 ; *pfOffsetY = 0 ; return true ; } // // Create bitmap that is copy of the source but with // a 1 pixel transparent surround. // // All pixels greater than uThreshold are made fully transparent. // LPBYTE pSBits8 ; LPBITMAPINFO pSInfo8 = ::AllocDIB(uSrcWidth8+2,uSrcHeight8+2,8,&pSBits8) ; if ( !pSInfo8 ) return false ; UINT32 uSWidth8 = pSInfo8->bmiHeader.biWidth ; UINT32 uSHeight8 = pSInfo8->bmiHeader.biHeight ; UINT32 uSByteWidth8 = DIBUtil::ScanlineSize(uSWidth8,8) ; LPBYTE pSrc = pSrcBits8 ; LPBYTE pDst = pSBits8+uSByteWidth8+1 ; UINT32 i,j ; memset(pSBits8,0xff,uSByteWidth8*uSHeight8) ; for ( j=0 ; jGetPaletteForBitmap(); for ( i=0 ; i<0x100 ; i++ ) (UINT32&)pPalette[i] = i*0x010101 ; pkbmpSBitmap->AttachDebugCopyToCurrentDocument("Contour bitmap 1") ; pwbmpSBitmap->BMBytes = ((WinBitmap*)OILBitmap::Default)->BMBytes ; delete pkbmpSBitmap ; } #endif // // Create bitmap that is the size of the source but with // a 1 pixel surround. Pixels are set if they have four non-transparent // neighbours. // LPBYTE pNBits8 ; LPBITMAPINFO pNInfo8 = ::AllocDIB(uSWidth8,uSHeight8,8,&pNBits8) ; if ( !pNInfo8 ) { ::FreeDIB(pSInfo8,pSBits8) ; return false ; } memset(pNBits8,0x00,uSByteWidth8*uSHeight8) ; pSrc = pSBits8+uSByteWidth8+1 ; pDst = pNBits8+uSByteWidth8+1 ; for ( j=0 ; jGetPaletteForBitmap(); (UINT32&)pPalette[0x00] = 0x00000000 ; (UINT32&)pPalette[0xff] = 0x00ffffff ; for ( i=0x01 ; i<0xff ; i++ ) (UINT32&)pPalette[i] = 0x000000ff ; pkbmpSBitmap->AttachDebugCopyToCurrentDocument("Contour bitmap 2"); pwbmpSBitmap->BMBytes = ((WinBitmap*)OILBitmap::Default)->BMBytes ; delete pkbmpSBitmap ; } #endif // // Now create bitmap that is the size of the source bitmap but with a border of // uContour-1 transparent pixels around it. Insert the last bitmap but make // semi-transparent areas opaque but preserve antialiasing. We recognise semi-transparent // areas as having 4 non-transparent neighbours and antialiasing as having from 1 to 3 // non-transparent neighbours. // LPBYTE pBits8 ; LPBITMAPINFO pInfo8 = bInside ? ::AllocDIB(uSrcWidth8 ,uSrcHeight8 ,8,&pBits8) : ::AllocDIB(uSrcWidth8+uContour*2,uSrcHeight8+uContour*2,8,&pBits8) ; if ( !pInfo8 ) { ::FreeDIB(pSInfo8,pSBits8) ; ::FreeDIB(pNInfo8,pNBits8) ; return false ; } UINT32 uWidth8 = pInfo8->bmiHeader.biWidth ; UINT32 uHeight8 = pInfo8->bmiHeader.biHeight ; UINT32 uByteWidth8 = DIBUtil::ScanlineSize(uWidth8,8) ; if ( !bInside ) memset(pBits8,0xff,uByteWidth8*uHeight8) ; LPBYTE pSSrc = pSBits8+uSByteWidth8+1 ; LPBYTE pNSrc = pNBits8+uSByteWidth8+1 ; pDst = bInside ? pBits8 : pBits8+(uByteWidth8+1)*uContour ; for ( j=0 ; j0xff ) b = 0x00 ; } } } } pSBits++ ; pNBits++ ; pDst[i] = b ; } pSSrc += uSByteWidth8 ; pNSrc += uSByteWidth8 ; pDst += uByteWidth8 ; } ::FreeDIB(pSInfo8,pSBits8) ; ::FreeDIB(pNInfo8,pNBits8) ; #if defined(_DEBUG) && defined(DISPLAY_CONTOUR) { WinBitmap* pwbmpSBitmap = new WinBitmap(pInfo8,pBits8) ; KernelBitmap* pkbmpSBitmap = new KernelBitmap(pwbmpSBitmap,TRUE) ; LPRGBQUAD pPalette = pkbmpSBitmap->GetPaletteForBitmap(); for ( i=0 ; i<0x100 ; i++ ) (UINT32&)pPalette[i] = i*0x010101 ; pkbmpSBitmap->AttachDebugCopyToCurrentDocument("Contour bitmap 3"); pwbmpSBitmap->BMBytes = ((WinBitmap*)OILBitmap::Default)->BMBytes ; delete pkbmpSBitmap ; } #endif if ( bInside ) { UINT32 uSize = uByteWidth8*uHeight8>>2 ; DWORD* p = (DWORD*)pBits8 ; for ( i=0 ; iGetPaletteForBitmap(); for ( i=0 ; i<0x100 ; i++ ) (UINT32&)pPalette[i] = i*0x010101 ; pkbmpSBitmap->AttachDebugCopyToCurrentDocument("Contour bitmap 3I"); pwbmpSBitmap->BMBytes = ((WinBitmap*)OILBitmap::Default)->BMBytes ; delete pkbmpSBitmap ; } #endif } // // Now create bitmap that is the size of the source but with a border of half the // contour size. This is the bitmap in which we will create the contoured image. // LPBYTE pDBits8 ; LPBITMAPINFO pDInfo8 = ::AllocDIB(uWidth8-uContour,uHeight8-uContour,8,&pDBits8) ; if ( !pDInfo8 ) { ::FreeDIB(pInfo8,pBits8) ; return false ; } { CamProfile cp(CAMPROFILE_SHADOW); ::ContourBitmap(pBits8,uByteWidth8, pDBits8,pDInfo8, fContour,uContour); } ::FreeDIB(pInfo8,pBits8) ; #if defined(_DEBUG) && defined(DISPLAY_CONTOUR) { WinBitmap* pwbmpSBitmap = new WinBitmap(pDInfo8,pDBits8) ; KernelBitmap* pkbmpSBitmap = new KernelBitmap(pwbmpSBitmap,TRUE) ; LPRGBQUAD pPalette = pkbmpSBitmap->GetPaletteForBitmap(); for ( i=0 ; i<0x100 ; i++ ) (UINT32&)pPalette[i] = i*0x010101 ; pkbmpSBitmap->AttachDebugCopyToCurrentDocument("Contour bitmap 4"); pwbmpSBitmap->BMBytes = ((WinBitmap*)OILBitmap::Default)->BMBytes ; delete pkbmpSBitmap ; } #endif UINT32 uDWidth8 = pDInfo8->bmiHeader.biWidth ; UINT32 uDHeight8 = pDInfo8->bmiHeader.biHeight ; UINT32 uDByteWidth8 = DIBUtil::ScanlineSize(uDWidth8,8) ; if ( bInside ) { UINT32 uSize = uDByteWidth8*uDHeight8>>2 ; DWORD* p = (DWORD*)pDBits8 ; for ( i=0 ; iGetPaletteForBitmap(); for ( i=0 ; i<0x100 ; i++ ) (UINT32&)pPalette[i] = i*0x010101 ; pkbmpSBitmap->AttachDebugCopyToCurrentDocument("Contour bitmap 5"); pwbmpSBitmap->BMBytes = ((WinBitmap*)OILBitmap::Default)->BMBytes ; delete pkbmpSBitmap ; } #endif *ppDestInfo8 = pDInfo8 ; *ppDestBits8 = pDBits8 ; *pfOffsetX = (bInside?+0.5:-0.5)*uContour ; *pfOffsetY = (bInside?+0.5:-0.5)*uContour ; return true ; } /******************************************************************************************************/ /******************************************************************************************************/ /******************************************************************************************************/ ////////////////////////////////////////////////////////////////////// // Dummy class to maintain consistency between WebStyle and Camelot // DMc 9/6/99 /******************************************************************************************** > ShadowBitmap::ShadowBitmap() Author: David_McClarnon (Xara Group Ltd) Created: 9/6/99 Inputs: - Returns: Purpose: Constructor ********************************************************************************************/ ShadowBitmap::ShadowBitmap() { m_Bytes = NULL; m_Width = 0; m_Height = 0; m_Depth = 0; } /******************************************************************************************** > ShadowBitmap::~ShadowBitmap() Author: David_McClarnon (Xara Group Ltd) Created: 9/6/99 Inputs: - Returns: Purpose: Destructor ********************************************************************************************/ ShadowBitmap::~ShadowBitmap() { if (m_Bytes) { delete [] m_Bytes; m_Bytes = NULL; } } /******************************************************************************************** > BOOL ShadowBitmap::CreateFilled(INT32 Width, INT32 Height, UINT32 value); Author: David_McClarnon (Xara Group Ltd) Created: 9/6/99 Inputs: - Returns: Purpose: Creates a filled bitmap of the given value ********************************************************************************************/ BOOL ShadowBitmap::CreateFilled(INT32 Width, INT32 Height, BYTE value, UINT32 Depth) { m_Depth = Depth; if (m_Bytes) { delete m_Bytes; m_Bytes = NULL; } INT32 ScanlineWidth = DIBUtil::ScanlineSize(Width, Depth); INT32 Size = ScanlineWidth * Height; m_Bytes = new BYTE[Size]; if (!m_Bytes) return FALSE; m_Width = Width; m_Height = Height; memset(m_Bytes,value,Size) ; return TRUE; } /******************************************************************************************** > BOOL ShadowBitmap::Create(INT32 Width, INT32 Height); Author: David_McClarnon (Xara Group Ltd) Created: 9/6/99 Inputs: - Returns: Purpose: Creates a filled bitmap of the given value ********************************************************************************************/ HRESULT ShadowBitmap::Create(INT32 Width, INT32 Height, UINT32 Depth) { m_Depth = Depth; if (m_Bytes) { delete m_Bytes; m_Bytes = NULL; } INT32 ScanlineWidth = DIBUtil::ScanlineSize(Width, Depth); INT32 Size = ScanlineWidth * Height; m_Bytes = new BYTE[Size]; if (!m_Bytes) return FALSE; m_Width = Width; m_Height = Height; return S_OK; } /******************************************************************************************** > BOOL ShadowBitmap::Create8BitBitmap(UINT32 * pBits, UINT32 Width, UINT32 Height) Author: David_McClarnon (Xara Group Ltd) Created: 14/9/99 Inputs: - Returns: Purpose: Creates an 8 bit bitmap from a 32 bit bitmap (out of the alpha channel) ********************************************************************************************/ BOOL ShadowBitmap::Create8BitBitmap(UINT32 * pBits, UINT32 Width, UINT32 Height) { CreateFilled(Width, Height, 0xff, 8); INT32 Width8 = DIBUtil::ScanlineSize(Width, 8); BYTE* pSrc = (BYTE *)pBits + 3; BYTE* pDest = GetBytes(); BYTE* pSrcNextLine = NULL; BYTE* pDestNextLine = NULL; UINT32 j = 0; for ( UINT32 i = 0; i < Height; i++) { pSrcNextLine = pSrc + Width*4 ; pDestNextLine = pDest+ Width8 ; for ( j=0 ; j