00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098 #include "camtypes.h"
00099
00100 #ifdef BUILDSHADOWS
00101
00102 #include "bshadow.h"
00103
00104
00105
00106
00107 #include "gdraw.h"
00108
00109 #include "camprofile.h"
00110
00111 #if _DEBUG
00112 #include "oilbitmap.h"
00113 #endif
00114
00115
00116
00117 #define UNALIGNED
00118
00119
00120 #pragma warning ( disable : 4554 )
00121
00122
00123
00124
00125 #define new CAM_DEBUG_NEW
00126
00127
00128
00129
00130
00131
00132 const double Pi = 3.1415926535897932384626433832795 ;
00133
00134
00135
00136
00137
00138
00139
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)
00238 {
00239
00240 if ( fBlur < MIN_BLUR_DIAMETER )
00241 {
00242
00243 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
00267 UINT32 uBlur = (UINT32)(2*fNewBlur+0.5) - 1;
00268
00269
00270
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
00276
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
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
00304 CreateFilled( ForegroundSize.x+uBlur, ForegroundSize.y+uBlur, 0xff , 8);
00305
00306
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
00320 Blur8BppBitmap( &SourceBI, pBitmapToShadow,
00321 &DestBI, GetBytes(),
00322 uBitmapToShadowWidth, fNewBlur );
00323
00324
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
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356 LPBITMAPINFO CBitmapShadow::Feather8BppBitmap( const double fBlur,
00357 LPBITMAPINFO pSrcInfo,
00358 LPBYTE pSrcBits8,
00359 LPBYTE* ppDestBits)
00360 {
00361
00362
00363 ERROR3IF(fBlur <= 0,
00364 "CBitmapShadow::Feather8BppBitmap; Feathering code used for zero blur size!");
00365
00366
00367 if ( fBlur < MIN_BLUR_DIAMETER )
00368 {
00369
00370
00371 *ppDestBits = pSrcBits8;
00372 return pSrcInfo;
00373
00374
00375
00376
00377
00378
00379
00380
00381 }
00382
00383
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
00390 CNativeSize SrcBmpSize(pSrcInfo->bmiHeader.biWidth, pSrcInfo->bmiHeader.biHeight);
00391
00392
00393 CNativeSize DestBmpSize(SrcBmpSize.x - uBlur + 1, SrcBmpSize.y - uBlur + 1);
00394
00395
00396 ERROR2IF( pSrcInfo->bmiHeader.biBitCount != 8, NULL,
00397 "CBitmapShadow::Shadow8BppBitmap; You must pass an 8bpp bitmap!");
00398
00399
00400 ERROR2IF( DestBmpSize.x <= 0 || DestBmpSize.y <= 0, NULL,
00401 "CBitmapShadow::Feather8BppBitmap; Blur patch bigger than source bitmap!");
00402
00403
00404
00405
00406 UINT32 DWordWidth = DIBUtil::ScanlineSize(SrcBmpSize.x, 8);
00407
00408
00410
00412
00413 BITMAPINFOHEADER SourceBI;
00414 SourceBI.biBitCount = 8;
00415 SourceBI.biWidth = SrcBmpSize.x;
00416 SourceBI.biHeight = SrcBmpSize.y;
00417 SourceBI.biPlanes = 1;
00418
00419
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
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457 void CBitmapShadow::Blur8BppBitmap( LPBITMAPINFOHEADER pSrcBMIHeader, LPBYTE pSrcBits,
00458 LPBITMAPINFOHEADER pDestBMIHeader, LPBYTE pDestBits,
00459 const UINT32 SWordBitmapWidth, const double fBlur )
00460 {
00462
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
00470
00471
00472
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
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
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
00537 delete [] pTranslationTable;
00538 }
00539
00540
00541
00542
00543
00544
00545
00546
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 )
00554 {
00555 m_OffsetX = 0;
00556 m_OffsetY = 0;
00557
00558
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
00593
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
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
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
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
00840
00841
00842
00843 ShadowBitmap* CBitmapShadow::Tilt(BYTE* pSourceBits, const INT32 nSourceWidth, const INT32 nSourceHeight, const double dTiltDegrees)
00844 {
00845
00846 const double dTanTiltAngle = tan(dTiltDegrees*2*Pi/360) ;
00847
00848
00849
00850 const INT32 nMaxOffset = (INT32)ceil((nSourceHeight-1)*fabs(dTanTiltAngle)) ;
00851
00852
00853
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
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
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 DIBUtil::ScanlineSize(uSrcWidth32,32) ;
00968
00969
00970
00971
00972
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
01011
01012
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
01057
01058
01059
01060
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 ;
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
01147
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
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
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
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
01313
01314
01315
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
01352
01353
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
01397
01398
01399
01400
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 ;
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
01506
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
01572
01573
01574
01575
01576
01577
01578
01579
01580
01581
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
01594
01595
01596
01597
01598
01599
01600
01601 ShadowBitmap::~ShadowBitmap()
01602 {
01603 if (m_Bytes)
01604 {
01605 delete [] m_Bytes;
01606 m_Bytes = NULL;
01607 }
01608 }
01609
01610
01611
01612
01613
01614
01615
01616
01617
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
01647
01648
01649
01650
01651
01652
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
01680
01681
01682
01683
01684
01685
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