bshadow.cpp

Go to the documentation of this file.
00001 // $Id: bshadow.cpp 1282 2006-06-09 09:46:49Z alex $
00002 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE
00003 ================================XARAHEADERSTART===========================
00004  
00005                Xara LX, a vector drawing and manipulation program.
00006                     Copyright (C) 1993-2006 Xara Group Ltd.
00007        Copyright on certain contributions may be held in joint with their
00008               respective authors. See AUTHORS file for details.
00009 
00010 LICENSE TO USE AND MODIFY SOFTWARE
00011 ----------------------------------
00012 
00013 This file is part of Xara LX.
00014 
00015 Xara LX is free software; you can redistribute it and/or modify it
00016 under the terms of the GNU General Public License version 2 as published
00017 by the Free Software Foundation.
00018 
00019 Xara LX and its component source files are distributed in the hope
00020 that it will be useful, but WITHOUT ANY WARRANTY; without even the
00021 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00022 See the GNU General Public License for more details.
00023 
00024 You should have received a copy of the GNU General Public License along
00025 with Xara LX (see the file GPL in the root directory of the
00026 distribution); if not, write to the Free Software Foundation, Inc., 51
00027 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
00028 
00029 
00030 ADDITIONAL RIGHTS
00031 -----------------
00032 
00033 Conditional upon your continuing compliance with the GNU General Public
00034 License described above, Xara Group Ltd grants to you certain additional
00035 rights. 
00036 
00037 The additional rights are to use, modify, and distribute the software
00038 together with the wxWidgets library, the wxXtra library, and the "CDraw"
00039 library and any other such library that any version of Xara LX relased
00040 by Xara Group Ltd requires in order to compile and execute, including
00041 the static linking of that library to XaraLX. In the case of the
00042 "CDraw" library, you may satisfy obligation under the GNU General Public
00043 License to provide source code by providing a binary copy of the library
00044 concerned and a copy of the license accompanying it.
00045 
00046 Nothing in this section restricts any of the rights you have under
00047 the GNU General Public License.
00048 
00049 
00050 SCOPE OF LICENSE
00051 ----------------
00052 
00053 This license applies to this program (XaraLX) and its constituent source
00054 files only, and does not necessarily apply to other Xara products which may
00055 in part share the same code base, and are subject to their own licensing
00056 terms.
00057 
00058 This license does not apply to files in the wxXtra directory, which
00059 are built into a separate library, and are subject to the wxWindows
00060 license contained within that directory in the file "WXXTRA-LICENSE".
00061 
00062 This license does not apply to the binary libraries (if any) within
00063 the "libs" directory, which are subject to a separate license contained
00064 within that directory in the file "LIBS-LICENSE".
00065 
00066 
00067 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS
00068 ----------------------------------------------
00069 
00070 Subject to the terms of the GNU Public License (see above), you are
00071 free to do whatever you like with your modifications. However, you may
00072 (at your option) wish contribute them to Xara's source tree. You can
00073 find details of how to do this at:
00074   http://www.xaraxtreme.org/developers/
00075 
00076 Prior to contributing your modifications, you will need to complete our
00077 contributor agreement. This can be found at:
00078   http://www.xaraxtreme.org/developers/contribute/
00079 
00080 Please note that Xara will not accept modifications which modify any of
00081 the text between the start and end of this header (marked
00082 XARAHEADERSTART and XARAHEADEREND).
00083 
00084 
00085 MARKS
00086 -----
00087 
00088 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara
00089 designs are registered or unregistered trademarks, design-marks, and/or
00090 service marks of Xara Group Ltd. All rights in these marks are reserved.
00091 
00092 
00093       Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK.
00094                         http://www.xara.com/
00095 
00096 =================================XARAHEADEREND============================
00097  */
00098 #include "camtypes.h"
00099 
00100 #ifdef BUILDSHADOWS
00101 
00102 #include "bshadow.h"
00103 //#include "gconsts.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00104 //#include "dibutil.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00105 //#include "bitmap.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00106 //#include "fillattr.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00107 #include "gdraw.h"
00108 
00109 #include "camprofile.h"
00110 
00111 #if _DEBUG
00112     #include "oilbitmap.h"
00113 #endif
00114 
00115 //#define MMX
00116 //#define SSE2
00117 #define UNALIGNED
00118 
00119 
00120 #pragma warning ( disable : 4554 )
00121 
00122 /******************************************************************************************************/
00123 
00124 // Declare smart memory handling in Debug builds
00125 #define new CAM_DEBUG_NEW
00126 
00127 // CC_IMPLEMENT_DYNCREATE(CBitmapShadow, CCObject)
00128 // CC_IMPLEMENT_DYNCREATE(ShadowBitmap, CCObject)
00129 
00130 /******************************************************************************************************/
00131 
00132 const double Pi = 3.1415926535897932384626433832795 ;
00133 
00134 /******************************************************************************************************/
00135 
00136 // shrink or extend a bitmap in the y direction only (will have same width)
00137 // uses resampling to produce more accurate shrunken bitmap replications.
00138 // Assumes buffers for source and Dest are already defined and of the given dimensions.
00139 // Merges (resamples) just the alpha channels, colour taken from a spot check
00140 
00141 bool CBitmapShadow::ProjectShadow(BYTE* pSBitmap, BYTE* pDBitmap, UINT32 nWidth, UINT32 nSHeight, UINT32 nDHeight)
00142 {
00143     const UINT32 nWidth0 = DIBUtil::ScanlineSize(nWidth,8) ;
00144     UINT32 j = 0;
00145     UINT32 k = 0;
00146     UINT32 i = 0;
00147     UINT64 nPos = 0;
00148     BYTE* pDPtr = NULL;
00149     BYTE* pSPtr = NULL;
00150     BYTE* pEPtr = NULL;
00151     UINT32 t = 0;
00152     UINT32 nEnd = 0;
00153     UINT32 nStart = 0;
00154     UINT32 nLow = 0;
00155     UINT32 nHgh = 0;
00156 
00157     if ( nSHeight==nDHeight )
00158         memcpy(pDBitmap,pSBitmap,nWidth0*nSHeight) ;
00159     else if ( nSHeight>nDHeight )
00160     {
00161         const UINT64 nStep = (((UINT64)nSHeight<<32)-1)/((UINT64)nDHeight) ;
00162         const UINT32 nScale = (nDHeight<<16)/nSHeight ;
00163         for ( j=0 ; j<nDHeight ; j++ )
00164         {
00165             pSPtr = pSBitmap+UINT32(nPos>>32)*nWidth0 ;
00166             pDPtr  = pDBitmap ;
00167             nStart = UINT32(nPos>>32) ;
00168             nLow   = ~UINT32(nPos)>>16 ;
00169             nPos += nStep ;
00170             nHgh   =  UINT32(nPos)>>16 ;
00171             nEnd = UINT32(nPos>>32) ;
00172             for ( i=0 ; i<nWidth ; i++ )
00173             {
00174                 t = 0 ;
00175                 pEPtr = pSPtr+nWidth0 ;
00176                 for ( k = nStart+1 ; k<nEnd ; k++ )
00177                 {
00178                     t += *pEPtr ;
00179                     pEPtr += nWidth0 ;
00180                 }
00181                 t = (t<<16)+*pSPtr*nLow+*pEPtr*nHgh ;
00182                 *pDPtr++ = BYTE((UInt32x32To64(t,nScale)+0x80000000)>>32) ;
00183                 pSPtr++ ;
00184             }
00185             pDBitmap += nWidth0 ;
00186         }
00187     }
00188     else
00189     {
00190         const UINT64 nStep = ((UINT64)(nSHeight-1)<<32)/((UINT64)(nDHeight-1)) ;
00191         memcpy(pDBitmap,pSBitmap,nWidth0) ;
00192         pDBitmap += nWidth0 ;
00193         UINT32 nScale = 0;
00194         for ( j=2 ; j<nDHeight ; j++ )
00195         {
00196             nPos += nStep ;
00197             pSPtr = pSBitmap+UINT32(nPos>>32)*nWidth0 ;
00198             pDPtr  = pDBitmap ;
00199             nScale = UINT32(nPos)>>8 ;
00200             for ( i=0 ; i<nWidth ; i++ )
00201             {
00202                 *pDPtr++ = (BYTE)(pSPtr[0]+(nScale*(pSPtr[nWidth0]-pSPtr[0])>>24)) ;
00203                 pSPtr++ ;
00204             }
00205             pDBitmap += nWidth0 ;
00206         }
00207         memcpy(pDBitmap,pSBitmap+(nSHeight-1)*nWidth0,nWidth0) ;
00208     }
00209 
00210     return TRUE;
00211 }
00212 
00213 
00214 
00215 CBitmapShadow::CBitmapShadow()
00216 {
00217     m_bIsWallShadow =0;
00218     m_dProjection =0.0;
00219     m_dTiltAngle =0.0;
00220     m_dBlurriness =0.0;
00221     m_dDarknessCoeff =0.0;
00222     m_dPositionX =0.0;
00223     m_dPositionY =0.0;
00224     m_OffsetX =0;
00225     m_OffsetY =0;       
00226 }
00227 
00228 
00229 
00230 BOOL CBitmapShadow::MakeWallShadow (const UINT32* pForegroundBits,
00231                                             const CNativeSize ForegroundSize,
00232                                             const INT32 nXPosition,
00233                                             const INT32 nYPosition,
00234                                             const double fBlur,
00235                                             INT32 *pOffsetX,
00236                                             INT32 *pOffsetY,
00237                                             const double dDarknessCoeff/*=1.0*/)
00238 {
00239     // if the required blur is too small, then just copy the existing bitmap into an 8 bit bitmap.
00240     if ( fBlur < MIN_BLUR_DIAMETER )
00241     {
00242         // set up my bitmap to shadow into
00243         /*HRESULT Result =*/ CreateFilled( ForegroundSize.x,ForegroundSize.y,0xff,8 ) ;
00244         UINT32 DestWidth = DIBUtil::ScanlineSize(ForegroundSize.x,8);
00245         BYTE* pSrc0 = (BYTE *)pForegroundBits + 3;
00246         BYTE* pDest0 = GetBytes();
00247         BYTE* pDest0NextLine = NULL;
00248         INT32 x = 0;
00249 
00250         for (INT32 y = 0; y < ForegroundSize.y; y++)
00251         {
00252             pDest0NextLine = pDest0 + DestWidth;
00253             for (x = 0; x < ForegroundSize.x; x++)
00254             {
00255                 *pDest0++ = *pSrc0;
00256                 pSrc0 += 4;
00257             }
00258             pDest0 = pDest0NextLine;
00259         }
00260         return TRUE;
00261     }
00262 
00263     double fNewBlur = fBlur/2.0 ;
00264     if ( fNewBlur>MAX_SHADOW_BLUR )
00265         fNewBlur = MAX_SHADOW_BLUR ;
00266 //  UINT32 uBlur = (UINT32)fNewBlur ;
00267     UINT32 uBlur = (UINT32)(2*fNewBlur+0.5) - 1;
00268 
00269     // Create the bitmap to pass into gavin's routine
00270     // must be Width + nNewBlur * 4, Height + nNewBlur * 4 in size and each scanline must be DWORD adjusted
00271     UINT32 uBitmapToShadowWidth = DIBUtil::ScanlineSize(ForegroundSize.x+uBlur*2,8);
00272     UINT32 uBitmapToShadowSize = uBitmapToShadowWidth*(ForegroundSize.y+uBlur*2) ;
00273     BYTE* pBitmapToShadow = new BYTE[uBitmapToShadowSize];
00274 
00275     // Now, set up the pointers to do the transfer of bits from one bitmap to the other
00276     // and move the destination pointer into position
00277     BYTE* pSrc  = (BYTE *)pForegroundBits+3 ;
00278     BYTE* pDest = (BYTE *)pBitmapToShadow+(uBitmapToShadowWidth+1)*uBlur;
00279 
00280     memset(pBitmapToShadow, 0xff, uBitmapToShadowSize);
00281 
00282     UINT32 ForegroundScanlineSize = ForegroundSize.x * 4;
00283     
00284     // transfer the source bitmap into this larger bitmap to be shadowed
00285     UINT32 j = 0;
00286     BYTE* pNextDstLine = NULL;
00287     BYTE* pNextSrcLine = NULL;
00288 
00289     for ( UINT32 i=0 ; i<(UINT32)ForegroundSize.y ; i++ )
00290     {
00291         pNextSrcLine = pSrc +ForegroundScanlineSize;
00292         pNextDstLine = pDest+uBitmapToShadowWidth;
00293 
00294         for ( j=0 ; j<(UINT32)ForegroundSize.x ; j++ )
00295         {
00296             *pDest++ = *pSrc;
00297             pSrc += 4;
00298         }
00299         pSrc  = pNextSrcLine;
00300         pDest = pNextDstLine;
00301     }
00302 
00303     // Set up my bitmap to shadow into
00304     /*HRESULT Result =*/ CreateFilled( ForegroundSize.x+uBlur, ForegroundSize.y+uBlur, 0xff , 8);
00305 
00306     // set up the bitmap info headers
00307     BITMAPINFOHEADER SourceBI;
00308     SourceBI.biBitCount = 8;
00309     SourceBI.biWidth    = ForegroundSize.x+uBlur*2;
00310     SourceBI.biHeight   = ForegroundSize.y+uBlur*2;
00311     SourceBI.biPlanes   = 1;
00312 
00313     BITMAPINFOHEADER DestBI;
00314     DestBI.biBitCount = 8;
00315     DestBI.biWidth    = ForegroundSize.x+uBlur;
00316     DestBI.biHeight   = ForegroundSize.y+uBlur;
00317     DestBI.biPlanes   = 1;
00318 
00319     // blur the bitmap.
00320     Blur8BppBitmap( &SourceBI,  pBitmapToShadow,
00321                     &DestBI,    GetBytes(),
00322                     uBitmapToShadowWidth, fNewBlur );
00323 
00324     // don't forget to discard the source bitmap.
00325     delete [] pBitmapToShadow;
00326 
00327     *pOffsetX = nXPosition - (uBlur>>1);
00328     *pOffsetY = nYPosition - (uBlur>>1);
00329     
00330     return true;
00331 }
00332 
00333 
00334 
00335 /********************************************************************************************
00336 
00337 >   static LPBITMAPINFO CBitmapShadow::Feather8BppBitmap(   const double fBlur,
00338                                                             LPBITMAPINFO pSrcInfo,
00339                                                             LPBYTE pSrcBits8,
00340                                                             LPBYTE* ppDestBits  )
00341     Author:     Karim_MacDonald (Xara Group Ltd) <camelotdev@xara.com>
00342     Created:    08/08/2000
00343 
00344     Inputs:     fBlur       the blur diameter - may have a fractional part.
00345                 pSrcInfo    bitmap info for the source bitmap.
00346                 pSrcBits8   the source bitmap bits.
00347                 ppDestBits  ptr to receive the address of the destination bitmap bits.
00348 
00349     Returns:    ptr to the destination bitmap's info structure, or NULL if unsuccessful.
00350 
00351     Purpose:    Convolve the given bitmap with a circular patch of the given blur diameter.
00352 
00353     Notes:      Creates a new bitmap to contain the result of the convolution.
00354 
00355 ********************************************************************************************/
00356 LPBITMAPINFO CBitmapShadow::Feather8BppBitmap(  const double fBlur,
00357                                                 LPBITMAPINFO pSrcInfo,
00358                                                 LPBYTE pSrcBits8,
00359                                                 LPBYTE* ppDestBits)
00360 {
00361     // shout out loud if the blur size is <= zero,
00362     // as we needn't do any feathering in this case.
00363     ERROR3IF(fBlur <= 0,
00364             "CBitmapShadow::Feather8BppBitmap; Feathering code used for zero blur size!");
00365 
00366     // if the blur size is too small, then just return a copy of the passed in bitmap.
00367     if ( fBlur < MIN_BLUR_DIAMETER )
00368     {
00369 // Phil 02/08/2004
00370 // Don't copy vast amounts of memory around, just return the pointers to the input bitmap!
00371         *ppDestBits = pSrcBits8;
00372         return pSrcInfo;
00373 //      LPBITMAPINFO pDestInfo = NULL;
00374 //      BOOL bCopied = DIBUtil::CopyBitmap( pSrcInfo, pSrcBits8,
00375 //                                          &pDestInfo, ppDestBits );
00376 //      if (bCopied)
00377 //          return pDestInfo;
00378 //      else
00379 //          return NULL;
00380 
00381     }
00382 
00383     // work out the appropriate blur radius, and cap it at our max allowed blur size.
00384     double fNewBlur = fBlur / 2.0;
00385     if (fNewBlur > MAX_SHADOW_BLUR)
00386         fNewBlur = MAX_SHADOW_BLUR;
00387     const UINT32 uBlur = UINT32(2*fNewBlur+0.5) ;
00388 
00389     // Size of the source bitmap.
00390     CNativeSize         SrcBmpSize(pSrcInfo->bmiHeader.biWidth, pSrcInfo->bmiHeader.biHeight);
00391 
00392     // size of the destination bitmap.
00393     CNativeSize         DestBmpSize(SrcBmpSize.x - uBlur + 1, SrcBmpSize.y - uBlur + 1);
00394 
00395     // the source bitmap must be 8 bits-per-pixel.
00396     ERROR2IF(   pSrcInfo->bmiHeader.biBitCount != 8, NULL,
00397                 "CBitmapShadow::Shadow8BppBitmap; You must pass an 8bpp bitmap!");
00398 
00399     // the destination bitmap must have a positive width and height.
00400     ERROR2IF(   DestBmpSize.x <= 0 || DestBmpSize.y <= 0, NULL,
00401                 "CBitmapShadow::Feather8BppBitmap; Blur patch bigger than source bitmap!");
00402 
00403     // the source bitmap must also be DWORD aligned.
00404     // DIBUtil::Alloc actually does give DWORD aligned bmp's,
00405     // although the bitmap info header does not reflect this.
00406     UINT32 DWordWidth = DIBUtil::ScanlineSize(SrcBmpSize.x, 8);
00407 
00408 
00410     // Allocate dib for convolved bmp and set up info to pass to convolution function.
00412     // Source bitmap info-header.
00413     BITMAPINFOHEADER SourceBI;
00414     SourceBI.biBitCount = 8;
00415     SourceBI.biWidth    = SrcBmpSize.x;
00416     SourceBI.biHeight   = SrcBmpSize.y;
00417     SourceBI.biPlanes   = 1;
00418 
00419     // Alloc a destination DIB for the convolution.
00420     LPBITMAPINFO pDestInfo = AllocDIB(DestBmpSize.x, DestBmpSize.y, 8, ppDestBits, NULL, TRUE);
00421     ERROR2IF(   pDestInfo == NULL, NULL,
00422                 "CBitmapShadow::Shadow8BppBitmap; Failed to allocate space for new bitmap.");
00423 
00424     pDestInfo->bmiHeader.biXPelsPerMeter = pSrcInfo->bmiHeader.biXPelsPerMeter;
00425     pDestInfo->bmiHeader.biYPelsPerMeter = pSrcInfo->bmiHeader.biYPelsPerMeter;
00426 
00427     Blur8BppBitmap(&SourceBI, pSrcBits8, &pDestInfo->bmiHeader, *ppDestBits, DWordWidth, fNewBlur);
00428 
00429     return pDestInfo;
00430 }
00431 
00432 
00433 
00434 /********************************************************************************************
00435 
00436 >   static void CBitmapShadow::Blur8BppBitmap(  LPBITMAPINFOHEADER pSrcBMIHeader, LPBYTE pSrcBits,
00437                                                 LPBITMAPINFOHEADER pDestBMIHeader, LPBYTE pDestBits,
00438                                                 const UINT32 SWordBitmapWidth, const double fBlur )
00439     Author:     Karim_MacDonald (Xara Group Ltd) <camelotdev@xara.com>
00440     Created:    08/08/2000
00441     Inputs:     pSrcBMIHeader       ptr to a bmiHeader for the source bitmap.
00442                 pSrcBits            ptr to the source bitmap bits.
00443                 pDestBMIHeader      ptr to a bmiHeader for the destination bitmap.
00444                 pDestBits           ptr to the destination bitmap bits.
00445                 SWordBitmapWidth    the width of the bitmap, which must be DWord-aligned.
00446                 fBlur               the blur radius - can be non-integer.
00447 
00448     Outputs:    pDestBits gets the result of blurring the bitmap stored in pSrcBits.
00449 
00450     Purpose:    Blur the given source bitmap and, putting the result into the destination
00451                 bitmap, by convolving the source with a circular patch of the given blur
00452                 radius.
00453     Errors:     
00454     See also:   
00455 
00456 ********************************************************************************************/
00457 void CBitmapShadow::Blur8BppBitmap( LPBITMAPINFOHEADER  pSrcBMIHeader, LPBYTE  pSrcBits,
00458                                     LPBITMAPINFOHEADER pDestBMIHeader, LPBYTE pDestBits,
00459                                     const UINT32 SWordBitmapWidth, const double fBlur )
00460 {
00462     // set up the row & columns for the circular convolution mask //
00464     UINT32 aLeft [MAX_ROW_OFFSETS] ;
00465     UINT32 aRight[MAX_ROW_OFFSETS] ;
00466     UINT32 aLow  [MAX_ROW_OFFSETS] ;
00467     UINT32 aHigh [MAX_ROW_OFFSETS] ;
00468 
00469 //  UINT32 uBlur = (UINT32)fBlur;
00470 //  UINT32 uSize = 1 + 2*uBlur;
00471 //  double S  = uBlur ;
00472 //  UINT32 uLine = 0 ;
00473     const UINT32 uSize = (UINT32)(2*fBlur+0.5) ;
00474     const double R = (uSize+1)*0.5 ;
00475           double S = (uSize-1)*0.5 ;
00476     const double R2 = fBlur*fBlur;
00477     UINT32 uLine = 0 ;
00478     UINT32 uArea = 0 ;
00479     UINT32 uRows = 0 ;
00480     
00481     for ( UINT32 r=0 ; r<uSize ; ++r )
00482     {
00483         double fRadius = R2-S*S ;
00484         if ( fRadius>=0 )
00485         {
00486             fRadius = sqrt(fRadius) ;
00487             const UINT32  uLeft = UINT32(R-fRadius) ;
00488 //          const UINT32 uRight = UINT32(R+fRadius) ;
00489             const UINT32 uRight = uSize-uLeft ;
00490             if ( uLeft<uRight )
00491             {
00492                  aLeft[uRows] =  uLeft+uLine ;
00493                 aRight[uRows] = uRight+uLine ;
00494                   aLow[uRows] =  uLeft*SWordBitmapWidth+r ;
00495                  aHigh[uRows] = uRight*SWordBitmapWidth+r ;
00496                 uArea += uRight-uLeft ;
00497                 uRows++ ;
00498             }
00499         }
00500         S-- ;
00501         uLine += SWordBitmapWidth ;
00502     }
00503 
00504     UINT32 uTableSize = uArea*255 ;
00505     UINT32 uInc = 0xffffffffu/uTableSize ;
00506     UINT32 uShift = 0 ;
00507     while ( uTableSize>=TABLE_SIZE )
00508     {
00509         uTableSize >>= 1 ;
00510         uShift++ ;
00511     }
00512     uInc <<= uShift ;
00513     BYTE* pTranslationTable = new BYTE[uTableSize+1] ;
00514     UINT32 uCount = 0 ;
00515     for ( UINT32 i=0 ; i<=uTableSize ; ++i )
00516     {
00517         pTranslationTable[i] = uCount>>24 ;
00518         uCount += uInc ;
00519     }
00520 
00521 
00523     // call gavin's routine to do the shadowing.
00525     CamProfile cp(CAMPROFILE_SHADOW);
00526     ::GenerateWallShadow(
00527          pSrcBMIHeader,  pSrcBits,
00528         pDestBMIHeader, pDestBits,
00529         uRows, aLeft,aRight,
00530         uRows, aLow ,aHigh ,
00531         uShift,pTranslationTable
00532     ) ; 
00533 
00535     // clean up the translation table.
00537     delete [] pTranslationTable;
00538 }
00539 
00540 
00541 
00542 // Same as the MakeShadow function above
00543 // only this produces a cast floor shadow
00544 // angle is in degrees - leans left + leans right
00545 // DestHeight lenghtens or shortens the shadow
00546 // make DestHeight = SourceHeight for 100% projection
00547 
00548 BOOL CBitmapShadow::MakeCastShadow (UINT32* pForegroundBits,
00549                                             const CNativeSize ForegroundSize,
00550                                             const double fBlur,                                  
00551                                             const double dTiltAngle, 
00552                                             const double dProjection,
00553                                             const double dDarknessCoeff/*=1.0*/ )
00554 {
00555     m_OffsetX = 0;  
00556     m_OffsetY = 0;  
00557     
00558     // Convert the bitmap down from 32bpp to 8bpp.
00559 
00560     UINT32 nForegroundWidth = DIBUtil::ScanlineSize(ForegroundSize.x,8) ;
00561     BYTE* p8BitBitmap = new BYTE[nForegroundWidth*ForegroundSize.y] ;
00562     CONST BYTE* pSrc = (BYTE*)pForegroundBits+3 ;
00563     BYTE* pDst = p8BitBitmap ;
00564     BYTE* pDPtr = NULL;
00565     UINT32 i=0;
00566     UINT32 j;
00567     
00568     for( j = 0 ; j<(UINT32)ForegroundSize.y ; j++ )
00569     {
00570         pDPtr = pDst ;
00571         for ( i=0 ; i<(UINT32)ForegroundSize.x ; i++ )
00572         {
00573             *pDPtr++ = *pSrc ;
00574             pSrc += 4 ;
00575         }
00576         pDst += nForegroundWidth ;
00577     }
00578 
00579     double fNewBlur = fBlur/2.0 ;
00580     if ( fNewBlur>MAX_SHADOW_BLUR )
00581         fNewBlur = MAX_SHADOW_BLUR ;
00582     UINT32 uBlur = (UINT32)fNewBlur ;
00583     
00584     CNativeSize ProjectedSize;
00585     ProjectedSize.x = ForegroundSize.x ;
00586     ProjectedSize.y = (INT32)( ForegroundSize.y*dProjection+0.5 );
00587     if ( ProjectedSize.y==0 )
00588         ProjectedSize.y = 1 ;
00589     if ( ProjectedSize.y+uBlur<2 )
00590         ProjectedSize.y = 2-uBlur ;
00591 
00592     // Create a stretched bitmap, for the projection by
00593     // shrinking/stretching the shadow to the correct projection height.
00594     const INT32 nProjectedSize = nForegroundWidth*ProjectedSize.y;
00595     BYTE* pProjected = new BYTE[nProjectedSize];
00596     ProjectShadow( p8BitBitmap, pProjected, ForegroundSize.x,ForegroundSize.y, ProjectedSize.y) ;
00597 
00598     delete [] p8BitBitmap;
00599 
00600 #if 0
00601     KernelBitmap *pBitmap0 = new KernelBitmap(ProjectedSize.x,ProjectedSize.y,8,0,TRUE) ;
00602     memcpy( pBitmap0->GetBitmapBits(),pProjected,nProjectedSize ) ;
00603     LPRGBQUAD pPalette0 = pBitmap0->GetPaletteForBitmap();
00604     for ( i=0 ; i<256 ; i++ )
00605     {
00606         pPalette0[i].rgbRed   =
00607         pPalette0[i].rgbGreen =
00608         pPalette0[i].rgbBlue  = i;
00609     }
00610     BitmapTranspFillAttribute* pTranspBitmapFill0 = new BitmapTranspFillAttribute;
00611     pTranspBitmapFill0->AttachBitmap(pBitmap0);
00612 #endif
00613 
00614     UINT32 uBitmapToShadowWidth = DIBUtil::ScanlineSize(ProjectedSize.x+uBlur*4,8) ;
00615     UINT32 uBitmapToShadowSize = uBitmapToShadowWidth*(ProjectedSize.y+uBlur*2) ;
00616     BYTE* pBitmapToShadow = new BYTE[uBitmapToShadowSize] ;
00617     memset( pBitmapToShadow, 0xff, uBitmapToShadowSize ) ;
00618     pSrc = pProjected;
00619     pDst = pBitmapToShadow+uBlur*2;
00620     for ( j=0 ; j<(UINT32)ProjectedSize.y ; j++ )
00621     {
00622         memcpy(pDst,pSrc,ProjectedSize.x) ;
00623         pSrc += nForegroundWidth;
00624         pDst += uBitmapToShadowWidth;
00625     }
00626 
00627 #if 0
00628     KernelBitmap *pBitmap1 = new KernelBitmap(ProjectedSize.x+uBlur*4,ProjectedSize.y+uBlur*2,8,0,TRUE) ;
00629     memcpy( pBitmap1->GetBitmapBits(),pBitmapToShadow,uBitmapToShadowSize ) ;
00630     LPRGBQUAD pPalette1 = pBitmap1->GetPaletteForBitmap();
00631     for ( i=0 ; i<256 ; i++ )
00632     {
00633         pPalette1[i].rgbRed   =
00634         pPalette1[i].rgbGreen =
00635         pPalette1[i].rgbBlue  = i;
00636     }
00637     BitmapTranspFillAttribute* pTranspBitmapFill1 = new BitmapTranspFillAttribute;
00638     pTranspBitmapFill1->AttachBitmap(pBitmap1);
00639 #endif
00640 
00641     delete [] pProjected;
00642 
00643     UINT32 nShadowWidth = DIBUtil::ScanlineSize(ProjectedSize.x+uBlur*2,8) ;
00644     const INT32 nShadowSize = nShadowWidth*(ProjectedSize.y+uBlur);
00645     BYTE* pShadowBitmap = new BYTE[nShadowSize];
00646     memset(pShadowBitmap,0xff,nShadowSize);
00647 
00648     // Set up the bitmap info headers
00649     BITMAPINFOHEADER SourceBI;
00650     SourceBI.biBitCount = 8;
00651     SourceBI.biWidth    = ProjectedSize.x+uBlur*4;
00652     SourceBI.biPlanes   = 1;
00653     BITMAPINFOHEADER DestBI;
00654     DestBI.biBitCount = 8;
00655     DestBI.biWidth    = ProjectedSize.x+uBlur*2;
00656     DestBI.biHeight   = 1;
00657     DestBI.biPlanes   = 1;
00658 
00659 #if defined(MMX) || defined(SSE2)
00660     BYTE aCode[40*MAX_ROW_OFFSETS] ;
00661 #else
00662     BYTE aCode[20*MAX_ROW_OFFSETS] ;
00663 #endif
00664     BYTE aTranslationTable[TABLE_SIZE+1] ;
00665     UINT32 uLastArea = 0 ;
00666     UINT32 uLastRows = 0 ;
00667     UINT32 uLastBlur = 0 ;
00668     UINT32 uShift = 0 ;
00669 
00670     const BYTE* pSLine = pBitmapToShadow ;
00671           BYTE* pDLine = pShadowBitmap ;
00672 
00673     for ( j=0 ; j<ProjectedSize.y+uBlur ; j++ )
00674     {
00675         // Set up the row & columns - a round patch
00676 
00677         INT32 aLeft [MAX_ROW_OFFSETS] ;
00678         INT32 aRight[MAX_ROW_OFFSETS] ;
00679 
00680         double fScale = (double)j/(ProjectedSize.y+uBlur-1) ;
00681         double fBlur2 = fScale * fNewBlur;
00682         UINT32 uThisBlur = (UINT32)fBlur2 ;
00683         if ( uThisBlur>j )
00684             uThisBlur = j ;
00685         if ( uThisBlur>uBlur )
00686             uThisBlur = uBlur ;
00687         UINT32 uSize = uThisBlur*2+1 ;
00688         double S = uThisBlur ;
00689         double R2 = fBlur2*fBlur2 ;
00690         INT32 nLine = uThisBlur-INT32(uThisBlur*uBitmapToShadowWidth) ;
00691         UINT32 uArea = 0 ;
00692         UINT32 uRows = 0 ;
00693 
00694         for ( UINT32 r=0 ; r<uSize ; ++r )
00695         {
00696             double Radius2 = R2-S*S ;
00697             if ( Radius2>=0 )
00698             {
00699                 UINT32 uRadius = (UINT32)sqrt(Radius2) ;
00700                  aLeft[uRows] = nLine-uRadius ;
00701                 aRight[uRows] = nLine+uRadius+1 ;
00702                 uArea += aRight[uRows]-aLeft[uRows] ;
00703                 uRows++ ;
00704             }
00705             S-- ;
00706             nLine += uBitmapToShadowWidth ;
00707         }
00708     
00709         if ( uRows==0 || uArea==1 )
00710             memcpy( pDLine+uBlur,pSLine+uBlur*2,ProjectedSize.x ) ;
00711         else
00712         {
00713             if ( uLastArea!=uArea || uLastRows!=uRows )
00714             {
00715                 UINT32 uTableSize = uArea*255 ;
00716                 UINT32 uInc = 0xffffffffu/uTableSize ;
00717                 uShift = 0 ;
00718                 
00719                 while ( uTableSize>=TABLE_SIZE )
00720                 {
00721                     uTableSize >>= 1 ;
00722                     uShift++ ;
00723                 }
00724                 uInc <<= uShift ;
00725                 UINT32 uCount = 0 ;
00726                 
00727                 for ( i=0 ; i<=uTableSize ; ++i )
00728                 {
00729                     aTranslationTable[i] = uCount>>24 ;
00730                     uCount += uInc ;
00731                 }
00732             }
00733             if ( uLastArea!=uArea || uLastRows!=uRows || uLastBlur!=uThisBlur )
00734             {
00735                 uLastArea = uArea ;
00736                 uLastRows = uRows ;
00737                 uLastBlur = uThisBlur ;
00738 #if 0 && defined(__WXMSW__)
00739                 ::CompileShadowCode(
00740                     aCode,
00741                     ProjectedSize.x+uThisBlur*2,
00742                     uRows,aLeft,aRight,
00743                     uShift,aTranslationTable
00744                 ) ;
00745 #endif
00746             }
00747             // Call Gavin's routine to do the shadowing for a single scanline
00748             CamProfile cp(CAMPROFILE_SHADOW);
00749             ::GenerateFloorShadow(
00750                 aCode,
00751                 &SourceBI,pSLine+(uBlur-uThisBlur)*2,
00752                   &DestBI,pDLine+uBlur-uThisBlur,
00753                 uRows, aLeft,aRight,
00754                 uShift, aTranslationTable
00755             ) ;
00756         }
00757         pSLine += uBitmapToShadowWidth ;
00758         pDLine += nShadowWidth ;
00759     }   
00760 
00761     delete [] pBitmapToShadow;
00762 
00763 #if 0
00764     KernelBitmap *pBitmap2 = new KernelBitmap(ProjectedSize.x+uBlur*2,ProjectedSize.y+uBlur,8,0,TRUE) ;
00765     memcpy( pBitmap2->GetBitmapBits(),pShadowBitmap,nShadowSize ) ;
00766     LPRGBQUAD pPalette2 = pBitmap2->GetPaletteForBitmap();
00767     for ( INT32 i=0 ; i<256 ; i++ )
00768     {
00769         pPalette2[i].rgbRed   =
00770         pPalette2[i].rgbGreen =
00771         pPalette2[i].rgbBlue  = i;
00772     }
00773     BitmapTranspFillAttribute* pTranspBitmapFill2 = new BitmapTranspFillAttribute;
00774     pTranspBitmapFill2->AttachBitmap(pBitmap2);
00775 #endif
00776 
00777     Tilt(pShadowBitmap, ProjectedSize.x+uBlur*2,ProjectedSize.y+uBlur, dTiltAngle);
00778     m_OffsetX -= uBlur;
00779     
00780     delete [] pShadowBitmap;
00781 
00782     return true;    
00783 }
00784 
00785 
00786 
00787 BOOL CBitmapShadow::CreateShadow(const BOOL bIsWallShadow,
00788                                  const double dProjection,
00789                                  const double dTiltAngle,
00790                                  const double dBlurriness,
00791                                  const double dDarknessCoeff,
00792                                  const double dPositionX,
00793                                  const double dPositionY,
00794                                  UINT32* pForegroundBits,
00795                                  const CNativeSize ForegroundSize
00796                                  )
00797 {                                       
00798     RECT ShadowRect;
00799     ShadowRect.left =0;
00800     ShadowRect.right =0;
00801     ShadowRect.top =0;
00802     ShadowRect.bottom =0;
00803 
00804     if(bIsWallShadow)
00805         MakeWallShadow (pForegroundBits,
00806                         ForegroundSize,
00807                         (INT32)(dPositionX + 0.5),
00808                         (INT32)(dPositionY + 0.5),
00809                         dBlurriness,
00810                         &m_OffsetX,
00811                         &m_OffsetY,
00812                         dDarknessCoeff);        
00813     else
00814         MakeCastShadow (pForegroundBits,
00815                         ForegroundSize,
00816                         dBlurriness,
00817                         dTiltAngle,
00818                         dProjection,
00819                         dDarknessCoeff);
00820     
00821     m_bIsWallShadow  = bIsWallShadow;
00822     m_dBlurriness    = dBlurriness;
00823     m_dDarknessCoeff = dDarknessCoeff;
00824 
00825     if(bIsWallShadow)
00826     {
00827         m_dPositionX = dPositionX;
00828         m_dPositionY = dPositionY;
00829     }
00830     else
00831     {
00832         m_dPositionX = 0;
00833         m_dPositionY = 0;
00834     }
00835     
00836     return true;
00837 }
00838 
00839 //Allocates a bitmap, and returns a pointer to it.
00840 //the returned bitmap is black with transparancy values from the specified source sheared by the 
00841 //specified angle
00842 //Modifies the XOffset members to maintain the position of the larger returned bitmap with respect to the source
00843 ShadowBitmap* CBitmapShadow::Tilt(BYTE* pSourceBits, const INT32 nSourceWidth, const INT32 nSourceHeight, const double dTiltDegrees)
00844 {
00845     //Convert the given tilt angle to radians, then get it's tangent
00846     const double dTanTiltAngle = tan(dTiltDegrees*2*Pi/360) ;
00847 
00848     //Find the X offset at the top of the bitmap, this gives the width increase of the
00849     //destination bitmap over the source
00850     const INT32 nMaxOffset = (INT32)ceil((nSourceHeight-1)*fabs(dTanTiltAngle)) ;
00851 
00852     //Create the destination bitmap
00853 //  ShadowBitmap* pDestBitmap = NULL ;
00854     CreateFilled(nSourceWidth+nMaxOffset,nSourceHeight,0xff,8);
00855 
00856     const UINT32 nSWidth = DIBUtil::ScanlineSize(nSourceWidth           ,8) ;
00857     const UINT32 nDWidth = DIBUtil::ScanlineSize(nSourceWidth+nMaxOffset,8) ;
00858     BYTE* pSLine = pSourceBits ;
00859     BYTE* pDLine = GetBytes() ;
00860 
00861     double fXOffset = dTanTiltAngle>0 ? 0 : nMaxOffset ;
00862     INT32 nXOffset = 0;
00863     UINT32 nXShift = 0;
00864     BYTE* pSPtr = NULL;
00865     BYTE* pDPtr = NULL;
00866     INT32 X=1 ;
00867 
00868     for ( INT32 Y=0 ; Y<nSourceHeight ; Y++ )
00869     {
00870         nXOffset = (INT32)floor(fXOffset) ;
00871         nXShift = (UINT32)((fXOffset-nXOffset)*0xffffff) ;
00872 
00873         if ( nXShift )
00874         {
00875             pSPtr = pSLine ;
00876             pDPtr = pDLine+nXOffset ;
00877             *pDPtr++ = pSPtr[0]+((0xff-pSPtr[0])*nXShift >> 24) ;
00878 
00879             for( X=1 ; X<nSourceWidth ; X++ )
00880             {
00881                 *pDPtr++ = pSPtr[1]+((pSPtr[0]-pSPtr[1])*nXShift >> 24) ;
00882                 pSPtr++ ;
00883             }
00884             *pDPtr++ = 0xff+((pSPtr[0]-0xff)*nXShift >> 24) ;
00885         }
00886         else
00887             memcpy(pDLine+nXOffset,pSLine,nSWidth) ;
00888         pSLine += nSWidth ;
00889         pDLine += nDWidth ;
00890         fXOffset += dTanTiltAngle ;
00891     }       
00892     if ( dTanTiltAngle<0 )
00893         m_OffsetX -= nMaxOffset;
00894 
00895     return this ;
00896 }
00897 
00898 /***************************************************************************************************************************
00899 
00900 >   static bool CBitmapShadow::ContourBitmap(
00901                         const LPBITMAPINFO  pSrcInfo32,
00902                         const LPBYTE        pSrcBits32,
00903                         const double        fContour,
00904                         const BYTE          uThreshold,
00905                         LPBITMAPINFO*       ppDestInfo32,
00906                         LPBYTE*             ppDestBits32,
00907                         INT32*              pnOffsetX,
00908                         INT32*              pnOffsetY
00909                     )
00910     Author:     Gavin_Theobald (Xara Group Ltd) <camelotdev@xara.com>
00911     Created:    24/11/2004
00912     Inputs:     pSrcInfo32          Ptr to 32bpp source bitmap info.
00913                 pSrcBits32          Ptr to 32bpp source bitmap bits.
00914                 fContour            Contour size, in pixels.
00915                 uThreshold          Grey levels greater than or equal to this are considered transparent.
00916                 ppDestInfo8         Ptr to ptr to 32bpp destination bitmap info.
00917                 ppDestBits8         Ptr to ptr to 32bpp destination bitmap bits.
00918                 pnOffsetX,pnOffsetY On return, set to amount by which the destination bitmap must be
00919                                     offset in comparison to the source bitmap.
00920 
00921     Outputs:    true if succesful.
00922 
00923     Purpose:    Contour the given source bitmap and, putting the result into the destination
00924                 bitmap. Transparency is removed from the source bitmap, although antialiasing is
00925                 retained.
00926     Errors:     
00927     See also:   
00928 
00929 **************************************************************************************************************************/
00930 
00931 //#define DISPLAY_CONTOUR
00932 #define ALLOW_HALF_OFFSET
00933 
00934 bool CBitmapShadow::ContourBitmap(
00935                         const LPBITMAPINFO  pSrcInfo32,
00936                         const LPBYTE        pSrcBits32,
00937 #if _DEBUG
00938                               double        fContour,
00939 #else
00940                         const double        fContour,
00941 #endif
00942                         const BYTE          uThreshold,
00943                         LPBITMAPINFO*       ppDestInfo32,
00944                         LPBYTE*             ppDestBits32,
00945                         double*             pfOffsetX,
00946                         double*             pfOffsetY
00947                     )
00948 {
00949 #if _DEBUG
00950     if ( fContour>MAX_CONTOUR )
00951         fContour = MAX_CONTOUR ;
00952     else if ( fContour<0.1 )
00953         fContour = 0.1 ;
00954 #else
00955     if ( fContour>MAX_CONTOUR )
00956         return false ;
00957 #endif
00958 
00959 #ifdef ALLOW_HALF_OFFSET
00960     const UINT32 uContour = UINT32(ceil(2*fContour)) ;
00961 #else
00962     const UINT32 uContour = UINT32(ceil(fContour)*2) ;
00963 #endif
00964 
00965     UINT32 uSrcWidth32  = pSrcInfo32->bmiHeader.biWidth ;
00966     UINT32 uSrcHeight32 = pSrcInfo32->bmiHeader.biHeight ;
00967     /*UINT32 uSrcByteWidth32 =*/ DIBUtil::ScanlineSize(uSrcWidth32,32) ;
00968     //
00969     // Create bitmap that is copy of the source T channel but with
00970     // a 1 pixel transparent surround.
00971     //
00972     // All pixels greater than uThreshold are made fully transparent.
00973     //
00974     LPBYTE pSBits8 ;
00975     LPBITMAPINFO pSInfo8 = ::AllocDIB(uSrcWidth32+2,uSrcHeight32+2,8,&pSBits8) ;
00976     if ( !pSInfo8 )
00977         return false ;
00978     UINT32 uSWidth8  = pSInfo8->bmiHeader.biWidth ;
00979     UINT32 uSHeight8 = pSInfo8->bmiHeader.biHeight ;
00980     UINT32 uSByteWidth8 = DIBUtil::ScanlineSize(uSWidth8,8) ;
00981     memset(pSBits8,0xff,uSByteWidth8*uSHeight8) ;
00982 
00983     LPBYTE pSrc = pSrcBits32+3 ;
00984     LPBYTE pDst = pSBits8+uSByteWidth8+1 ;
00985     UINT32 i,j ;
00986     for ( j=0 ; j<uSrcHeight32 ; j++ )
00987     {
00988         for ( i=0 ; i<uSrcWidth32 ; i++ )
00989         {
00990             if ( *pSrc<uThreshold )
00991                 pDst[i] = *pSrc ;
00992             pSrc += 4 ;
00993         }
00994         pDst += uSByteWidth8 ;
00995     }
00996 
00997 #if defined(_DEBUG) && defined(DISPLAY_CONTOUR)
00998     {
00999         WinBitmap* pwbmpSBitmap = new WinBitmap(pSInfo8,pSBits8) ;
01000         KernelBitmap* pkbmpSBitmap = new KernelBitmap(pwbmpSBitmap,TRUE) ;
01001         LPRGBQUAD pPalette = pkbmpSBitmap->GetPaletteForBitmap();
01002         for ( i=0 ; i<0x100 ; i++ )
01003             (UINT32&)pPalette[i] = i*0x010101 ;
01004         pkbmpSBitmap->AttachDebugCopyToCurrentDocument("Contour bitmap 1") ;
01005         pwbmpSBitmap->BMBytes = ((WinBitmap*)OILBitmap::Default)->BMBytes ;
01006         delete pkbmpSBitmap ;
01007     }
01008 #endif
01009     //
01010     // Create bitmap that is the size of the source but with
01011     // a 1 pixel surround. Pixels are set if they have four non-transparent
01012     // neighbours.
01013     //
01014     LPBYTE pNBits8 ;
01015     LPBITMAPINFO pNInfo8 = ::AllocDIB(uSWidth8,uSHeight8,8,&pNBits8) ;
01016     if ( !pNInfo8 )
01017     {
01018 		::FreeDIB(pSInfo8,pSBits8) ;
01019         return false ;
01020     }
01021     memset(pNBits8,0x00,uSByteWidth8*uSHeight8) ;
01022 
01023     pSrc = pSBits8+uSByteWidth8+1 ;
01024     pDst = pNBits8+uSByteWidth8+1 ;
01025     for ( j=0 ; j<uSrcHeight32 ; j++ )
01026     {
01027         LPBYTE p = pSrc ;
01028         for ( i=0 ; i<uSrcWidth32 ; i++ )
01029         {
01030             bool c0 = p[-1]                 !=0xff ;
01031             bool c1 = p[+1]                 !=0xff ;
01032             bool c2 = p[-(INT32)uSByteWidth8]!=0xff ;
01033             bool c3 = p[+(INT32)uSByteWidth8]!=0xff ;
01034             p++ ;
01035             pDst[i] = -INT32(c0+c1+c2+c3==4) ;
01036         }
01037         pSrc += uSByteWidth8 ;
01038         pDst += uSByteWidth8 ;
01039     }
01040 
01041 #if defined(_DEBUG) && defined(DISPLAY_CONTOUR)
01042     {
01043         WinBitmap* pwbmpSBitmap = new WinBitmap(pNInfo8,pNBits8) ;
01044         KernelBitmap* pkbmpSBitmap = new KernelBitmap(pwbmpSBitmap,TRUE) ;
01045         LPRGBQUAD pPalette = pkbmpSBitmap->GetPaletteForBitmap();
01046         (UINT32&)pPalette[0x00] = 0x00000000 ;
01047         (UINT32&)pPalette[0xff] = 0x00ffffff ;
01048         for ( i=0x01 ; i<0xff ; i++ )
01049             (UINT32&)pPalette[i] = 0x000000ff ;
01050         pkbmpSBitmap->AttachDebugCopyToCurrentDocument("Contour bitmap 2");
01051         pwbmpSBitmap->BMBytes = ((WinBitmap*)OILBitmap::Default)->BMBytes ;
01052         delete pkbmpSBitmap ;
01053     }
01054 #endif
01055     //
01056     // Now create bitmap that is the size of the source bitmap but with a border of
01057     // uContour-1 transparent pixels around it. Insert the last bitmap but make
01058     // semi-transparent areas opaque but preserve antialiasing. We recognise semi-transparent
01059     // areas as having 4 non-transparent neighbours and antialiasing as having from 1 to 3
01060     // non-transparent neighbours.
01061     //
01062     LPBYTE pBits8 ;
01063     LPBITMAPINFO pInfo8 = ::AllocDIB(uSrcWidth32+uContour*2,uSrcHeight32+uContour*2,8,&pBits8) ;
01064     if ( !pInfo8 )
01065     {
01066 		::FreeDIB(pSInfo8,pSBits8) ;
01067 		::FreeDIB(pNInfo8,pNBits8) ;
01068         return false ;
01069     }
01070     UINT32 uWidth8  = pInfo8->bmiHeader.biWidth ;
01071     UINT32 uHeight8 = pInfo8->bmiHeader.biHeight ;
01072     UINT32 uByteWidth8 = DIBUtil::ScanlineSize(uWidth8,8) ;
01073 
01074     memset(pBits8,0xff,uByteWidth8*uHeight8) ;
01075 
01076     LPBYTE pSSrc = pSBits8+uSByteWidth8+1 ;
01077     LPBYTE pNSrc = pNBits8+uSByteWidth8+1 ;
01078            pDst  =  pBits8+(uByteWidth8+1)*uContour ;
01079     for ( j=0 ; j<uSrcHeight32 ; j++ )
01080     {
01081         BYTE* pSBits = pSSrc ;
01082         BYTE* pNBits = pNSrc ;
01083         for ( i=0 ; i<uSrcWidth32 ; i++ )
01084         {
01085             BYTE b = *pSBits ;
01086             if ( b && b!=0xff )
01087             {
01088                 BYTE c0 = pNBits[-1] ;
01089                 BYTE c1 = pNBits[+1] ;
01090                 BYTE c2 = pNBits[-(INT32)uSByteWidth8] ;
01091                 BYTE c3 = pNBits[+(INT32)uSByteWidth8] ;
01092                 UINT32 c = -(c0+c1+c2+c3) & 0xff ;
01093                 if ( c==4 )
01094                     b = 0x00 ;
01095                 else if ( c )
01096                 {
01097                     UINT32 t = (c0 & pSBits[-1              ])+
01098                              (c1 & pSBits[+1                ])+
01099                              (c2 & pSBits[-(INT32)uSByteWidth8])+
01100                              (c3 & pSBits[+(INT32)uSByteWidth8]) ;
01101                     if ( t )
01102                     {
01103                         static const UINT32 aMul[5] = {0*0xff,1*0xff,2*0xff,3*0xff,4*0xff} ;
01104                         t = aMul[c]-t ;
01105                         if ( t )
01106                         {
01107                             c = (b^0xff)*aMul[c]/t ;        // Could use a float table to replace divide by multiply.
01108                             b = ~c ;
01109                             if ( c>0xff )
01110                                 b = 0x00 ;
01111                         }
01112                     }
01113                 }
01114             }
01115             pSBits++ ;
01116             pNBits++ ;
01117             pDst[i] = b ;
01118         }
01119         pSSrc += uSByteWidth8 ;
01120         pNSrc += uSByteWidth8 ;
01121         pDst  +=  uByteWidth8 ;
01122     }
01123 	::FreeDIB(pSInfo8,pSBits8) ;
01124 	::FreeDIB(pNInfo8,pNBits8) ;
01125 
01126 #if defined(_DEBUG) && defined(DISPLAY_CONTOUR)
01127     {
01128         WinBitmap* pwbmpSBitmap = new WinBitmap(pInfo8,pBits8) ;
01129         KernelBitmap* pkbmpSBitmap = new KernelBitmap(pwbmpSBitmap,TRUE) ;
01130         LPRGBQUAD pPalette = pkbmpSBitmap->GetPaletteForBitmap();
01131         for ( i=0 ; i<0x100 ; i++ )
01132             (UINT32&)pPalette[i] = i*0x010101 ;
01133         pkbmpSBitmap->AttachDebugCopyToCurrentDocument("Contour bitmap 3");
01134         pwbmpSBitmap->BMBytes = ((WinBitmap*)OILBitmap::Default)->BMBytes ;
01135         delete pkbmpSBitmap ;
01136     }
01137 #endif
01138 
01139 #if 0   
01140     *ppDestInfo8 = pInfo8 ;
01141     *ppDestBits8 = pBits8 ;
01142     *pfOffsetX = -uContour ;
01143     *pfOffsetY = -uContour ;
01144 #else
01145     //
01146     // Now create bitmap that is the size of the source but with a border of half the
01147     // contour size. This is the bitmap in which we will create the contoured image.
01148     //
01149     LPBYTE pDBits8 ;
01150     LPBITMAPINFO pDInfo8 = ::AllocDIB(uSrcWidth32+uContour,uSrcHeight32+uContour,8,&pDBits8) ;
01151     if ( !pDInfo8 )
01152     {
01153 		::FreeDIB(pInfo8,pBits8) ;
01154         return false ;
01155     }
01156     {
01157         CamProfile cp(CAMPROFILE_SHADOW);
01158         ::ContourBitmap(pBits8,uByteWidth8, pDBits8,pDInfo8, fContour,uContour);
01159     }
01160 	::FreeDIB(pInfo8,pBits8) ;
01161 
01162 #if defined(_DEBUG) && defined(DISPLAY_CONTOUR)
01163     {
01164         WinBitmap* pwbmpSBitmap = new WinBitmap(pDInfo8,pDBits8) ;
01165         KernelBitmap* pkbmpSBitmap = new KernelBitmap(pwbmpSBitmap,TRUE) ;
01166         LPRGBQUAD pPalette = pkbmpSBitmap->GetPaletteForBitmap();
01167         for ( i=0 ; i<0x100 ; i++ )
01168             (UINT32&)pPalette[i] = i*0x010101 ;
01169         pkbmpSBitmap->AttachDebugCopyToCurrentDocument("Contour bitmap 4");
01170         pwbmpSBitmap->BMBytes = ((WinBitmap*)OILBitmap::Default)->BMBytes ;
01171         delete pkbmpSBitmap ;
01172     }
01173 #endif
01174     //
01175     // Now create final bitmap. This is simply a 32bpp copy of the last bitmap.
01176     //
01177     UINT32 uDWidth8  = pDInfo8->bmiHeader.biWidth ;
01178     UINT32 uDHeight8 = pDInfo8->bmiHeader.biHeight ;
01179     UINT32 uDByteWidth8 = DIBUtil::ScanlineSize(uDWidth8,8) ;
01180 
01181     LPBYTE pDBits32 ;
01182     LPBITMAPINFO pDInfo32 = ::AllocDIB(uDWidth8,uDHeight8,32,&pDBits32) ;
01183     if ( !pDInfo32 )
01184     {
01185 		::FreeDIB(pDInfo8,pDBits8) ;
01186         return false ;
01187     }
01188     memset(pDBits32,0x00,uDWidth8*uDHeight8<<2) ;
01189 
01190     pSrc = pDBits8 ;
01191     pDst = pDBits32+3 ;
01192     for ( j=0 ; j<uDHeight8 ; j++ )
01193     {
01194         for ( i=0 ; i<uDWidth8 ; i++ )
01195         {
01196             *pDst = pSrc[i] ;
01197             pDst += 4 ;
01198         }
01199         pSrc += uDByteWidth8 ;
01200     }
01201 
01202 	::FreeDIB(pDInfo8,pDBits8) ;
01203 
01204     *ppDestInfo32 = pDInfo32 ;
01205     *ppDestBits32 = pDBits32 ;
01206     *pfOffsetX = -0.5*uContour ;
01207     *pfOffsetY = -0.5*uContour ;
01208 #endif
01209     return true ;
01210 }
01211 
01212 /***************************************************************************************************************************
01213 
01214 >   static bool CBitmapShadow::ContourBitmap(
01215                         const LPBITMAPINFO  pSrcInfo8,
01216                         const LPBYTE        pSrcBits8,
01217                         double              fContour,
01218                         const bool          bInside,
01219                         const BYTE          uThreshold,
01220                         LPBITMAPINFO*       ppDestInfo8,
01221                         LPBYTE*             ppDestBits8,
01222                         INT32*              pnOffsetX,
01223                         INT32*              pnOffsetY
01224                     )
01225     Author:     Gavin_Theobald (Xara Group Ltd) <camelotdev@xara.com>
01226     Created:    20/04/2005
01227     Inputs:     pSrcInfo8           Ptr to 8bpp source bitmap info.
01228                 pSrcBits8           Ptr to 8bpp source bitmap bits.
01229                 fContour            Contour size, in pixels.
01230                 bInside             Set to contour inside rather than outside the image
01231                 uThreshold          Grey levels greater than or equal to this are considered transparent.
01232                 ppDestInfo8         Ptr to ptr to 8bpp destination bitmap info.
01233                 ppDestBits8         Ptr to ptr to 8bpp destination bitmap bits.
01234                 pnOffsetX,pnOffsetY On return, set to amount by which the destination bitmap must be
01235                                     offset in comparison to the source bitmap.
01236 
01237     Outputs:    true if succesful.
01238 
01239     Purpose:    Contour the given source bitmap and, putting the result into the destination
01240                 bitmap. Transparency is removed from the source bitmap, although antialiasing is
01241                 retained.
01242 
01243                 Even if successful the destination info and bitmap may be returned as NULL if the
01244                 result is empty. This is only possible if contouring inside.
01245 
01246     Errors:     
01247     See also:   
01248 
01249 **************************************************************************************************************************/
01250 
01251 //#define DISPLAY_CONTOUR
01252 #define ALLOW_HALF_OFFSET
01253 
01254 bool CBitmapShadow::ContourBitmap(
01255                         const LPBITMAPINFO  pSrcInfo8,
01256                         const LPBYTE        pSrcBits8,
01257 #if _DEBUG
01258                               double        fContour,
01259 #else
01260                         const double        fContour,
01261 #endif
01262                         const bool          bInside,
01263                         const BYTE          uThreshold,
01264                         LPBITMAPINFO*       ppDestInfo8,
01265                         LPBYTE*             ppDestBits8,
01266                         double*             pfOffsetX,
01267                         double*             pfOffsetY
01268                     )
01269 {
01270 #if _DEBUG
01271     if ( fContour>MAX_CONTOUR )
01272         fContour = MAX_CONTOUR ;
01273     else if ( fContour<0.1 )
01274         fContour = 0.1 ;
01275 #else
01276     if ( fContour>MAX_CONTOUR )
01277         return false ;
01278 #endif
01279 
01280 #ifdef ALLOW_HALF_OFFSET
01281     const UINT32 uContour = UINT32(ceil(2*fContour)) ;
01282 #else
01283     const UINT32 uContour = UINT32(ceil(fContour)*2) ;
01284 #endif
01285 
01286 #if defined(_DEBUG) && defined(DISPLAY_CONTOUR) && 0
01287     {
01288         WinBitmap* pwbmpSBitmap = new WinBitmap(pSrcInfo8,pSrcBits8) ;
01289         KernelBitmap* pkbmpSBitmap = new KernelBitmap(pwbmpSBitmap,TRUE) ;
01290         LPRGBQUAD pPalette = pkbmpSBitmap->GetPaletteForBitmap();
01291         for ( UINT32 i=0 ; i<0x100 ; i++ )
01292             (UINT32&)pPalette[i] = i*0x010101 ;
01293         pkbmpSBitmap->AttachDebugCopyToCurrentDocument("Contour bitmap source");
01294         pwbmpSBitmap->BMBytes = ((WinBitmap*)OILBitmap::Default)->BMBytes ;
01295         delete pkbmpSBitmap ;
01296     }
01297 #endif
01298 
01299     UINT32 uSrcWidth8  = pSrcInfo8->bmiHeader.biWidth ;
01300     UINT32 uSrcHeight8 = pSrcInfo8->bmiHeader.biHeight ;
01301     UINT32 uSrcByteWidth8 = DIBUtil::ScanlineSize(uSrcWidth8,8) ;
01302 
01303     if ( bInside && (uSrcWidth8<=uContour || uSrcHeight8<=uContour) )
01304     {
01305         *ppDestInfo8 = NULL ;
01306         *ppDestBits8 = NULL ;
01307         *pfOffsetX = 0 ;
01308         *pfOffsetY = 0 ;
01309         return true ;
01310     }
01311     //
01312     // Create bitmap that is copy of the source but with
01313     // a 1 pixel transparent surround.
01314     //
01315     // All pixels greater than uThreshold are made fully transparent.
01316     //
01317     LPBYTE pSBits8 ;
01318     LPBITMAPINFO pSInfo8 = ::AllocDIB(uSrcWidth8+2,uSrcHeight8+2,8,&pSBits8) ;
01319     if ( !pSInfo8 )
01320         return false ;
01321     UINT32 uSWidth8  = pSInfo8->bmiHeader.biWidth ;
01322     UINT32 uSHeight8 = pSInfo8->bmiHeader.biHeight ;
01323     UINT32 uSByteWidth8 = DIBUtil::ScanlineSize(uSWidth8,8) ;
01324 
01325     LPBYTE pSrc = pSrcBits8 ;
01326     LPBYTE pDst =   pSBits8+uSByteWidth8+1 ;
01327     UINT32 i,j ;
01328     memset(pSBits8,0xff,uSByteWidth8*uSHeight8) ;
01329     for ( j=0 ; j<uSrcHeight8 ; j++ )
01330     {
01331         for ( i=0 ; i<uSrcWidth8 ; i++ )
01332             if ( pSrc[i]<uThreshold )
01333                 pDst[i] = pSrc[i] ;
01334         pSrc += uSrcByteWidth8 ;
01335         pDst +=   uSByteWidth8 ;
01336     }
01337 
01338 #if defined(_DEBUG) && defined(DISPLAY_CONTOUR)
01339     {
01340         WinBitmap* pwbmpSBitmap = new WinBitmap(pSInfo8,pSBits8) ;
01341         KernelBitmap* pkbmpSBitmap = new KernelBitmap(pwbmpSBitmap,TRUE) ;
01342         LPRGBQUAD pPalette = pkbmpSBitmap->GetPaletteForBitmap();
01343         for ( i=0 ; i<0x100 ; i++ )
01344             (UINT32&)pPalette[i] = i*0x010101 ;
01345         pkbmpSBitmap->AttachDebugCopyToCurrentDocument("Contour bitmap 1") ;
01346         pwbmpSBitmap->BMBytes = ((WinBitmap*)OILBitmap::Default)->BMBytes ;
01347         delete pkbmpSBitmap ;
01348     }
01349 #endif
01350     //
01351     // Create bitmap that is the size of the source but with
01352     // a 1 pixel surround. Pixels are set if they have four non-transparent
01353     // neighbours.
01354     //
01355     LPBYTE pNBits8 ;
01356     LPBITMAPINFO pNInfo8 = ::AllocDIB(uSWidth8,uSHeight8,8,&pNBits8) ;
01357     if ( !pNInfo8 )
01358     {
01359 		::FreeDIB(pSInfo8,pSBits8) ;
01360         return false ;
01361     }
01362     memset(pNBits8,0x00,uSByteWidth8*uSHeight8) ;
01363     pSrc = pSBits8+uSByteWidth8+1 ;
01364     pDst = pNBits8+uSByteWidth8+1 ;
01365     for ( j=0 ; j<uSrcHeight8 ; j++ )
01366     {
01367         LPBYTE p = pSrc ;
01368         for ( i=0 ; i<uSrcWidth8 ; i++ )
01369         {
01370             INT32 c0 = p[-1]                  !=0xff ;
01371             INT32 c1 = p[+1]                  !=0xff ;
01372             INT32 c2 = p[-(INT32)uSByteWidth8]!=0xff ;
01373             INT32 c3 = p[+(INT32)uSByteWidth8]!=0xff ;
01374             p++ ;
01375             pDst[i] = -INT32(c0+c1+c2+c3==4) ;
01376         }
01377         pSrc += uSByteWidth8 ;
01378         pDst += uSByteWidth8 ;
01379     }
01380 
01381 #if defined(_DEBUG) && defined(DISPLAY_CONTOUR)
01382     {
01383         WinBitmap* pwbmpSBitmap = new WinBitmap(pNInfo8,pNBits8) ;
01384         KernelBitmap* pkbmpSBitmap = new KernelBitmap(pwbmpSBitmap,TRUE) ;
01385         LPRGBQUAD pPalette = pkbmpSBitmap->GetPaletteForBitmap();
01386         (UINT32&)pPalette[0x00] = 0x00000000 ;
01387         (UINT32&)pPalette[0xff] = 0x00ffffff ;
01388         for ( i=0x01 ; i<0xff ; i++ )
01389             (UINT32&)pPalette[i] = 0x000000ff ;
01390         pkbmpSBitmap->AttachDebugCopyToCurrentDocument("Contour bitmap 2");
01391         pwbmpSBitmap->BMBytes = ((WinBitmap*)OILBitmap::Default)->BMBytes ;
01392         delete pkbmpSBitmap ;
01393     }
01394 #endif
01395     //
01396     // Now create bitmap that is the size of the source bitmap but with a border of
01397     // uContour-1 transparent pixels around it. Insert the last bitmap but make
01398     // semi-transparent areas opaque but preserve antialiasing. We recognise semi-transparent
01399     // areas as having 4 non-transparent neighbours and antialiasing as having from 1 to 3
01400     // non-transparent neighbours.
01401     //
01402     LPBYTE pBits8 ;
01403     LPBITMAPINFO pInfo8 = bInside ?
01404 		::AllocDIB(uSrcWidth8         ,uSrcHeight8           ,8,&pBits8) :
01405 		::AllocDIB(uSrcWidth8+uContour*2,uSrcHeight8+uContour*2,8,&pBits8) ;
01406     if ( !pInfo8 )
01407     {
01408 		::FreeDIB(pSInfo8,pSBits8) ;
01409 		::FreeDIB(pNInfo8,pNBits8) ;
01410         return false ;
01411     }
01412     UINT32 uWidth8  = pInfo8->bmiHeader.biWidth ;
01413     UINT32 uHeight8 = pInfo8->bmiHeader.biHeight ;
01414     UINT32 uByteWidth8 = DIBUtil::ScanlineSize(uWidth8,8) ;
01415 
01416     if ( !bInside )
01417         memset(pBits8,0xff,uByteWidth8*uHeight8) ;
01418 
01419     LPBYTE pSSrc = pSBits8+uSByteWidth8+1 ;
01420     LPBYTE pNSrc = pNBits8+uSByteWidth8+1 ;
01421            pDst  = bInside ?
01422                     pBits8 :
01423                     pBits8+(uByteWidth8+1)*uContour ;
01424     for ( j=0 ; j<uSrcHeight8 ; j++ )
01425     {
01426         BYTE* pSBits = pSSrc ;
01427         BYTE* pNBits = pNSrc ;
01428         for ( i=0 ; i<uSrcWidth8 ; i++ )
01429         {
01430             BYTE b = *pSBits ;
01431             if ( b && b!=0xff )
01432             {
01433                 BYTE c0 = pNBits[-1] ;
01434                 BYTE c1 = pNBits[+1] ;
01435                 BYTE c2 = pNBits[-(INT32)uSByteWidth8] ;
01436                 BYTE c3 = pNBits[+(INT32)uSByteWidth8] ;
01437                 UINT32 c = -(c0+c1+c2+c3) & 0xff ;
01438                 if ( c==4 )
01439                     b = 0x00 ;
01440                 else if ( c )
01441                 {
01442                     UINT32 t = (c0 & pSBits[-1                  ])+
01443                                (c1 & pSBits[+1                  ])+
01444                                (c2 & pSBits[-(INT32)uSByteWidth8])+
01445                                (c3 & pSBits[+(INT32)uSByteWidth8]) ;
01446                     if ( t )
01447                     {
01448                         static const UINT32 aMul[5] = {0*0xff,1*0xff,2*0xff,3*0xff,4*0xff} ;
01449                         t = aMul[c]-t ;
01450                         if ( t )
01451                         {
01452                             c = (b^0xff)*aMul[c]/t ;        // Could use a float table to replace divide by multiply.
01453                             b = ~c ;
01454                             if ( c>0xff )
01455                                 b = 0x00 ;
01456                         }
01457                     }
01458                 }
01459             }
01460             pSBits++ ;
01461             pNBits++ ;
01462             pDst[i] = b ;
01463         }
01464         pSSrc += uSByteWidth8 ;
01465         pNSrc += uSByteWidth8 ;
01466         pDst  +=  uByteWidth8 ;
01467     }
01468 	::FreeDIB(pSInfo8,pSBits8) ;
01469 	::FreeDIB(pNInfo8,pNBits8) ;
01470 
01471 #if defined(_DEBUG) && defined(DISPLAY_CONTOUR)
01472     {
01473         WinBitmap* pwbmpSBitmap = new WinBitmap(pInfo8,pBits8) ;
01474         KernelBitmap* pkbmpSBitmap = new KernelBitmap(pwbmpSBitmap,TRUE) ;
01475         LPRGBQUAD pPalette = pkbmpSBitmap->GetPaletteForBitmap();
01476         for ( i=0 ; i<0x100 ; i++ )
01477             (UINT32&)pPalette[i] = i*0x010101 ;
01478         pkbmpSBitmap->AttachDebugCopyToCurrentDocument("Contour bitmap 3");
01479         pwbmpSBitmap->BMBytes = ((WinBitmap*)OILBitmap::Default)->BMBytes ;
01480         delete pkbmpSBitmap ;
01481     }
01482 #endif
01483 
01484     if ( bInside )
01485     {
01486         UINT32 uSize = uByteWidth8*uHeight8>>2 ;
01487         DWORD* p = (DWORD*)pBits8 ;
01488         for ( i=0 ; i<uSize ; i++ )
01489             p[i] = ~p[i] ;
01490     #if defined(_DEBUG) && defined(DISPLAY_CONTOUR) && 0
01491         {
01492             WinBitmap* pwbmpSBitmap = new WinBitmap(pInfo8,pBits8) ;
01493             KernelBitmap* pkbmpSBitmap = new KernelBitmap(pwbmpSBitmap,TRUE) ;
01494             LPRGBQUAD pPalette = pkbmpSBitmap->GetPaletteForBitmap();
01495             for ( i=0 ; i<0x100 ; i++ )
01496                 (UINT32&)pPalette[i] = i*0x010101 ;
01497             pkbmpSBitmap->AttachDebugCopyToCurrentDocument("Contour bitmap 3I");
01498             pwbmpSBitmap->BMBytes = ((WinBitmap*)OILBitmap::Default)->BMBytes ;
01499             delete pkbmpSBitmap ;
01500         }
01501     #endif
01502     }
01503 
01504     //
01505     // Now create bitmap that is the size of the source but with a border of half the
01506     // contour size. This is the bitmap in which we will create the contoured image.
01507     //
01508     LPBYTE pDBits8 ;
01509     LPBITMAPINFO pDInfo8 = ::AllocDIB(uWidth8-uContour,uHeight8-uContour,8,&pDBits8) ;
01510     if ( !pDInfo8 )
01511     {
01512 		::FreeDIB(pInfo8,pBits8) ;
01513         return false ;
01514     }
01515     {
01516         CamProfile cp(CAMPROFILE_SHADOW);
01517         ::ContourBitmap(pBits8,uByteWidth8, pDBits8,pDInfo8, fContour,uContour);
01518     }
01519 	::FreeDIB(pInfo8,pBits8) ;
01520 
01521 #if defined(_DEBUG) && defined(DISPLAY_CONTOUR)
01522     {
01523         WinBitmap* pwbmpSBitmap = new WinBitmap(pDInfo8,pDBits8) ;
01524         KernelBitmap* pkbmpSBitmap = new KernelBitmap(pwbmpSBitmap,TRUE) ;
01525         LPRGBQUAD pPalette = pkbmpSBitmap->GetPaletteForBitmap();
01526         for ( i=0 ; i<0x100 ; i++ )
01527             (UINT32&)pPalette[i] = i*0x010101 ;
01528         pkbmpSBitmap->AttachDebugCopyToCurrentDocument("Contour bitmap 4");
01529         pwbmpSBitmap->BMBytes = ((WinBitmap*)OILBitmap::Default)->BMBytes ;
01530         delete pkbmpSBitmap ;
01531     }
01532 #endif
01533 
01534     UINT32 uDWidth8  = pDInfo8->bmiHeader.biWidth ;
01535     UINT32 uDHeight8 = pDInfo8->bmiHeader.biHeight ;
01536     UINT32 uDByteWidth8 = DIBUtil::ScanlineSize(uDWidth8,8) ;
01537 
01538     if ( bInside )
01539     {
01540         UINT32 uSize = uDByteWidth8*uDHeight8>>2 ;
01541         DWORD* p = (DWORD*)pDBits8 ;
01542         for ( i=0 ; i<uSize ; i++ )
01543             p[i] = ~p[i] ;
01544     }
01545 
01546 #if defined(_DEBUG) && defined(DISPLAY_CONTOUR) && 0
01547     {
01548         WinBitmap* pwbmpSBitmap = new WinBitmap(pDInfo8,pDBits8) ;
01549         KernelBitmap* pkbmpSBitmap = new KernelBitmap(pwbmpSBitmap,TRUE) ;
01550         LPRGBQUAD pPalette = pkbmpSBitmap->GetPaletteForBitmap();
01551         for ( i=0 ; i<0x100 ; i++ )
01552             (UINT32&)pPalette[i] = i*0x010101 ;
01553         pkbmpSBitmap->AttachDebugCopyToCurrentDocument("Contour bitmap 5");
01554         pwbmpSBitmap->BMBytes = ((WinBitmap*)OILBitmap::Default)->BMBytes ;
01555         delete pkbmpSBitmap ;
01556     }
01557 #endif
01558 
01559     *ppDestInfo8 = pDInfo8 ;
01560     *ppDestBits8 = pDBits8 ;
01561     *pfOffsetX = (bInside?+0.5:-0.5)*uContour ;
01562     *pfOffsetY = (bInside?+0.5:-0.5)*uContour ;
01563 
01564     return true ;
01565 }
01566 
01567 /******************************************************************************************************/
01568 /******************************************************************************************************/
01569 /******************************************************************************************************/
01571 // Dummy class to maintain consistency between WebStyle and Camelot
01572 // DMc 9/6/99
01573 
01574 /********************************************************************************************
01575 >   ShadowBitmap::ShadowBitmap()
01576 
01577     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
01578     Created:    9/6/99
01579     Inputs:     -
01580     Returns:    
01581     Purpose:    Constructor
01582 ********************************************************************************************/
01583 
01584 ShadowBitmap::ShadowBitmap()
01585 {
01586     m_Bytes = NULL;
01587     m_Width = 0;
01588     m_Height = 0;
01589     m_Depth = 0;
01590 }
01591 
01592 /********************************************************************************************
01593 >   ShadowBitmap::~ShadowBitmap()
01594 
01595     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
01596     Created:    9/6/99
01597     Inputs:     -
01598     Returns:    
01599     Purpose:    Destructor
01600 ********************************************************************************************/
01601 ShadowBitmap::~ShadowBitmap()
01602 {
01603     if (m_Bytes)
01604     {
01605         delete [] m_Bytes;
01606         m_Bytes = NULL;
01607     }
01608 }
01609 
01610 /********************************************************************************************
01611 >   BOOL ShadowBitmap::CreateFilled(INT32 Width, INT32 Height, UINT32 value);
01612 
01613     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
01614     Created:    9/6/99
01615     Inputs:     -
01616     Returns:    
01617     Purpose:    Creates a filled bitmap of the given value
01618 ********************************************************************************************/
01619 BOOL ShadowBitmap::CreateFilled(INT32 Width, INT32 Height, BYTE value, UINT32 Depth)
01620 {
01621     m_Depth = Depth;
01622     
01623     if (m_Bytes)
01624     {
01625         delete m_Bytes;
01626         m_Bytes = NULL;
01627     }
01628 
01629     INT32 ScanlineWidth = DIBUtil::ScanlineSize(Width, Depth);
01630     INT32 Size        = ScanlineWidth * Height;
01631 
01632     m_Bytes = new BYTE[Size];
01633 
01634     if (!m_Bytes)
01635         return FALSE;
01636 
01637     m_Width = Width;
01638     m_Height = Height;
01639 
01640     memset(m_Bytes,value,Size) ;
01641 
01642     return TRUE;
01643 }
01644 
01645 /********************************************************************************************
01646 >   BOOL ShadowBitmap::Create(INT32 Width, INT32 Height);
01647 
01648     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
01649     Created:    9/6/99
01650     Inputs:     -
01651     Returns:    
01652     Purpose:    Creates a filled bitmap of the given value
01653 ********************************************************************************************/
01654 HRESULT ShadowBitmap::Create(INT32 Width, INT32 Height, UINT32 Depth)
01655 {
01656     m_Depth = Depth;
01657     
01658     if (m_Bytes)
01659     {
01660         delete m_Bytes;
01661         m_Bytes = NULL;
01662     }
01663 
01664     INT32 ScanlineWidth = DIBUtil::ScanlineSize(Width, Depth);
01665     INT32 Size        = ScanlineWidth * Height;
01666 
01667     m_Bytes = new BYTE[Size];
01668 
01669     if (!m_Bytes)
01670         return FALSE;
01671 
01672     m_Width = Width;
01673     m_Height = Height;
01674 
01675     return S_OK;
01676 }
01677 
01678 /********************************************************************************************
01679 >   BOOL ShadowBitmap::Create8BitBitmap(UINT32 * pBits, UINT32 Width, UINT32 Height)
01680 
01681     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
01682     Created:    14/9/99
01683     Inputs:     -
01684     Returns:    
01685     Purpose:    Creates an 8 bit bitmap from a 32 bit bitmap (out of the alpha channel)
01686 ********************************************************************************************/
01687 
01688 BOOL ShadowBitmap::Create8BitBitmap(UINT32 * pBits, UINT32 Width, UINT32 Height)
01689 {
01690     CreateFilled(Width, Height, 0xff, 8);
01691 
01692     INT32 Width8 = DIBUtil::ScanlineSize(Width, 8);
01693 
01694     BYTE* pSrc = (BYTE *)pBits + 3;
01695     BYTE* pDest = GetBytes();
01696     BYTE* pSrcNextLine  = NULL;
01697     BYTE* pDestNextLine = NULL;
01698     UINT32 j = 0;
01699 
01700     for ( UINT32 i = 0; i < Height; i++)
01701     {
01702         pSrcNextLine  = pSrc + Width*4 ;
01703         pDestNextLine = pDest+ Width8 ;
01704 
01705         for ( j=0 ; j<Width; j++ )
01706         {
01707             *pDest = *pSrc;
01708             pDest ++;
01709             pSrc += 4;
01710         }
01711         pSrc = pSrcNextLine;
01712         pDest = pDestNextLine;
01713     }
01714 
01715     return TRUE;
01716 }
01717 
01718 /******************************************************************************************************/
01719 
01720 #endif

Generated on Sat Nov 10 03:44:35 2007 for Camelot by  doxygen 1.4.4