ExtCmdIcon.cpp
上传用户:sesekoo
上传日期:2020-07-18
资源大小:21543k
文件大小:243k
源码类别:

界面编程

开发平台:

Visual C++

  1. // This is part of the Professional User Interface Suite library.
  2. // Copyright (C) 2001-2009 FOSS Software, Inc.
  3. // All rights reserved.
  4. //
  5. // http://www.prof-uis.com
  6. // mailto:support@prof-uis.com
  7. //
  8. // This source code can be used, modified and redistributed
  9. // under the terms of the license agreement that is included
  10. // in the Professional User Interface Suite package.
  11. //
  12. // Warranties and Disclaimers:
  13. // THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND
  14. // INCLUDING, BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY,
  15. // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
  16. // IN NO EVENT WILL FOSS SOFTWARE INC. BE LIABLE FOR ANY DIRECT,
  17. // INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES,
  18. // INCLUDING DAMAGES FOR LOSS OF PROFITS, LOSS OR INACCURACY OF DATA,
  19. // INCURRED BY ANY PERSON FROM SUCH PERSON'S USAGE OF THIS SOFTWARE
  20. // EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
  21. #include "StdAfx.h"
  22. #if (!defined __EXT_CMD_ICON_H)
  23. #include <ExtCmdIcon.h>
  24. #endif
  25. #if (!defined __EXT_PAINT_MANAGER_H)
  26. #include <ExtPaintManager.h>
  27. #endif
  28. #if (!defined __EXT_MEMORY_DC_H)
  29. #include <../Src/ExtMemoryDC.h>
  30. #endif
  31. #if (!defined __ExtCmdManager_H)
  32. #include <ExtCmdManager.h>
  33. #endif
  34. #if (!defined __AFXPRIV_H__)
  35. #include <AfxPriv.h>
  36. #endif 
  37. #ifdef _DEBUG
  38. #define new DEBUG_NEW
  39. #undef THIS_FILE
  40. static char THIS_FILE[] = __FILE__;
  41. #endif
  42. /////////////////////////////////////////////////////////////////////////////
  43. // CExtBitmap
  44. CExtBitmap::CExtBitmap()
  45. : m_pImageBuffer( NULL )
  46. {
  47. }
  48. CExtBitmap::CExtBitmap(
  49. const CExtBitmap & other
  50. )
  51. : m_pImageBuffer( NULL )
  52. {
  53. VERIFY( AssignFromOther( other ) );
  54. }
  55. CExtBitmap::~CExtBitmap()
  56. {
  57. Empty();
  58. }
  59. CExtBitmap & CExtBitmap::operator = (
  60. const CExtBitmap & other
  61. )
  62. {
  63. VERIFY( AssignFromOther( other ) );
  64. return (*this);
  65. }
  66. void CExtBitmap::Empty()
  67. {
  68. if( m_pImageBuffer != NULL )
  69. {
  70. stat_FreeHL( m_pImageBuffer );
  71. m_pImageBuffer = NULL;
  72. }
  73. OnContentChanged();
  74. }
  75. bool CExtBitmap::IsEmpty() const
  76. {
  77. return ( ( m_pImageBuffer != NULL ) ? false : true );
  78. }
  79. void CExtBitmap::SerializeUnpacked( CArchive & ar )
  80. {
  81. DWORD dwFlags = 0;
  82. if( ar.IsStoring() )
  83. {
  84. bool bEmpty = IsEmpty();
  85. if( bEmpty )
  86. dwFlags |= 0x00000001;
  87. else
  88. {
  89. if( PreMultipliedRGBChannelsGet() )
  90. {
  91. PreMultiplyRGBChannels( false );
  92. PreMultipliedRGBChannelsSet( false );
  93. }
  94. }
  95. ar << dwFlags;
  96. if( bEmpty )
  97. return;
  98. ASSERT( m_pImageBuffer != NULL );
  99. VERIFY( stat_BmpSave( m_pImageBuffer, ar, true, true ) );
  100. } // if( ar.IsStoring() )
  101. else
  102. {
  103. Empty();
  104. ar >> dwFlags;
  105. if( ( dwFlags & 0x00000001 ) != 0 )
  106. return;
  107. m_pImageBuffer = stat_BmpLoad( ar, true, false );
  108. ASSERT( m_pImageBuffer != NULL );
  109. OnContentChanged();
  110. } // else from if( ar.IsStoring() )
  111. }
  112. bool CExtBitmap::Clipboard_Copy(
  113. HWND hWnd, // = NULL
  114. bool bProvideWinFormat, // = true
  115. bool bProvideExtFormat  // = true
  116. ) const
  117. {
  118. if( ! ( bProvideWinFormat || bProvideExtFormat ) )
  119. return false;
  120. if( PreMultipliedRGBChannelsGet() )
  121. {
  122. CExtBitmap _bmp2;
  123. _bmp2 = *this;
  124. if( _bmp2.IsEmpty() )
  125. return false;
  126. _bmp2.PreMultiplyRGBChannels( false );
  127. _bmp2.PreMultipliedRGBChannelsSet( false );
  128. return _bmp2.Clipboard_Copy( hWnd, bProvideWinFormat, bProvideExtFormat );
  129. }
  130. if( hWnd == NULL )
  131. hWnd = ::GetDesktopWindow();
  132. if( ! ::OpenClipboard( hWnd ) )
  133. return false;
  134. if( ! ::EmptyClipboard() )
  135. {
  136. ::CloseClipboard();
  137. return false;
  138. }
  139. bool bSuccess = false;
  140. if( bProvideExtFormat )
  141. {
  142. CLIPFORMAT cf = Clipboard_GetExtFormat();
  143. if( cf != 0 )
  144. {
  145. try
  146. {
  147. CSharedFile _file;
  148. CArchive ar( &_file, CArchive::store );
  149. ( const_cast < CExtBitmap * > ( this ) ) -> SerializeUnpacked( ar );
  150. ar.Flush();
  151. ar.Close();
  152. HGLOBAL hGlobal = (HGLOBAL) _file.Detach();
  153. ASSERT( hGlobal != NULL );
  154. ::SetClipboardData( cf, hGlobal );
  155. bSuccess = true;
  156. }
  157. catch( CException * pException )
  158. {
  159. pException->Delete();
  160. }
  161. }
  162. }
  163. if( bProvideWinFormat )
  164. {
  165. HBITMAP hBmpCopy = NULL;
  166. COLORREF clrTransparent = RGB( 0, 0, 0 ), * pClrSurface = NULL;
  167. if( ExtractEditableBitmap(
  168. hBmpCopy,
  169. clrTransparent,
  170. NULL,
  171. &pClrSurface
  172. )
  173. )
  174. {
  175. HGLOBAL hGlobal = CExtBitmap::stat_HBITMAPtoHGLOBAL( hBmpCopy );
  176. if( hGlobal != NULL )
  177. {
  178. if( ::SetClipboardData( CF_DIB, hGlobal ) == NULL )
  179. {
  180. ASSERT( FALSE );
  181. }
  182. else
  183. bSuccess = true;
  184. } // if( hGlobal != NULL )
  185. #ifdef _DEBUG
  186. else
  187. {
  188. ASSERT( FALSE );
  189. } // else from if( hGlobal != NULL )
  190. #endif // _DEBUG
  191. ::DeleteObject( hBmpCopy );
  192. }
  193. }
  194. ::CloseClipboard();
  195. return bSuccess;
  196. }
  197. bool CExtBitmap::Clipboard_Paste(
  198. HWND hWnd, // = NULL
  199. bool bProvideWinFormat, // = true
  200. bool bProvideExtFormat  // = true
  201. )
  202. {
  203. Empty();
  204. if( ! ( bProvideWinFormat || bProvideExtFormat ) )
  205. return false;
  206. if( hWnd == NULL )
  207. hWnd = ::GetDesktopWindow();
  208. if( ! ::OpenClipboard( hWnd ) )
  209. return false;
  210. bool bSuccess = false;
  211. if( bProvideExtFormat )
  212. {
  213. CLIPFORMAT cf = Clipboard_GetExtFormat();
  214. if( cf != 0
  215. && ::IsClipboardFormatAvailable( cf )
  216. )
  217. {
  218. HGLOBAL hGlobal = (HGLOBAL) ::GetClipboardData( cf );
  219. if( hGlobal != NULL )
  220. {
  221. CSharedFile _file;
  222. try
  223. {
  224. _file.SetHandle( hGlobal, FALSE );
  225. _file.Seek( 0, CFile::begin );
  226. CArchive ar( &_file, CArchive::load );
  227. SerializeUnpacked( ar );
  228. if( ! IsEmpty() )
  229. bSuccess = true;
  230. }
  231. catch( CException * pException )
  232. {
  233. pException->Delete();
  234. Empty();
  235. }
  236. _file.Detach();
  237. }
  238. }
  239. }
  240. if( ( ! bSuccess )
  241. && bProvideWinFormat
  242. && ( ::IsClipboardFormatAvailable( CF_BITMAP )
  243. || ::IsClipboardFormatAvailable( CF_DIB )
  244. )
  245. )
  246. {
  247. HBITMAP hBmpClipboard = (HBITMAP) ::GetClipboardData( CF_BITMAP );
  248. if( hBmpClipboard != NULL )
  249. {
  250. FromBitmap( hBmpClipboard );
  251. if( ! IsEmpty() )
  252. bSuccess = true;
  253. }
  254. }
  255. ::CloseClipboard();
  256. return bSuccess;
  257. }
  258. bool CExtBitmap::Clipboard_CanCopy(
  259. bool bProvideWinFormat, // = true
  260. bool bProvideExtFormat  // = true
  261. ) const
  262. {
  263. if( ! ( bProvideWinFormat || bProvideExtFormat ) )
  264. return false;
  265. if( IsEmpty() )
  266. return false;
  267. bool bCanCopy = false;
  268. if( bProvideExtFormat )
  269. {
  270. CLIPFORMAT cf = Clipboard_GetExtFormat();
  271. if( cf != 0 )
  272. bCanCopy = true;
  273. }
  274. if( ( ! bCanCopy )
  275. && bProvideWinFormat
  276. )
  277. bCanCopy = true;
  278. return bCanCopy;
  279. }
  280. bool CExtBitmap::Clipboard_CanPaste(
  281. HWND hWnd, // = NULL
  282. bool bProvideWinFormat, // = true
  283. bool bProvideExtFormat  // = true
  284. ) const
  285. {
  286. if( ! ( bProvideWinFormat || bProvideExtFormat ) )
  287. return false;
  288. if( hWnd == NULL )
  289. hWnd = ::GetDesktopWindow();
  290. if( ! ::OpenClipboard( hWnd ) )
  291. return false;
  292. bool bCanPaste = false;
  293. if( bProvideExtFormat )
  294. {
  295. CLIPFORMAT cf = Clipboard_GetExtFormat();
  296. if( cf != 0
  297. && ::IsClipboardFormatAvailable( cf )
  298. )
  299. bCanPaste = true;
  300. }
  301. if( ( ! bCanPaste )
  302. && bProvideWinFormat
  303. && ( ::IsClipboardFormatAvailable( CF_BITMAP )
  304. || ::IsClipboardFormatAvailable( CF_DIB )
  305. )
  306. )
  307. bCanPaste = true;
  308. ::CloseClipboard();
  309. return bCanPaste;
  310. }
  311. __EXT_MFC_SAFE_LPCTSTR CExtBitmap::g_strExtBitmapClipboardFormatName = _T("ProfUIS-ExtBitmap");
  312. CLIPFORMAT CExtBitmap::Clipboard_GetExtFormat() const
  313. {
  314. static CLIPFORMAT g_cf;
  315. if( g_cf != 0 )
  316. return g_cf;
  317. CExtSafeString str = Clipboard_GetExtFormatName();
  318. if( str.IsEmpty() )
  319. return 0;
  320. g_cf = (CLIPFORMAT) ::RegisterClipboardFormat( LPCTSTR(str) );
  321. return g_cf;
  322. }
  323. CExtSafeString CExtBitmap::Clipboard_GetExtFormatName() const
  324. {
  325. CExtSafeString str;
  326. str = g_strExtBitmapClipboardFormatName;
  327. return str;
  328. }
  329. bool CExtBitmap::Process(
  330. LONG * pMatrix,
  331. LONG nMatrixSize,
  332. LONG nFactor,
  333. LONG nOffset,
  334. LPCRECT pRect // = NULL
  335. )
  336. {
  337. if( IsEmpty() )
  338. return false;
  339. if( PreMultipliedRGBChannelsGet() )
  340. {
  341. PreMultiplyRGBChannels( false );
  342. PreMultipliedRGBChannelsSet( false );
  343. }
  344. CExtBitmap _bmpBuffer = (*this);
  345. if( _bmpBuffer.IsEmpty() )
  346. return false;
  347. RGBQUAD _pixel;
  348. LONG nX, nY, nRed, nGreen, nBlue,
  349. nMatrixValue, nMatrixX, nMatrixY,
  350. nHalfMatrixSize = nMatrixSize/2;
  351. LONG nMaxMatrixReview = nMatrixSize - nHalfMatrixSize;
  352. CRect rcReview( 0, 0, 0, 0 );
  353. if( pRect != NULL )
  354. rcReview = (*pRect);
  355. else
  356. {
  357. CSize _size = GetSize();
  358. rcReview.right = _size.cx;
  359. rcReview.bottom = _size.cy;
  360. }
  361. for( nY = rcReview.top; nY < rcReview.bottom; nY++ )
  362. {
  363. for( nX = rcReview.left; nX < rcReview.right; nX++ )
  364. {
  365. if( ! rcReview.PtInRect( CPoint( nX, nY ) ) )
  366. continue;
  367. nRed = nBlue = nGreen = 0L;
  368. for( nMatrixX = -nHalfMatrixSize; nMatrixX < nMaxMatrixReview; nMatrixX++ )
  369. {
  370. for( nMatrixY = -nHalfMatrixSize; nMatrixY < nMaxMatrixReview; nMatrixY++ )
  371. {
  372. if( ! GetPixel(
  373. nX + nMatrixX,
  374. nY + nMatrixY,
  375. _pixel
  376. )
  377. )
  378. continue;
  379. nMatrixValue =
  380. pMatrix[
  381. ( nMatrixX + nHalfMatrixSize )
  382. + nMatrixSize * ( nMatrixY + nHalfMatrixSize )
  383. ];
  384. nRed   += _pixel.rgbRed   * nMatrixValue;
  385. nGreen += _pixel.rgbGreen * nMatrixValue;
  386. nBlue  += _pixel.rgbBlue  * nMatrixValue;
  387. } // for( nMatrixY = -nHalfMatrixSize; nMatrixY < nMaxMatrixReview; nMatrixY++ )
  388. } // for( nMatrixX = -nHalfMatrixSize; nMatrixX < nMaxMatrixReview; nMatrixX++ )
  389. if( nFactor == 0 )
  390. {
  391. _pixel.rgbRed   = (BYTE) min( 255, max( 0, (LONG)( nRed   + nOffset ) ) );
  392. _pixel.rgbGreen = (BYTE) min( 255, max( 0, (LONG)( nGreen + nOffset ) ) );
  393. _pixel.rgbBlue  = (BYTE) min( 255, max( 0, (LONG)( nBlue  + nOffset ) ) );
  394. }
  395. else
  396. {
  397. _pixel.rgbRed   = (BYTE) min( 255, max( 0, (LONG)( nRed   / nFactor + nOffset ) ) );
  398. _pixel.rgbGreen = (BYTE) min( 255, max( 0, (LONG)( nGreen / nFactor + nOffset ) ) );
  399. _pixel.rgbBlue  = (BYTE) min( 255, max( 0, (LONG)( nBlue  / nFactor + nOffset ) ) );
  400. }
  401. _bmpBuffer.SetPixel( nX, nY, _pixel );
  402. } // for( nX = rcReview.left; nX < rcReview.right; nX++ )
  403. } // for( nY = rcReview.top; nY < rcReview.bottom; nY++ )
  404. (*this) = _bmpBuffer;
  405. OnContentChanged();
  406. if( IsEmpty() )
  407. return false;
  408. return true;
  409. }
  410. CExtBitmap::Filter::Filter(
  411. CExtBitmap::Filter::e_filter_type eFT, // = ft_default
  412. double * pArrParms, // = NULL
  413. INT nParmCount // = 0
  414. )
  415. : m_eFT( eFT )
  416. {
  417. ASSERT( ft_min_number <= m_eFT && m_eFT <= ft_max_number );
  418. FilterWidthSetDefault();
  419. INT nParmIndex;
  420. for( nParmIndex = 0;
  421. nParmIndex < (sizeof(m_arrParmBuffer)/(sizeof(m_arrParmBuffer[0])));
  422. nParmIndex ++
  423. )
  424. m_arrParmBuffer[ nParmIndex ] = 0.0;
  425. if( pArrParms != NULL && nParmCount > 0 )
  426. {
  427. nParmCount = min( nParmCount, (sizeof(m_arrParmBuffer)/(sizeof(m_arrParmBuffer[0]))) );
  428. for( nParmIndex = 0;
  429. nParmIndex < nParmCount;
  430. nParmIndex ++
  431. )
  432. m_arrParmBuffer[ nParmIndex ] = pArrParms[ nParmIndex ];
  433. }
  434. if( m_eFT == bicubic )
  435. {
  436. if( pArrParms == NULL || nParmCount < 2 )
  437. m_arrParmBuffer[0] = m_arrParmBuffer[1] = 1.0 / 3.0;
  438. m_arrParmBuffer[2] = ( 6.0 - 2.0 * m_arrParmBuffer[0] ) / 6.0;
  439. m_arrParmBuffer[3] = ( -18.0 + 12.0 * m_arrParmBuffer[0] + 6.0 * m_arrParmBuffer[1] ) / 6.0;
  440. m_arrParmBuffer[4] = ( 12.0 - 9.0 * m_arrParmBuffer[0] - 6.0 * m_arrParmBuffer[1] ) / 6.0;
  441. m_arrParmBuffer[5] = ( 8.0 * m_arrParmBuffer[0] + 24.0 * m_arrParmBuffer[1] ) / 6.0;
  442. m_arrParmBuffer[6] = ( -12.0 * m_arrParmBuffer[0] - 48.0 * m_arrParmBuffer[1] ) / 6.0;
  443. m_arrParmBuffer[7] = ( 6.0 * m_arrParmBuffer[0] + 30.0 * m_arrParmBuffer[1] ) / 6.0;
  444. m_arrParmBuffer[8] = ( -m_arrParmBuffer[0] - 6.0 * m_arrParmBuffer[1] ) / 6.0;
  445. }
  446. }
  447. CExtBitmap::Filter::~Filter()
  448. {
  449. }
  450. double CExtBitmap::Filter::stat_rCalc( double lfV )
  451. {
  452. if( lfV == 0.0 )
  453. return 1.0;
  454. lfV *= double(3.1415926535897932384626433832795);
  455. lfV = ::sin( lfV ) / lfV;
  456. return lfV;
  457. }
  458. double CExtBitmap::Filter::Process(
  459. double lfV
  460. )
  461. {
  462. ASSERT( ft_min_number <= m_eFT && m_eFT <= ft_max_number );
  463. switch( m_eFT )
  464. {
  465. case box:
  466. return ( ( ::fabs( lfV ) <= m_lfWidth ) ? 1.0 : 0.0 );
  467. case linear:
  468. if( lfV < -1.0 )
  469. return 0.0;
  470. else if( lfV < 0.0 )
  471. return 1.0 + lfV;
  472. else if( lfV < 1.0 )
  473. return 1.0 - lfV;
  474. else
  475. return 0.0;
  476. case bilinear:
  477. lfV = ::fabs( lfV ); 
  478. return ( ( lfV < m_lfWidth ) ? m_lfWidth - lfV : 0.0 );
  479. case hermite:
  480. if( lfV < -1.0 )
  481. return 0.0;
  482. else if( lfV < 0.0 )
  483. return ( -2.0 * lfV - 3.0 ) * lfV * lfV + 1.0;
  484. else if( lfV < 1.0 )
  485. return ( 2.0 * lfV - 3.0 ) * lfV * lfV + 1.0;
  486. else
  487. return 0.0;
  488. case sinc:
  489. if( lfV == 0.0 )
  490. return 1.0;
  491. else
  492. {
  493. double lfTemp = 3.1415926535897932384626433832795 * lfV;
  494. return ::sin( lfTemp ) / ( lfTemp );
  495. }
  496. case catmull_rom:
  497. if( lfV < -2.0 )
  498. return 0.0;
  499. else if( lfV < -1.0 )
  500. return ( 0.5 * ( 4.0 + lfV * ( 8.0 + lfV * ( 5.0 + lfV ) ) ) );
  501. else if( lfV < 0.0 )
  502. return ( 0.5 * ( 2.0 + lfV * lfV * ( -5.0 - 3.0 * lfV ) ) );
  503. else if( lfV < 1.0 )
  504. return ( 0.5 * ( 2.0 + lfV * lfV * ( -5.0 + 3.0 * lfV ) ) );
  505. else if( lfV < 2.0 )
  506. return ( 0.5 * ( 4.0 + lfV * ( -8.0 + lfV * ( 5.0 - lfV ) ) ) );
  507. else
  508. return 0.0;
  509. case b_spline:
  510. lfV = ::fabs( lfV );
  511. if( lfV < 1.0 )
  512. return ( 4.0 + lfV * lfV * ( -6.0 + 3.0 * lfV ) ) / 6.0;
  513. else if( lfV < 2.0 )
  514. {
  515. double lfTemp = 2.0 - lfV;
  516. return ( lfTemp * lfTemp * lfTemp / 6.0 );
  517. }
  518. else
  519. return 0.0;
  520. case blackman:
  521. if( ::fabs( lfV ) > m_lfWidth )
  522. return 0.0; 
  523. else
  524. {
  525. double lfTemp = 2 * m_lfWidth + 1; 
  526. lfV /= ( lfTemp - 1 );
  527. return
  528. 0.42
  529. + 0.5  * ::cos( 2.0 * 3.1415926535897932384626433832795 * lfV )
  530. + 0.08 * ::cos( 4.0 * 3.1415926535897932384626433832795 * lfV )
  531. }
  532. case lanczos:
  533. lfV = ::fabs( lfV ); 
  534. if( lfV >= m_lfWidth )
  535. return 0.0;
  536. lfV = stat_rCalc( lfV ) * stat_rCalc( lfV / m_lfWidth );
  537. return lfV;
  538. case quadratic:
  539. if( lfV < -1.5 )
  540. return 0.0;
  541. else if( lfV < -0.5 )
  542. return ( 0.5 * ( lfV + 1.5 ) * ( lfV + 1.5 ) );
  543. else if (lfV < 0.5 )
  544. return ( 0.75 - lfV * lfV );
  545. else if( lfV < 1.5 )
  546. return ( 0.5 * ( lfV - 1.5 ) * ( lfV - 1.5 ) );
  547. else
  548. return 0.0;
  549. case gaussian:
  550. if( ::fabs( lfV ) > m_lfWidth ) 
  551. return 0.0;
  552. else
  553. {
  554. static const double lfSq2PI = ::sqrt( 2.0 * 3.1415926535897932384626433832795 );
  555. return ( ::exp( -lfV * lfV / 2.0 ) / lfSq2PI ); 
  556. }
  557. case hamming:
  558. if( ::fabs( lfV ) > m_lfWidth ) 
  559. return 0.0;
  560. else
  561. {
  562. double lfWin =
  563. 0.54 +
  564. 0.46 * ::cos( 2.0 * 3.1415926535897932384626433832795 * lfV ); 
  565. double lfS = ( lfV == 0 )
  566. ? 1.0
  567. : ( ::sin(
  568. 3.1415926535897932384626433832795 * lfV)
  569. / ( 3.1415926535897932384626433832795 * lfV
  570. )
  571. )
  572. return lfWin * lfS;
  573. }
  574. case bicubic:
  575. lfV = ::fabs( lfV );
  576. if( lfV < 1.0 )
  577. return ( m_arrParmBuffer[2] + lfV * lfV * ( m_arrParmBuffer[3] + lfV * m_arrParmBuffer[4] ) );
  578. else if( lfV < 2.0 )
  579. return ( m_arrParmBuffer[5] + lfV * ( m_arrParmBuffer[6] + lfV * ( m_arrParmBuffer[7] + lfV * m_arrParmBuffer[8] ) ) );
  580. else
  581. return 0.0;
  582. default:
  583. ASSERT( FALSE );
  584. return 0.0;
  585. } // switch( m_eFT )
  586. }
  587. double CExtBitmap::Filter::static_DefaultWidth(
  588. CExtBitmap::Filter::e_filter_type eFT
  589. )
  590. {
  591. ASSERT( ft_min_number <= eFT && eFT <= ft_max_number );
  592. switch( eFT )
  593. {
  594. case box:
  595. return 0.5;
  596. case linear:
  597. return 1.0;
  598. case bilinear:
  599. return 1.0;
  600. case hermite:
  601. return 1.0;
  602. case sinc:
  603. return 1.0;
  604. case catmull_rom:
  605. return 2.0;
  606. case b_spline:
  607. return 2.0;
  608. case blackman:
  609. return 0.5;
  610. case lanczos:
  611. return 3.0;
  612. case quadratic:
  613. return 1.0;
  614. case gaussian:
  615. return 3.0;
  616. case hamming:
  617. return 0.5;
  618. case bicubic:
  619. return 2.0;
  620. default:
  621. ASSERT( FALSE );
  622. return 1.0;
  623. } // switch( eFT )
  624. }
  625. CExtBitmap::Filter::e_filter_type CExtBitmap::Filter::FilterTypeGet() const
  626. {
  627. ASSERT( ft_min_number <= m_eFT && m_eFT <= ft_max_number );
  628. return m_eFT;
  629. }
  630. void CExtBitmap::Filter::FilterTypeSet(
  631. CExtBitmap::Filter::e_filter_type eFT
  632. )
  633. {
  634. ASSERT( ft_min_number <= eFT && eFT <= ft_max_number );
  635. m_eFT = eFT;
  636. }
  637. double CExtBitmap::Filter::FilterWidthGet() const
  638. {
  639. ASSERT( ft_min_number <= m_eFT && m_eFT <= ft_max_number );
  640. return m_lfWidth;
  641. }
  642. void CExtBitmap::Filter::FilterWidthSet(
  643. double lfWidth
  644. )
  645. {
  646. ASSERT( ft_min_number <= m_eFT && m_eFT <= ft_max_number );
  647. m_lfWidth = lfWidth;
  648. }
  649. void CExtBitmap::Filter::FilterWidthSetDefault()
  650. {
  651. ASSERT( ft_min_number <= m_eFT && m_eFT <= ft_max_number );
  652. double lfWidth = static_DefaultWidth( m_eFT );
  653. FilterWidthSet( lfWidth );
  654. }
  655. bool CExtBitmap::Filter::stat_FilterWidthIsUsed(
  656. CExtBitmap::Filter::e_filter_type eFT
  657. )
  658. {
  659. ASSERT( ft_min_number <= eFT && eFT <= ft_max_number );
  660. switch( eFT )
  661. {
  662. case linear:
  663. case hermite:
  664. case sinc:
  665. case catmull_rom:
  666. case b_spline:
  667. case quadratic:
  668. case bicubic:
  669. return false;
  670. } // switch( eFT )
  671. return true;
  672. }
  673. bool CExtBitmap::Filter::FilterWidthIsUsed() const
  674. {
  675. ASSERT( ft_min_number <= m_eFT && m_eFT <= ft_max_number );
  676. return stat_FilterWidthIsUsed( m_eFT );
  677. }
  678. INT CExtBitmap::Filter::FilterParameterGetCount()
  679. {
  680. return (sizeof(m_arrParmBuffer)/(sizeof(m_arrParmBuffer[0])));
  681. }
  682. double CExtBitmap::Filter::FilterParameterGetAt(
  683. INT nPos
  684. ) const
  685. {
  686. if( ! ( 0 <= nPos && nPos < (sizeof(m_arrParmBuffer)/(sizeof(m_arrParmBuffer[0]))) ) )
  687. {
  688. ASSERT( FALSE );
  689. return 0.0;
  690. }
  691. return m_arrParmBuffer[ nPos ];
  692. }
  693. void CExtBitmap::Filter::FilterParameterSetAt(
  694. INT nPos,
  695. double lfV
  696. )
  697. {
  698. if( ! ( 0 <= nPos && nPos < (sizeof(m_arrParmBuffer)/(sizeof(m_arrParmBuffer[0]))) ) )
  699. {
  700. ASSERT( FALSE );
  701. return;
  702. }
  703. m_arrParmBuffer[ nPos ] = lfV;
  704. }
  705. __EXT_MFC_SAFE_LPCTSTR CExtBitmap::Filter::stat_FilterNameGet(
  706. CExtBitmap::Filter::e_filter_type eFT
  707. )
  708. {
  709. ASSERT( ft_min_number <= eFT && eFT <= ft_max_number );
  710. switch( eFT )
  711. {
  712. case box:
  713. return _T("Box");
  714. case linear:
  715. return _T("Linear");
  716. case bilinear:
  717. return _T("Bilinear");
  718. case hermite:
  719. return _T("Hermite");
  720. case sinc:
  721. return _T("Sinc");
  722. case catmull_rom:
  723. return _T("Catmull-Rom");
  724. case b_spline:
  725. return _T("B-Spline");
  726. case blackman:
  727. return _T("Blackman");
  728. case lanczos:
  729. return _T("Lanczos");
  730. case quadratic:
  731. return _T("Quadratic");
  732. case gaussian:
  733. return _T("Gaussian");
  734. case hamming:
  735. return _T("Hamming");
  736. case bicubic:
  737. return _T("Bicubic");
  738. default:
  739. ASSERT( FALSE );
  740. return _T("");
  741. } // switch( eFT )
  742. }
  743. __EXT_MFC_SAFE_LPCTSTR CExtBitmap::Filter::FilterNameGet() const
  744. {
  745. ASSERT( ft_min_number <= m_eFT && m_eFT <= ft_max_number );
  746. return stat_FilterNameGet( m_eFT );
  747. }
  748. CExtBitmap::WT::WT(
  749. Filter & _f,
  750. UINT nLineSizeDst,
  751. UINT nLineSizeSrc
  752. )
  753. : m_pWT( NULL )
  754. {
  755. try
  756. {
  757. double lfTarget, lfScaleA = 1.0, lfScale = double(nLineSizeDst) / double(nLineSizeSrc);
  758. if( lfScale < 1.0 )
  759. {
  760. lfTarget = _f.FilterWidthGet() / lfScale; 
  761. lfScaleA = lfScale; 
  762. }
  763. else
  764. lfTarget = _f.FilterWidthGet(); 
  765. m_nReviewSize = 2 * (INT)::ceil( lfTarget ) + 1; 
  766. m_nImageLineSize = nLineSizeDst; 
  767. m_pWT = new WE [ m_nImageLineSize ];
  768. UINT nIndex;
  769. for( nIndex = 0; nIndex < m_nImageLineSize; nIndex++ )
  770. m_pWT[nIndex].m_pWV = new double[ m_nReviewSize ];
  771. double dOffset = (0.5 / lfScale) - 0.5;
  772. for( nIndex = 0; nIndex < m_nImageLineSize; nIndex++ )
  773. {
  774. double dCenter = (double)nIndex / lfScale + dOffset;
  775. INT nPosMin = max(0, (INT) ::floor( dCenter - lfTarget ) ); 
  776. INT nPosMax = min( (INT)ceil( dCenter + lfTarget ), int(nLineSizeSrc) - 1 ); 
  777. if( ( nPosMax - nPosMin + 1 ) > INT( m_nReviewSize ) )
  778. {
  779. if( nPosMin < ( INT(nLineSizeSrc) - 1 / 2 ) )
  780. nPosMin ++;
  781. else
  782. nPosMax --;
  783. }
  784. m_pWT[nIndex].m_nMin = nPosMin; 
  785. m_pWT[nIndex].m_nMax = nPosMax;
  786. int iSrc = 0;
  787. double dTotalWeight = 0;
  788. for( iSrc = nPosMin; iSrc <= nPosMax; iSrc++ )
  789. {
  790. double lfW =
  791. lfScaleA *
  792. _f.Process( lfScaleA * (dCenter - (double)iSrc) );
  793. m_pWT[nIndex].m_pWV[ iSrc - nPosMin ] = lfW;
  794. dTotalWeight += lfW;
  795. }
  796. if( (dTotalWeight > 0) && (dTotalWeight != 1) )
  797. {
  798. for( iSrc = nPosMin; iSrc <= nPosMax; iSrc++ )
  799. m_pWT[nIndex].m_pWV[iSrc-nPosMin] /= dTotalWeight; 
  800. iSrc = nPosMax - nPosMin;
  801. while( m_pWT[nIndex].m_pWV[iSrc] == 0 )
  802. {
  803. m_pWT[nIndex].m_nMax--;
  804. iSrc--;
  805. if( m_pWT[nIndex].m_nMax == m_pWT[nIndex].m_nMin )
  806. break;
  807. }
  808. }
  809. return;
  810. }
  811. catch( CException * pException )
  812. {
  813. pException->Delete();
  814. ASSERT( FALSE );
  815. }
  816. catch( ... )
  817. {
  818. }
  819. if( m_pWT != NULL )
  820. {
  821. delete [ ] m_pWT;
  822. m_pWT = NULL;
  823. }
  824. }
  825. CExtBitmap::WT::~WT()
  826. {
  827. if( m_pWT != NULL )
  828. delete [ ] m_pWT;
  829. }
  830. LPBYTE CExtBitmap::stat_rcResize(
  831. LPBYTE pImageBuffer,
  832. ULONG nWidth,
  833. ULONG nHeight,
  834. Filter & _f,
  835. bool bEnableAlphaMarginAdjustment
  836. )
  837. {
  838. LPBITMAPINFOHEADER pBIH = stat_RcInfoHeader( pImageBuffer );
  839. ULONG nMaskRed = stat_MaskRed( pImageBuffer );
  840. ULONG nMaskGreen = stat_MaskGreen( pImageBuffer );
  841. ULONG nMaskBlue = stat_MaskBlue( pImageBuffer );
  842. ULONG nMaskAlpha = stat_MaskAlpha( pImageBuffer );
  843. ULONG nFlags = stat_RunTimeFlagsGet( pImageBuffer );
  844. LPBYTE pImageBufferDst =
  845. stat_AllocHL(
  846. ULONG(nWidth),
  847. ULONG(nHeight),
  848. ULONG(pBIH->biBitCount),
  849. nMaskRed,
  850. nMaskGreen,
  851. nMaskBlue,
  852. nMaskAlpha,
  853. nFlags
  854. );
  855. if( pImageBufferDst == NULL )
  856. return NULL;
  857. bool bHorzFirst = false;
  858. LONG nWeightLeft = LONG(nWidth) * pBIH->biHeight;
  859. LONG nWeightRight = LONG(nHeight) * pBIH->biWidth;
  860. if( nWeightLeft <= nWeightRight )
  861. bHorzFirst = true;
  862. if( bHorzFirst )
  863. {
  864. LPBYTE pImageBufferTmp =
  865. stat_AllocHL(
  866. ULONG(nWidth),
  867. ULONG(pBIH->biHeight),
  868. ULONG(pBIH->biBitCount),
  869. nMaskRed,
  870. nMaskGreen,
  871. nMaskBlue,
  872. nMaskAlpha,
  873. nFlags
  874. );
  875. if( pImageBufferTmp == NULL )
  876. {
  877. stat_FreeHL( pImageBufferDst );
  878. return NULL;
  879. }
  880. stat_rcResizeH(
  881. pImageBuffer,
  882. pBIH->biWidth,
  883. pImageBufferTmp,
  884. nWidth,
  885. pBIH->biHeight,
  886. _f,
  887. bEnableAlphaMarginAdjustment
  888. );
  889. stat_rcResizeV(
  890. pImageBufferTmp,
  891. pBIH->biHeight,
  892. pImageBufferDst,
  893. nWidth,
  894. nHeight,
  895. _f,
  896. bEnableAlphaMarginAdjustment
  897. );
  898. stat_FreeHL( pImageBufferTmp );
  899. } // if( bHorzFirst )
  900. else
  901. {
  902. LPBYTE pImageBufferTmp =
  903. stat_AllocHL(
  904. ULONG(pBIH->biWidth),
  905. ULONG(nHeight),
  906. ULONG(pBIH->biBitCount),
  907. nMaskRed,
  908. nMaskGreen,
  909. nMaskBlue,
  910. nMaskAlpha,
  911. nFlags
  912. );
  913. if( pImageBufferTmp == NULL )
  914. {
  915. stat_FreeHL( pImageBufferDst );
  916. return NULL;
  917. }
  918. stat_rcResizeV(
  919. pImageBuffer,
  920. pBIH->biHeight,
  921. pImageBufferTmp,
  922. pBIH->biWidth,
  923. nHeight,
  924. _f,
  925. bEnableAlphaMarginAdjustment
  926. );
  927. stat_rcResizeH(
  928. pImageBufferTmp,
  929. pBIH->biWidth,
  930. pImageBufferDst,
  931. nWidth,
  932. nHeight,
  933. _f,
  934. bEnableAlphaMarginAdjustment
  935. );
  936. stat_FreeHL( pImageBufferTmp );
  937. } // if( bHorzFirst )
  938. return pImageBufferDst;
  939. }
  940. void CExtBitmap::stat_rcResizeH(
  941. LPBYTE pImageBufferSrc,
  942. ULONG nWidthSrc,
  943. LPBYTE pImageBufferDst,
  944. ULONG nWidthDst,
  945. ULONG nHeightDst,
  946. Filter & _f,
  947. bool bEnableAlphaMarginAdjustment
  948. )
  949. {
  950. LPBITMAPINFOHEADER pSrcBIH = stat_RcInfoHeader( pImageBufferSrc );
  951. LPBITMAPINFOHEADER pDstBIH = stat_RcInfoHeader( pImageBufferDst );
  952. if( nWidthDst == nWidthSrc )
  953. {
  954. LPBYTE pSurfaceSrc = stat_RcSurface( pImageBufferSrc );
  955. LPBYTE pSurfaceDst = stat_RcSurface( pImageBufferDst );
  956. UINT nSizeInBytes = 
  957. nHeightDst *
  958. stat_RcScanLineSize(
  959. pDstBIH->biWidth,
  960. pDstBIH->biBitCount
  961. );
  962. __EXT_MFC_MEMCPY(
  963. pSurfaceDst,
  964. nSizeInBytes,
  965. pSurfaceSrc,
  966. nSizeInBytes
  967. );
  968. }
  969. else
  970. {
  971. UINT nWalkIdx = 0;
  972. WT _wt( _f, nWidthDst, nWidthSrc ); 
  973. switch( pSrcBIH->biBitCount )
  974. {
  975. case 8:
  976. case 24:
  977. case 32:
  978. {
  979. if( bEnableAlphaMarginAdjustment )
  980. {
  981. if( pSrcBIH->biBitCount != 32
  982. || stat_MaskAlpha( pImageBufferSrc ) == 0
  983. )
  984. bEnableAlphaMarginAdjustment = false;
  985. }
  986. UINT nPixelBytes =
  987. stat_RcLine(
  988. pSrcBIH->biWidth,
  989. pSrcBIH->biBitCount
  990. )
  991. / pSrcBIH->biWidth;
  992. ULONG nScanLineSizeSrc =
  993. stat_RcScanLineSize(
  994. pSrcBIH->biWidth,
  995. pSrcBIH->biBitCount
  996. );
  997. ULONG nScanLineSizeDst =
  998. stat_RcScanLineSize(
  999. pDstBIH->biWidth,
  1000. pDstBIH->biBitCount
  1001. );
  1002. for( UINT nY = 0; nY < nHeightDst; nY++ )
  1003. {
  1004. LPBYTE pSurfaceSrc =
  1005. stat_RcScanLine(
  1006. pImageBufferSrc,
  1007. nY,
  1008. nScanLineSizeSrc
  1009. );
  1010. LPBYTE pSurfaceDst =
  1011. stat_RcScanLine(
  1012. pImageBufferDst,
  1013. nY,
  1014. nScanLineSizeDst
  1015. );
  1016. for( UINT nX = 0; nX < nWidthDst; nX++ )
  1017. {
  1018. double arrW [ 4 ] = { 0.0, 0.0, 0.0, 0.0 };
  1019. INT nPosMin = _wt.GetMin( nX );
  1020. INT nPosMax = _wt.GetMax( nX );
  1021. for( INT nPos = nPosMin; nPos <= nPosMax; nPos++ )
  1022. {
  1023. double lfW = _wt.Weight( nX, nPos - nPosMin );
  1024. nWalkIdx = nPos * nPixelBytes;
  1025. if( bEnableAlphaMarginAdjustment
  1026. && nPixelBytes == 4
  1027. //&& pSurfaceSrc[ nWalkIdx + 3 ] != 0
  1028. )
  1029. {
  1030. arrW [ 0 ] +=
  1031. lfW * double( pSurfaceSrc[ nWalkIdx + 0 ] ) * double( pSurfaceSrc[ nWalkIdx + 3 ] ) / 255.0;
  1032. arrW [ 1 ] +=
  1033. lfW * double( pSurfaceSrc[ nWalkIdx + 1 ] ) * double( pSurfaceSrc[ nWalkIdx + 3 ] ) / 255.0;
  1034. arrW [ 2 ] +=
  1035. lfW * double( pSurfaceSrc[ nWalkIdx + 2 ] ) * double( pSurfaceSrc[ nWalkIdx + 3 ] ) / 255.0;
  1036. arrW [ 3 ] +=
  1037. lfW * double( pSurfaceSrc[ nWalkIdx + 3 ] );
  1038. nWalkIdx += 4;
  1039. }
  1040. else
  1041. {
  1042. for( UINT nPart = 0; nPart < nPixelBytes; nPart++ )
  1043. arrW [ nPart ] +=
  1044. lfW * double( pSurfaceSrc[ nWalkIdx ++ ] );
  1045. }
  1046. for( UINT nPart = 0; nPart < nPixelBytes; nPart++ )
  1047. pSurfaceDst [ nPart ] = (BYTE)
  1048. min(
  1049. max(
  1050. (int)0,
  1051. (int)( arrW [ nPart ] + 0.5 )
  1052. ),
  1053. (int)255
  1054. );
  1055. pSurfaceDst += nPixelBytes;
  1056. }
  1057. }
  1058. break;
  1059. case 16:
  1060. {
  1061. UINT nPixelWords =
  1062. ( stat_RcLine(
  1063. pSrcBIH->biWidth,
  1064. pSrcBIH->biBitCount
  1065. )
  1066. / pSrcBIH->biWidth )
  1067. / sizeof(WORD);
  1068. ULONG nScanLineSizeSrc =
  1069. stat_RcScanLineSize(
  1070. pSrcBIH->biWidth,
  1071. pSrcBIH->biBitCount
  1072. );
  1073. ULONG nScanLineSizeDst =
  1074. stat_RcScanLineSize(
  1075. pDstBIH->biWidth,
  1076. pDstBIH->biBitCount
  1077. );
  1078. for( UINT nY = 0; nY < nHeightDst; nY++ )
  1079. {
  1080. LPWORD pSurfaceSrc = (LPWORD)
  1081. stat_RcScanLine(
  1082. pImageBufferSrc,
  1083. nY,
  1084. nScanLineSizeSrc
  1085. );
  1086. LPWORD pSurfaceDst = (LPWORD)
  1087. stat_RcScanLine(
  1088. pImageBufferDst,
  1089. nY,
  1090. nScanLineSizeDst
  1091. );
  1092. for( UINT nX = 0; nX < nWidthDst; nX++ )
  1093. {
  1094. double arrW [ 4 ] = { 0.0, 0.0, 0.0, 0.0 };
  1095. INT nPosMin = _wt.GetMin( nX );
  1096. INT nPosMax = _wt.GetMax( nX );
  1097. for( int nPos = nPosMin; nPos <= nPosMax; nPos++ )
  1098. {
  1099. double lfW = _wt.Weight( nX, nPos - nPosMin );
  1100. nWalkIdx = nPos * nPixelWords;
  1101. for( UINT nPart = 0; nPart < nPixelWords; nPart++ )
  1102. arrW[ nPart ] +=
  1103. lfW * double( pSurfaceSrc[ nWalkIdx ++ ] ); 
  1104. for( UINT nPart = 0; nPart < nPixelWords; nPart++ )
  1105. pSurfaceDst [ nPart ] = (WORD)
  1106. min(
  1107. max(
  1108. (int)0,
  1109. (int)( arrW [ nPart ] + 0.5 )
  1110. ),
  1111. (int)0xFFFF
  1112. );
  1113. pSurfaceDst += nPixelWords;
  1114. }
  1115. }
  1116. break;
  1117. } // switch( pSrcBIH->biBitCount )
  1118. }
  1119. }
  1120. void CExtBitmap::stat_rcResizeV(
  1121. LPBYTE pImageBufferSrc,
  1122. ULONG nHeightSrc,
  1123. LPBYTE pImageBufferDst,
  1124. ULONG nWidthDst,
  1125. ULONG nHeightDst,
  1126. Filter & _f,
  1127. bool bEnableAlphaMarginAdjustment
  1128. )
  1129. {
  1130. LPBITMAPINFOHEADER pSrcBIH = stat_RcInfoHeader( pImageBufferSrc );
  1131. LPBITMAPINFOHEADER pDstBIH = stat_RcInfoHeader( pImageBufferDst );
  1132. if( nHeightSrc == nHeightDst )
  1133. {
  1134. LPBYTE pSurfaceSrc = stat_RcSurface( pImageBufferSrc );
  1135. LPBYTE pSurfaceDst = stat_RcSurface( pImageBufferDst );
  1136. UINT nSizeInBytes = 
  1137. nHeightDst *
  1138. stat_RcScanLineSize(
  1139. pDstBIH->biWidth,
  1140. pDstBIH->biBitCount
  1141. );
  1142. __EXT_MFC_MEMCPY(
  1143. pSurfaceDst,
  1144. nSizeInBytes,
  1145. pSurfaceSrc,
  1146. nSizeInBytes
  1147. );
  1148. }
  1149. else
  1150. {
  1151. UINT nWalkIdx = 0;
  1152. WT _wt( _f, nHeightDst, nHeightSrc ); 
  1153. switch( pSrcBIH->biBitCount )
  1154. {
  1155. case 8:
  1156. case 24:
  1157. case 32:
  1158. {
  1159. if( bEnableAlphaMarginAdjustment )
  1160. {
  1161. if( pSrcBIH->biBitCount != 32
  1162. || stat_MaskAlpha( pImageBufferSrc ) == 0
  1163. )
  1164. bEnableAlphaMarginAdjustment = false;
  1165. }
  1166. UINT nPixelBytes =
  1167. stat_RcLine(
  1168. pSrcBIH->biWidth,
  1169. pSrcBIH->biBitCount
  1170. )
  1171. / pSrcBIH->biWidth;
  1172. UINT nScanLineSizeSrc =
  1173. stat_RcScanLineSize(
  1174. pSrcBIH->biWidth,
  1175. pSrcBIH->biBitCount
  1176. );
  1177. UINT nScanLineSizeDst =
  1178. stat_RcScanLineSize(
  1179. pDstBIH->biWidth,
  1180. pDstBIH->biBitCount
  1181. );
  1182. for( UINT nX = 0; nX < nWidthDst; nX++ )
  1183. {
  1184. nWalkIdx = nX * nPixelBytes;
  1185. LPBYTE pSurfaceDst =
  1186. stat_RcSurface( pImageBufferDst )
  1187. + nWalkIdx;
  1188. for( UINT nY = 0; nY < nHeightDst; nY++ )
  1189. {
  1190. double arrW [ 4 ] = { 0.0, 0.0, 0.0, 0.0 };
  1191. INT nPosMin = _wt.GetMin( nY );
  1192. INT nPosMax = _wt.GetMax( nY );
  1193. LPBYTE pSurfaceSrc =
  1194. stat_RcScanLine(
  1195. pImageBufferSrc,
  1196. nPosMin,
  1197. nScanLineSizeSrc
  1198. )
  1199. + nWalkIdx;
  1200. for( INT nPos = nPosMin; nPos <= nPosMax; nPos++ )
  1201. {
  1202. double lfW = _wt.Weight( nY, nPos - nPosMin );
  1203. if( bEnableAlphaMarginAdjustment
  1204. && nPixelBytes == 4
  1205. //&& pSurfaceSrc[ 3 ] != 0
  1206. )
  1207. {
  1208. arrW [ 0 ] +=
  1209. lfW * double( pSurfaceSrc[ 0 ] ) * double( pSurfaceSrc[ 3 ] ) / 255.0;
  1210. arrW [ 1 ] +=
  1211. lfW * double( pSurfaceSrc[ 1 ] ) * double( pSurfaceSrc[ 3 ] ) / 255.0;
  1212. arrW [ 2 ] +=
  1213. lfW * double( pSurfaceSrc[ 2 ] ) * double( pSurfaceSrc[ 3 ] ) / 255.0;
  1214. arrW [ 3 ] +=
  1215. lfW * double( pSurfaceSrc[ 3 ] );
  1216. }
  1217. else
  1218. {
  1219. for( UINT nPart = 0; nPart < nPixelBytes; nPart++ )
  1220. arrW [ nPart ] +=
  1221. lfW * double( pSurfaceSrc [ nPart ] );
  1222. }
  1223. pSurfaceSrc += nScanLineSizeSrc;
  1224. }
  1225. for( UINT nPart = 0; nPart < nPixelBytes; nPart++ )
  1226. {
  1227. pSurfaceDst [ nPart ] =
  1228. (BYTE)min(
  1229. max(
  1230. (int)0,
  1231. (int)( arrW [ nPart ] + 0.5 )
  1232. ),
  1233. (int)255
  1234. );
  1235. }
  1236. pSurfaceDst += nScanLineSizeDst;
  1237. }
  1238. }
  1239. }
  1240. break;
  1241. case 16:
  1242. {
  1243. UINT nPixelWords =
  1244. ( stat_RcLine(
  1245. pSrcBIH->biWidth,
  1246. pSrcBIH->biBitCount
  1247. )
  1248. / pSrcBIH->biWidth )
  1249. / sizeof(WORD);
  1250. UINT nScanLineSizeSrc =
  1251. stat_RcScanLineSize(
  1252. pSrcBIH->biWidth,
  1253. pSrcBIH->biBitCount
  1254. ) / sizeof(WORD);
  1255. UINT nScanLineSizeDst =
  1256. stat_RcScanLineSize(
  1257. pDstBIH->biWidth,
  1258. pDstBIH->biBitCount
  1259. ) / sizeof(WORD);
  1260. for( UINT nX = 0; nX < nWidthDst; nX++ )
  1261. {
  1262. nWalkIdx = nX * nPixelWords;
  1263. LPWORD pSurfaceDst = (LPWORD)
  1264. stat_RcSurface( pImageBufferDst ) + nWalkIdx;
  1265. for( UINT nY = 0; nY < nHeightDst; nY++ )
  1266. {
  1267. double arrW [ 4 ] = { 0.0, 0.0, 0.0, 0.0 };
  1268. INT nPosMin = _wt.GetMin( nY );
  1269. INT nPosMax = _wt.GetMax( nY );
  1270. LPWORD pSurfaceSrc = (LPWORD)
  1271. stat_RcScanLine(
  1272. pImageBufferSrc,
  1273. nPosMin,
  1274. nScanLineSizeSrc
  1275. )
  1276. + nWalkIdx;
  1277. for( INT nPos = nPosMin; nPos <= nPosMax; nPos++ )
  1278. {
  1279. double lfW = _wt.Weight( nY, nPos - nPosMin );
  1280. for( UINT nPart = 0; nPart < nPixelWords; nPart++ )
  1281. arrW [ nPart ] +=
  1282. lfW * double( pSurfaceSrc [ nPart ] );
  1283. pSurfaceSrc += nScanLineSizeSrc;
  1284. }
  1285. for( UINT nPart = 0; nPart < nPixelWords; nPart++ )
  1286. pSurfaceDst [ nPart ] = (WORD)
  1287. min(
  1288. max(
  1289. (int)0,
  1290. (int)( arrW [ nPart ] + 0.5 )
  1291. ),
  1292. (int)0xFFFF
  1293. );
  1294. pSurfaceDst += nScanLineSizeDst;
  1295. }
  1296. }
  1297. }
  1298. break;
  1299. } // switch( pSrcBIH->biBitCount )
  1300. }
  1301. }
  1302. bool CExtBitmap::Flip(
  1303. bool bHorizontal,
  1304. bool bVertVertical,
  1305. LPCRECT pRectFlip // = NULL
  1306. )
  1307. {
  1308. if( IsEmpty()
  1309. || ( (!bHorizontal) && (!bVertVertical) )
  1310. )
  1311. return false;
  1312. CSize _size = GetSize();
  1313. CRect rcFlip( 0, 0, _size.cx, _size.cy );
  1314. if( pRectFlip != NULL )
  1315. {
  1316. rcFlip.left = max( rcFlip.left, pRectFlip->left );
  1317. rcFlip.top = max( rcFlip.top, pRectFlip->top );
  1318. rcFlip.right = min( rcFlip.right, pRectFlip->right );
  1319. rcFlip.bottom = min( rcFlip.bottom, pRectFlip->bottom );
  1320. }
  1321. if( rcFlip.left >= rcFlip.right
  1322. || rcFlip.top >= rcFlip.bottom
  1323. )
  1324. return false;
  1325. CSize _sizeFlip = rcFlip.Size();
  1326. INT nX, nY, nSizeWalk;
  1327. RGBQUAD _pixel1, _pixel2;
  1328. if( bHorizontal )
  1329. {
  1330. nSizeWalk = _sizeFlip.cx / 2;
  1331. ASSERT( nSizeWalk >= 1 );
  1332. for( nX = 0; nX < nSizeWalk; nX ++ )
  1333. {
  1334. for( nY = 0; nY < _sizeFlip.cy; nY ++ )
  1335. {
  1336. VERIFY(
  1337. GetPixel(
  1338. nX + rcFlip.left,
  1339. nY + rcFlip.top,
  1340. _pixel1
  1341. )
  1342. );
  1343. VERIFY(
  1344. GetPixel(
  1345. rcFlip.right - nX - 1,
  1346. nY + rcFlip.top,
  1347. _pixel2
  1348. )
  1349. );
  1350. VERIFY(
  1351. SetPixel(
  1352. nX + rcFlip.left,
  1353. nY + rcFlip.top,
  1354. _pixel2
  1355. )
  1356. );
  1357. VERIFY(
  1358. SetPixel(
  1359. rcFlip.right - nX - 1,
  1360. nY + rcFlip.top,
  1361. _pixel1
  1362. )
  1363. );
  1364. } // for( nY = 0; nY < _sizeFlip.cy; nY ++ )
  1365. } // for( nX = 0; nX < nSizeWalk; nX ++ )
  1366. } // if( bHorizontal )
  1367. if( bVertVertical )
  1368. {
  1369. nSizeWalk = _sizeFlip.cy / 2;
  1370. ASSERT( nSizeWalk >= 1 );
  1371. for( nY = 0; nY < nSizeWalk; nY ++ )
  1372. {
  1373. for( nX = 0; nX < _sizeFlip.cx; nX ++ )
  1374. {
  1375. VERIFY(
  1376. GetPixel(
  1377. nX + rcFlip.left,
  1378. nY + rcFlip.top,
  1379. _pixel1
  1380. )
  1381. );
  1382. VERIFY(
  1383. GetPixel(
  1384. nX + rcFlip.left,
  1385. rcFlip.bottom - nY - 1,
  1386. _pixel2
  1387. )
  1388. );
  1389. VERIFY(
  1390. SetPixel(
  1391. nX + rcFlip.left,
  1392. nY + rcFlip.top,
  1393. _pixel2
  1394. )
  1395. );
  1396. VERIFY(
  1397. SetPixel(
  1398. nX + rcFlip.left,
  1399. rcFlip.bottom - nY - 1,
  1400. _pixel1
  1401. )
  1402. );
  1403. } // for( nX = 0; nX < _sizeFlip.cx; nX ++ )
  1404. } // for( nY = 0; nY < nSizeWalk; nY ++ )
  1405. } // if( bVertVertical )
  1406. OnContentChanged();
  1407. return true;
  1408. }
  1409. bool CExtBitmap::FlipHorizontal(
  1410. LPCRECT pRectFlip // = NULL
  1411. )
  1412. {
  1413. return Flip( true, false, pRectFlip );
  1414. }
  1415. bool CExtBitmap::FlipVertical(
  1416. LPCRECT pRectFlip // = NULL
  1417. )
  1418. {
  1419. return Flip( false, true, pRectFlip );
  1420. }
  1421. bool CExtBitmap::Scale(
  1422. INT nWidth,
  1423. INT nHeight,
  1424. CExtBitmap::Filter & _f
  1425. )
  1426. {
  1427. if( IsEmpty()
  1428. || nWidth <= 0
  1429. || nHeight <= 0
  1430. || GetBPP() < 16
  1431. )
  1432. return false;
  1433. CSize _size = GetSize();
  1434. if( INT(_size.cx) == nWidth
  1435. && INT(_size.cy) == nHeight
  1436. )
  1437. return true;
  1438. if( PreMultipliedRGBChannelsGet() )
  1439. {
  1440. PreMultiplyRGBChannels( false );
  1441. PreMultipliedRGBChannelsSet( false );
  1442. }
  1443. LPBYTE pImageBuffer =
  1444. stat_rcResize(
  1445. m_pImageBuffer,
  1446. ULONG(nWidth),
  1447. ULONG(nHeight),
  1448. _f,
  1449. true
  1450. );
  1451. if( pImageBuffer == NULL )
  1452. return false;
  1453. Empty();
  1454. m_pImageBuffer = pImageBuffer;
  1455. OnContentChanged();
  1456. return true;
  1457. }
  1458. bool CExtBitmap::Scale(
  1459. INT nWidth,
  1460. INT nHeight
  1461. )
  1462. {
  1463. CExtBitmap::Filter _f; //( CExtBitmap::Filter::bilinear );
  1464. return Scale( nWidth, nHeight, _f );
  1465. }
  1466. bool CExtBitmap::LoadBMP_Resource(
  1467. __EXT_MFC_SAFE_LPCTSTR sResourceID,
  1468. __EXT_MFC_SAFE_LPCTSTR sResourceType, // = RT_BITMAP // default bitmap section
  1469. HINSTANCE hInst, // = NULL // find it automatically
  1470. bool bMake32, //= false
  1471. bool bEnableThrowException // = false
  1472. )
  1473. {
  1474. if( hInst == NULL )
  1475. {
  1476. hInst =
  1477. g_ResourceManager->FindResourceHandle(
  1478. sResourceType,
  1479. (UINT)(__EXT_MFC_UINT_PTR)(LPCTSTR)sResourceID
  1480. );
  1481. if( hInst == NULL )
  1482. {
  1483. if( bEnableThrowException )
  1484. ::AfxThrowUserException();
  1485. return false;
  1486. } // if( hInst == NULL )
  1487. } // if( hInst == NULL )
  1488. HRSRC hRsrc =
  1489. ::FindResource(
  1490. hInst,
  1491. sResourceID,
  1492. sResourceType
  1493. );
  1494. if( hRsrc == NULL )
  1495. {
  1496. if( bEnableThrowException )
  1497. ::AfxThrowUserException();
  1498. return NULL;
  1499. } // if( hRsrc == NULL )
  1500. return
  1501. LoadBMP_Resource(
  1502. hInst,
  1503. hRsrc,
  1504. bMake32,
  1505. bEnableThrowException
  1506. );
  1507. }
  1508. bool CExtBitmap::LoadBMP_Resource(
  1509. HINSTANCE hInst,
  1510. HRSRC hRsrc,
  1511. bool bMake32, //= false
  1512. bool bEnableThrowException // = false
  1513. )
  1514. {
  1515. HGLOBAL hGlobal = ::LoadResource( hInst, hRsrc );
  1516. if( hGlobal == NULL )
  1517. {
  1518. if( bEnableThrowException )
  1519. ::AfxThrowUserException();
  1520. return false;
  1521. } // if( hGlobal == NULL )
  1522. LPBYTE pData = (LPBYTE)::LockResource( hGlobal );
  1523. DWORD dwResourceSize = ::SizeofResource( hInst, hRsrc );
  1524. ASSERT( dwResourceSize > 0 );
  1525. if( pData == NULL )
  1526. {
  1527. ::FreeResource( hGlobal );
  1528. if( bEnableThrowException )
  1529. ::AfxThrowUserException();
  1530. return false;
  1531. } // if( pData == NULL )
  1532. try
  1533. {
  1534. CMemFile _file;
  1535. _file.Attach( pData, dwResourceSize );
  1536. _file.Seek( 0, CFile::begin );
  1537. CArchive ar( &_file, CArchive::load );
  1538. bool bRetVal =
  1539. LoadBMP(
  1540. ar,
  1541. bMake32,
  1542. bEnableThrowException,
  1543. true
  1544. );
  1545. ::UnlockResource( hGlobal );
  1546. ::FreeResource( hGlobal );
  1547. return bRetVal;
  1548. } // try
  1549. catch( CException * pException )
  1550. {
  1551. ::UnlockResource( hGlobal );
  1552. ::FreeResource( hGlobal );
  1553. if( bEnableThrowException )
  1554. throw;
  1555. pException->Delete();
  1556. } // catch( CException * pException )
  1557. catch( ... )
  1558. {
  1559. ::UnlockResource( hGlobal );
  1560. ::FreeResource( hGlobal );
  1561. if( bEnableThrowException )
  1562. throw;
  1563. } // catch( ... )
  1564. return false;
  1565. }
  1566. bool CExtBitmap::LoadBMP_Buffer(
  1567. LPCVOID pBuffer,
  1568. UINT nByteCount,
  1569. bool bMake32, //= false
  1570. bool bEnableThrowException, // = false
  1571. bool bResourceFormat // = false
  1572. )
  1573. {
  1574. ASSERT( pBuffer != NULL );
  1575. try
  1576. {
  1577. Empty();
  1578. CMemFile _file(
  1579. (LPBYTE)pBuffer,
  1580. nByteCount
  1581. );
  1582. if( ! LoadBMP_File(
  1583. _file,
  1584. bMake32,
  1585. bEnableThrowException,
  1586. bResourceFormat
  1587. )
  1588. )
  1589. return false;
  1590. return true;
  1591. } // try
  1592. catch( CException * pException )
  1593. {
  1594. if( bEnableThrowException )
  1595. throw;
  1596. pException->Delete();
  1597. } // catch( CException * pException )
  1598. catch( ... )
  1599. {
  1600. if( bEnableThrowException )
  1601. throw;
  1602. } // catch( ... )
  1603. return false;
  1604. }
  1605. bool CExtBitmap::LoadBMP_File(
  1606. __EXT_MFC_SAFE_LPCTSTR strFilePath,
  1607. bool bMake32, //= false
  1608. bool bEnableThrowException, // = false
  1609. bool bResourceFormat // = false
  1610. )
  1611. {
  1612. try
  1613. {
  1614. CFile _file(
  1615. strFilePath,
  1616. CFile::modeRead
  1617. | CFile::typeBinary
  1618. );
  1619. return
  1620. LoadBMP_File(
  1621. _file,
  1622. bMake32,
  1623. bEnableThrowException,
  1624. bResourceFormat
  1625. );
  1626. } // try
  1627. catch( CException * pException )
  1628. {
  1629. if( bEnableThrowException )
  1630. throw;
  1631. pException->Delete();
  1632. } // catch( CException * pException )
  1633. catch( ... )
  1634. {
  1635. if( bEnableThrowException )
  1636. throw;
  1637. } // catch( ... )
  1638. return false;
  1639. }
  1640. bool CExtBitmap::LoadBMP_File(
  1641. CFile & _file,
  1642. bool bMake32, //= false
  1643. bool bEnableThrowException, // = false
  1644. bool bResourceFormat // = false
  1645. )
  1646. {
  1647. CArchive ar(
  1648. &_file,
  1649. CArchive::load
  1650. );
  1651. return
  1652. LoadBMP(
  1653. ar,
  1654. bMake32,
  1655. bEnableThrowException,
  1656. bResourceFormat
  1657. );
  1658. }
  1659. bool CExtBitmap::LoadBMP(
  1660. CArchive & ar,
  1661. bool bMake32, //= false
  1662. bool bEnableThrowException, // = false
  1663. bool bResourceFormat // = false
  1664. )
  1665. {
  1666. ASSERT( ar.IsLoading() );
  1667. Empty();
  1668. m_pImageBuffer =
  1669. stat_BmpLoad(
  1670. ar,
  1671. bEnableThrowException,
  1672. bResourceFormat
  1673. );
  1674. if( m_pImageBuffer == NULL )
  1675. return false;
  1676. OnLoad();
  1677. if( bMake32 )
  1678. return Make32( bEnableThrowException );
  1679. return true;
  1680. }
  1681. #ifndef _AFX_NO_OLE_SUPPORT
  1682. bool CExtBitmap::stat_OlePictureLoad(
  1683. IStream * pStream, DWORD dwImageSize, IPicture ** ppPicture,
  1684. CSize * pSizeImage, OLE_XSIZE_HIMETRIC * p_nWidthHM, OLE_YSIZE_HIMETRIC * p_nHeightHM,
  1685. bool bShowMsgBoxes // = false
  1686. )
  1687. {
  1688. ASSERT( ppPicture != NULL && pStream != NULL );
  1689. if( (*ppPicture) != NULL )
  1690. {
  1691. (*ppPicture)->Release();
  1692. (*ppPicture) = NULL;
  1693. }
  1694. if( pSizeImage != NULL )
  1695. pSizeImage->cx = pSizeImage->cy = 0;
  1696. if( p_nWidthHM != NULL )
  1697. (*p_nWidthHM) = 0L;
  1698. if( p_nHeightHM != NULL )
  1699. (*p_nHeightHM) = 0L;
  1700. HRESULT hr = ::OleLoadPicture( pStream, dwImageSize, FALSE, IID_IPicture, (LPVOID*)ppPicture );
  1701. if( ( !( SUCCEEDED(hr) ) ) || (*ppPicture) == NULL )
  1702. {
  1703. if( bShowMsgBoxes )
  1704. ::AfxMessageBox( _T("Image format error(s) detected while reading picture file."), MB_OK|MB_ICONERROR );
  1705. return false;
  1706. }
  1707. if( pSizeImage != NULL || p_nWidthHM != NULL || p_nHeightHM != NULL )
  1708. {
  1709. OLE_XSIZE_HIMETRIC nWidthHM = 0L;
  1710. OLE_YSIZE_HIMETRIC nHeightHM = 0L;
  1711. (*ppPicture)->get_Width ( &nWidthHM );
  1712. (*ppPicture)->get_Height( &nHeightHM );
  1713. if( pSizeImage != NULL )
  1714. {
  1715. pSizeImage->cx = ::MulDiv( nWidthHM,  g_PaintManager.m_nLPX, 2540 );
  1716. pSizeImage->cy = ::MulDiv( nHeightHM, g_PaintManager.m_nLPY, 2540 );
  1717. }
  1718. if( p_nWidthHM != NULL )
  1719. (*p_nWidthHM) = nWidthHM;
  1720. if( p_nHeightHM != NULL )
  1721. (*p_nHeightHM) = nHeightHM;
  1722. }
  1723. return true;
  1724. }
  1725. bool CExtBitmap::stat_OlePictureLoad(
  1726. LPCTSTR strPictureFilePath, IPicture ** ppPicture,
  1727. CSize * pSizeImage, OLE_XSIZE_HIMETRIC * p_nWidthHM, OLE_YSIZE_HIMETRIC * p_nHeightHM,
  1728. bool bShowMsgBoxes // = false
  1729. )
  1730. {
  1731. ASSERT( ppPicture != NULL && strPictureFilePath != NULL && _tcslen(strPictureFilePath) > 0 );
  1732. if( (*ppPicture) != NULL )
  1733. {
  1734. (*ppPicture)->Release();
  1735. (*ppPicture) = NULL;
  1736. }
  1737. if( pSizeImage != NULL )
  1738. pSizeImage->cx = pSizeImage->cy = 0;
  1739. if( p_nWidthHM != NULL )
  1740. (*p_nWidthHM) = 0L;
  1741. if( p_nHeightHM != NULL )
  1742. (*p_nHeightHM) = 0L;
  1743. HANDLE hFile = ::CreateFile( strPictureFilePath, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL );
  1744. if( hFile == INVALID_HANDLE_VALUE )
  1745. {
  1746. if( bShowMsgBoxes )
  1747. {
  1748. CExtSafeString strMsgBox;
  1749. strMsgBox.Format( _T("Failed not read the "%s" picture file."), strPictureFilePath );
  1750. ::AfxMessageBox( LPCTSTR(strMsgBox), MB_OK|MB_ICONERROR );
  1751. }
  1752. return false;
  1753. }
  1754. DWORD dwFileSize = ::GetFileSize( hFile, NULL );
  1755. if( dwFileSize == (DWORD)-1 )
  1756. {
  1757. ::CloseHandle( hFile );
  1758. if( bShowMsgBoxes )
  1759. {
  1760. CExtSafeString strMsgBox;
  1761. strMsgBox.Format( _T("The "%s" picture file is invalid."), strPictureFilePath );
  1762. ::AfxMessageBox( LPCTSTR(strMsgBox), MB_OK|MB_ICONERROR );
  1763. }
  1764. return false;
  1765. }
  1766. LPVOID pvData = NULL;
  1767. HGLOBAL hGlobal = ::GlobalAlloc( GMEM_MOVEABLE, dwFileSize );
  1768. if( hGlobal == NULL)
  1769. {
  1770. ::CloseHandle( hFile );
  1771. if( bShowMsgBoxes )
  1772. {
  1773. CExtSafeString strMsgBox;
  1774. strMsgBox.Format( _T("Not enough memory for reading the "%s" picture file."), strPictureFilePath );
  1775. ::AfxMessageBox( LPCTSTR(strMsgBox), MB_OK|MB_ICONERROR );
  1776. }
  1777. return false;
  1778. }
  1779. pvData = GlobalLock(hGlobal);
  1780. if( pvData == NULL )
  1781. {
  1782. ::GlobalUnlock( hGlobal );
  1783. ::CloseHandle( hFile );
  1784. if( bShowMsgBoxes )
  1785. {
  1786. CExtSafeString strMsgBox;
  1787. strMsgBox.Format( _T("Memory locking error occured while reading the "%s" picture file."), strPictureFilePath );
  1788. ::AfxMessageBox( LPCTSTR(strMsgBox), MB_OK|MB_ICONERROR );
  1789. }
  1790. return false;
  1791. }
  1792. DWORD dwBytesRead = 0;
  1793. BOOL bRead = ::ReadFile( hFile, pvData, dwFileSize, &dwBytesRead, NULL );
  1794. ::GlobalUnlock( hGlobal );
  1795. ::CloseHandle( hFile );
  1796. if( ! bRead )
  1797. {
  1798. if( bShowMsgBoxes )
  1799. {
  1800. CExtSafeString strMsgBox;
  1801. strMsgBox.Format( _T("File reading error occured while accessing the "%s" picture file."), strPictureFilePath );
  1802. ::AfxMessageBox( LPCTSTR(strMsgBox), MB_OK|MB_ICONERROR );
  1803. }
  1804. return false;
  1805. }
  1806. LPSTREAM pStream = NULL;
  1807. HRESULT hr = ::CreateStreamOnHGlobal( hGlobal, TRUE, &pStream );
  1808. if( ( ! ( SUCCEEDED(hr) ) ) || pStream == NULL )
  1809. {
  1810. if( bShowMsgBoxes )
  1811. {
  1812. CExtSafeString strMsgBox;
  1813. strMsgBox.Format( _T("Not enough memory for reading the "%s" picture file."), strPictureFilePath );
  1814. ::AfxMessageBox( LPCTSTR(strMsgBox), MB_OK|MB_ICONERROR );
  1815. }
  1816. if( pStream != NULL )
  1817. pStream->Release();
  1818. return false;
  1819. }
  1820. bool bRetVal = stat_OlePictureLoad( pStream, dwFileSize, ppPicture, pSizeImage, p_nWidthHM, p_nHeightHM, false );
  1821. pStream->Release();
  1822. if( (!bRetVal) && bShowMsgBoxes )
  1823. {
  1824. CExtSafeString strMsgBox;
  1825. strMsgBox.Format( _T("Image format error(s) detected while reading the "%s" picture file."), strPictureFilePath );
  1826. ::AfxMessageBox( LPCTSTR(strMsgBox), MB_OK|MB_ICONERROR );
  1827. }
  1828. return bRetVal;
  1829. }
  1830. bool CExtBitmap::OlePictureLoad(
  1831. __EXT_MFC_SAFE_LPCTSTR sResourceID,
  1832. __EXT_MFC_SAFE_LPCTSTR sResourceType, // = RT_BITMAP // default bitmap section
  1833. HINSTANCE hInst, // = NULL // find it automatically
  1834. bool bMake32, // = false
  1835. bool bEnableThrowException, // = false
  1836. bool bShowMsgBoxes // = false
  1837. )
  1838. {
  1839. if( hInst == NULL )
  1840. {
  1841. hInst =
  1842. g_ResourceManager->FindResourceHandle(
  1843. sResourceType,
  1844. (UINT)(__EXT_MFC_UINT_PTR)(LPCTSTR)sResourceID
  1845. );
  1846. if( hInst == NULL )
  1847. {
  1848. if( bEnableThrowException )
  1849. ::AfxThrowUserException();
  1850. return false;
  1851. } // if( hInst == NULL )
  1852. } // if( hInst == NULL )
  1853. HRSRC hRsrc =
  1854. ::FindResource(
  1855. hInst,
  1856. sResourceID,
  1857. sResourceType
  1858. );
  1859. if( hRsrc == NULL )
  1860. {
  1861. if( bEnableThrowException )
  1862. ::AfxThrowUserException();
  1863. return NULL;
  1864. } // if( hRsrc == NULL )
  1865. return
  1866. OlePictureLoad(
  1867. hInst,
  1868. hRsrc,
  1869. bMake32,
  1870. bEnableThrowException,
  1871. bShowMsgBoxes
  1872. );
  1873. }
  1874. bool CExtBitmap::OlePictureLoad(
  1875. HINSTANCE hInst,
  1876. HRSRC hRsrc,
  1877. bool bMake32, // = false
  1878. bool bEnableThrowException, // = false
  1879. bool bShowMsgBoxes // = false
  1880. )
  1881. {
  1882. HGLOBAL hGlobal = ::LoadResource( hInst, hRsrc );
  1883. if( hGlobal == NULL )
  1884. {
  1885. if( bEnableThrowException )
  1886. ::AfxThrowUserException();
  1887. return false;
  1888. } // if( hGlobal == NULL )
  1889. LPBYTE pData = (LPBYTE)::LockResource( hGlobal );
  1890. DWORD dwResourceSize = ::SizeofResource( hInst, hRsrc );
  1891. ASSERT( dwResourceSize > 0 );
  1892. if( pData == NULL )
  1893. {
  1894. ::FreeResource( hGlobal );
  1895. if( bEnableThrowException )
  1896. ::AfxThrowUserException();
  1897. return false;
  1898. } // if( pData == NULL )
  1899. try
  1900. {
  1901. CMemFile _file;
  1902. _file.Attach( pData, dwResourceSize );
  1903. _file.Seek( 0, CFile::begin );
  1904. CArchive ar( &_file, CArchive::load );
  1905. bool bRetVal =
  1906. OlePictureLoad(
  1907. ar,
  1908. bMake32,
  1909. bEnableThrowException,
  1910. bShowMsgBoxes
  1911. );
  1912. ::UnlockResource( hGlobal );
  1913. ::FreeResource( hGlobal );
  1914. return bRetVal;
  1915. } // try
  1916. catch( CException * pException )
  1917. {
  1918. ::UnlockResource( hGlobal );
  1919. ::FreeResource( hGlobal );
  1920. if( bEnableThrowException )
  1921. throw;
  1922. pException->Delete();
  1923. } // catch( CException * pException )
  1924. catch( ... )
  1925. {
  1926. ::UnlockResource( hGlobal );
  1927. ::FreeResource( hGlobal );
  1928. if( bEnableThrowException )
  1929. throw;
  1930. } // catch( ... )
  1931. return false;
  1932. }
  1933. bool CExtBitmap::OlePictureLoad(
  1934. CFile & _file,
  1935. bool bMake32, // = false,
  1936. bool bEnableThrowException, // = false
  1937. bool bShowMsgBoxes // = false
  1938. )
  1939. {
  1940. CArchive ar( &_file, CArchive::load );
  1941. return OlePictureLoad( ar, bMake32, bEnableThrowException, bShowMsgBoxes );
  1942. }
  1943. bool CExtBitmap::OlePictureLoad(
  1944. CArchive & ar,
  1945. bool bMake32, // = false,
  1946. bool bEnableThrowException, // = false
  1947. bool bShowMsgBoxes // = false
  1948. )
  1949. {
  1950. CArchiveStream _stream( &ar );
  1951. return OlePictureLoad( &_stream, bMake32, bEnableThrowException, bShowMsgBoxes );
  1952. }
  1953. bool CExtBitmap::OlePictureLoad(
  1954. IStream * pStream,
  1955. bool bMake32, // = false
  1956. bool bEnableThrowException, // = false
  1957. bool bShowMsgBoxes // = false
  1958. )
  1959. {
  1960. return OlePictureLoad( pStream, 0, bMake32, bEnableThrowException, bShowMsgBoxes );
  1961. }
  1962. bool CExtBitmap::OlePictureLoad(
  1963. IStream * pStream,
  1964. DWORD dwImageSize,
  1965. bool bMake32, // = false
  1966. bool bEnableThrowException, // = false
  1967. bool bShowMsgBoxes // = false
  1968. )
  1969. {
  1970. if( pStream == NULL )
  1971. {
  1972. if( bEnableThrowException )
  1973. ::AfxThrowUserException();
  1974. return false;
  1975. }
  1976. Empty();
  1977. LPPICTURE pPicture = NULL;
  1978. CSize sizeBmp( 0, 0 );
  1979. OLE_XSIZE_HIMETRIC nWidthHM = 0L;
  1980. OLE_YSIZE_HIMETRIC nHeightHM = 0L;
  1981. if( ! stat_OlePictureLoad( pStream, dwImageSize, &pPicture, &sizeBmp, &nWidthHM, &nHeightHM, bShowMsgBoxes ) )
  1982. {
  1983. if( bEnableThrowException )
  1984. ::AfxThrowUserException();
  1985. return false;
  1986. }
  1987. CWindowDC dcDesktop(NULL);
  1988. CDC dcBuffer;
  1989. if( dcBuffer.CreateCompatibleDC( &dcDesktop ) )
  1990. {
  1991. BITMAPINFOHEADER bih; bih.biSize = sizeof(BITMAPINFOHEADER);
  1992. bih.biWidth = sizeBmp.cx; bih.biHeight = sizeBmp.cy; bih.biPlanes = 1; bih.biBitCount = 32; bih.biCompression = BI_RGB;
  1993. bih.biSizeImage = bih.biWidth*bih.biHeight; bih.biXPelsPerMeter = 0; bih.biYPelsPerMeter = 0; bih.biClrUsed = 0; bih.biClrImportant = 0;
  1994. COLORREF * pClrSurface = NULL;
  1995. HBITMAP hDIB = ::CreateDIBSection( dcDesktop.GetSafeHdc(), (LPBITMAPINFO)&bih, DIB_RGB_COLORS, (void **)&pClrSurface, NULL, NULL );
  1996. if( hDIB != NULL )
  1997. {
  1998. ASSERT( pClrSurface != NULL );
  1999. CBitmap bmpBuffer; // works as destructor for hDIB
  2000. bmpBuffer.Attach( hDIB );
  2001. CBitmap * pOldBmp = dcBuffer.SelectObject( &bmpBuffer );
  2002. HRESULT hr = pPicture->Render( dcBuffer.m_hDC, 0, 0, sizeBmp.cx, sizeBmp.cy, 0, nHeightHM, nWidthHM, -nHeightHM, NULL );
  2003. if( SUCCEEDED( hr ) )
  2004. {
  2005. CRect rcBuffer( 0, 0, sizeBmp.cx, sizeBmp.cy );
  2006. FromSurface( dcBuffer.m_hDC, rcBuffer );
  2007. }
  2008. dcBuffer.SelectObject( pOldBmp );
  2009. }
  2010. }
  2011. pPicture->Release();
  2012. bool bRetVal = IsEmpty() ? false : true;
  2013. if( bRetVal )
  2014. {
  2015. if( bMake32 )
  2016. bRetVal = Make32( bEnableThrowException );
  2017. if( bRetVal )
  2018. OnLoad();
  2019. }
  2020. else if( bEnableThrowException )
  2021. ::AfxThrowUserException();
  2022. return bRetVal;
  2023. }
  2024. bool CExtBitmap::OlePictureLoad(
  2025. LPCTSTR strPictureFilePath,
  2026. bool bMake32,
  2027. bool bEnableThrowException, // = false
  2028. bool bShowMsgBoxes // = false
  2029. )
  2030. {
  2031. if( strPictureFilePath == NULL )
  2032. {
  2033. if( bEnableThrowException )
  2034. ::AfxThrowUserException();
  2035. return false;
  2036. }
  2037. Empty();
  2038. LPPICTURE pPicture = NULL;
  2039. CSize sizeBmp( 0, 0 );
  2040. OLE_XSIZE_HIMETRIC nWidthHM = 0L;
  2041. OLE_YSIZE_HIMETRIC nHeightHM = 0L;
  2042. if( ! stat_OlePictureLoad( strPictureFilePath, &pPicture, &sizeBmp, &nWidthHM, &nHeightHM, bShowMsgBoxes ) )
  2043. {
  2044. if( bEnableThrowException )
  2045. ::AfxThrowUserException();
  2046. return false;
  2047. }
  2048. CWindowDC dcDesktop(NULL);
  2049. CDC dcBuffer;
  2050. if( dcBuffer.CreateCompatibleDC( &dcDesktop ) )
  2051. {
  2052. BITMAPINFOHEADER bih; bih.biSize = sizeof(BITMAPINFOHEADER);
  2053. bih.biWidth = sizeBmp.cx; bih.biHeight = sizeBmp.cy; bih.biPlanes = 1; bih.biBitCount = 32; bih.biCompression = BI_RGB;
  2054. bih.biSizeImage = bih.biWidth*bih.biHeight; bih.biXPelsPerMeter = 0; bih.biYPelsPerMeter = 0; bih.biClrUsed = 0; bih.biClrImportant = 0;
  2055. COLORREF * pClrSurface = NULL;
  2056. HBITMAP hDIB = ::CreateDIBSection( dcDesktop.GetSafeHdc(), (LPBITMAPINFO)&bih, DIB_RGB_COLORS, (void **)&pClrSurface, NULL, NULL );
  2057. if( hDIB != NULL )
  2058. {
  2059. ASSERT( pClrSurface != NULL );
  2060. CBitmap bmpBuffer; // works as destructor for hDIB
  2061. bmpBuffer.Attach( hDIB );
  2062. CBitmap * pOldBmp = dcBuffer.SelectObject( &bmpBuffer );
  2063. HRESULT hr = pPicture->Render( dcBuffer.m_hDC, 0, 0, sizeBmp.cx, sizeBmp.cy, 0, nHeightHM, nWidthHM, -nHeightHM, NULL );
  2064. if( SUCCEEDED( hr ) )
  2065. {
  2066. CRect rcBuffer( 0, 0, sizeBmp.cx, sizeBmp.cy );
  2067. FromSurface( dcBuffer.m_hDC, rcBuffer );
  2068. }
  2069. dcBuffer.SelectObject( pOldBmp );
  2070. }
  2071. }
  2072. pPicture->Release();
  2073. bool bRetVal = IsEmpty() ? false : true;
  2074. if( bRetVal )
  2075. {
  2076. if( bMake32 )
  2077. bRetVal = Make32( bEnableThrowException );
  2078. if( bRetVal )
  2079. OnLoad();
  2080. }
  2081. else if( bEnableThrowException )
  2082. ::AfxThrowUserException();
  2083. return bRetVal;
  2084. }
  2085. #endif // _AFX_NO_OLE_SUPPORT
  2086. bool CExtBitmap::Make32(
  2087. bool bEnableThrowException // = false
  2088. )
  2089. {
  2090. if( IsEmpty() )
  2091. return false;
  2092. LPBITMAPINFOHEADER pBIH = stat_RcInfoHeader( m_pImageBuffer );
  2093. if( pBIH->biBitCount == 32 )
  2094. {
  2095. LPBYTE pImageBuffer = m_pImageBuffer;
  2096. ULONG nMaskBufferSize = max( sizeof(ULONG) * 5, 32 );
  2097. pImageBuffer -= nMaskBufferSize;
  2098. ULONG * pMaskBuffer = (ULONG *)pImageBuffer;
  2099. if( pMaskBuffer[0] == 0x00FF0000
  2100. && pMaskBuffer[1] == 0x0000FF00
  2101. && pMaskBuffer[2] == 0x000000FF
  2102. && pMaskBuffer[3] != 0xFF000000
  2103. )
  2104. {
  2105. pMaskBuffer[3] = 0xFF000000;
  2106. OnContentChanged();
  2107. }
  2108. return true;
  2109. }
  2110. LPBYTE pImageBuffer32 = stat_RcTo32( m_pImageBuffer, bEnableThrowException );
  2111. if( pImageBuffer32 == NULL )
  2112. return false;
  2113. stat_FreeHL( m_pImageBuffer );
  2114. m_pImageBuffer = pImageBuffer32;
  2115. OnContentChanged();
  2116. return true;
  2117. }
  2118. bool CExtBitmap::SaveBMP_File(
  2119. __EXT_MFC_SAFE_LPCTSTR strFilePath,
  2120. bool bMake32, //= false
  2121. bool bEnableThrowException, // = false
  2122. bool bUseIndexedRLE // = true
  2123. )
  2124. {
  2125. try
  2126. {
  2127. CFile _file(
  2128. strFilePath,
  2129. CFile::modeCreate
  2130. | CFile::modeWrite
  2131. | CFile::typeBinary
  2132. );
  2133. return
  2134. SaveBMP_File(
  2135. _file,
  2136. bMake32,
  2137. bEnableThrowException,
  2138. bUseIndexedRLE
  2139. );
  2140. } // try
  2141. catch( CException * pException )
  2142. {
  2143. if( bEnableThrowException )
  2144. throw;
  2145. pException->Delete();
  2146. } // catch( CException * pException )
  2147. catch( ... )
  2148. {
  2149. if( bEnableThrowException )
  2150. throw;
  2151. } // catch( ... )
  2152. return false;
  2153. }
  2154. bool CExtBitmap::SaveBMP_File(
  2155. CFile & _file,
  2156. bool bMake32, //= false
  2157. bool bEnableThrowException, // = false
  2158. bool bUseIndexedRLE // = true
  2159. )
  2160. {
  2161. CArchive ar(
  2162. &_file,
  2163. CArchive::store
  2164. );
  2165. return
  2166. SaveBMP(
  2167. ar,
  2168. bMake32,
  2169. bEnableThrowException,
  2170. bUseIndexedRLE
  2171. );
  2172. }
  2173. bool CExtBitmap::SaveBMP(
  2174. CArchive & ar,
  2175. bool bMake32, //= false
  2176. bool bEnableThrowException, // = false
  2177. bool bUseIndexedRLE // = true
  2178. )
  2179. {
  2180. ASSERT( ar.IsStoring() );
  2181. if( m_pImageBuffer == NULL )
  2182. {
  2183. ASSERT( FALSE );
  2184. if( bEnableThrowException )
  2185. ::AfxThrowUserException();
  2186. return false;
  2187. } // if( m_pImageBuffer == NULL )
  2188. if( bMake32 )
  2189. {
  2190. if( ! Make32( bEnableThrowException ) )
  2191. return false;
  2192. } // if( bMake32 )
  2193. if( PreMultipliedRGBChannelsGet() )
  2194. {
  2195. PreMultiplyRGBChannels( false );
  2196. PreMultipliedRGBChannelsSet( false );
  2197. }
  2198. return
  2199. stat_BmpSave(
  2200. m_pImageBuffer,
  2201. ar,
  2202. bEnableThrowException,
  2203. bUseIndexedRLE
  2204. );
  2205. }
  2206. bool CExtBitmap::FromColor(
  2207. COLORREF clr,
  2208. const SIZE & _dimension,
  2209. BYTE nAlpha, // = BYTE(255)
  2210. bool bEnableThrowException // = false
  2211. )
  2212. {
  2213. if( _dimension.cx <= 0 || _dimension.cy <= 0 )
  2214. return false;
  2215. Empty();
  2216. m_pImageBuffer =
  2217. stat_AllocHL(
  2218. _dimension.cx,
  2219. _dimension.cy,
  2220. 32,
  2221. 0x00FF0000,
  2222. 0x0000FF00,
  2223. 0x000000FF,
  2224. 0xFF000000,
  2225. 0 // run-time flags
  2226. );
  2227. if( m_pImageBuffer == NULL )
  2228. {
  2229. if( bEnableThrowException )
  2230. ::AfxThrowUserException();
  2231. return false;
  2232. } // if( m_pImageBuffer == NULL )
  2233. LONG nX, nY;
  2234. for( nY = 0; nY < _dimension.cy; nY ++ )
  2235. {
  2236. for( nX = 0; nX < _dimension.cx; nX ++ )
  2237. {
  2238. RGBQUAD _pixel;
  2239. VERIFY( GetPixel( nX, nY, _pixel ) );
  2240. _pixel.rgbRed   = GetRValue(clr);
  2241. _pixel.rgbGreen = GetGValue(clr);
  2242. _pixel.rgbBlue  = GetBValue(clr);
  2243. _pixel.rgbReserved = nAlpha;
  2244. VERIFY( SetPixel( nX, nY, _pixel ) );
  2245. }
  2246. }
  2247. OnLoad();
  2248. return true;
  2249. }
  2250. bool CExtBitmap::FromSurface(
  2251. HDC hDC,
  2252. const RECT & rcSrc,
  2253. bool bEnableThrowException // = false
  2254. )
  2255. {
  2256. Empty();
  2257. if( hDC == NULL
  2258. || rcSrc.left >= rcSrc.right
  2259. || rcSrc.top >= rcSrc.bottom
  2260. )
  2261. {
  2262. if( bEnableThrowException )
  2263. ::AfxThrowUserException();
  2264. return false;
  2265. }
  2266. HDC hDCSrc = ::CreateCompatibleDC( NULL );
  2267. if( hDCSrc == NULL )
  2268. {
  2269. if( bEnableThrowException )
  2270. ::AfxThrowUserException();
  2271. return false;
  2272. }
  2273. CDC dc;
  2274. dc.Attach( hDCSrc );
  2275. DWORD biWidth = rcSrc.right - rcSrc.left;
  2276. DWORD biHeight = rcSrc.bottom - rcSrc.top;
  2277. BITMAPINFOHEADER bih;
  2278. ::memset( &bih, 0, sizeof( BITMAPINFOHEADER ) );
  2279. bih.biSize = sizeof( BITMAPINFOHEADER );
  2280. bih.biWidth = biWidth;
  2281. bih.biHeight = biHeight;
  2282. bih.biPlanes = 1;
  2283. bih.biBitCount = 32;
  2284. bih.biCompression = BI_RGB;
  2285. bih.biSizeImage = biWidth * biHeight;
  2286. COLORREF * pClrSurface = NULL;
  2287. HBITMAP hBitmap =
  2288. ::CreateDIBSection(
  2289. hDC,
  2290. (LPBITMAPINFO)&bih,
  2291. DIB_RGB_COLORS,
  2292. (void **)&pClrSurface,
  2293. NULL,
  2294. NULL
  2295. );
  2296. if( hBitmap == NULL 
  2297. || pClrSurface == NULL 
  2298. )
  2299. {
  2300. if( bEnableThrowException )
  2301. ::AfxThrowUserException();
  2302. return false;
  2303. }
  2304. CBitmap bmp;
  2305. bmp.Attach( hBitmap );
  2306. HGDIOBJ hBitmapOld = ::SelectObject( hDCSrc, (HGDIOBJ)hBitmap );
  2307. VERIFY(
  2308. ::BitBlt(
  2309. hDCSrc,
  2310. 0, 0, biWidth, biHeight,
  2311. hDC,
  2312. rcSrc.left, rcSrc.top,
  2313. SRCCOPY
  2314. )
  2315. );
  2316. ::SelectObject( hDCSrc, (HGDIOBJ)hBitmapOld );
  2317. if( ! FromBitmap( hBitmap, bEnableThrowException ) )
  2318. return false;
  2319. bmp.DeleteObject();
  2320. dc.DeleteDC();
  2321. OnLoad();
  2322. return true;
  2323. }
  2324. bool CExtBitmap::FromBitmap(
  2325. HBITMAP hBitmap,
  2326. bool bEnableThrowException, // = false
  2327. bool bNoAdjustAlpha // = false
  2328. )
  2329. {
  2330. return
  2331. FromBitmap(
  2332. hBitmap,
  2333. NULL,
  2334. bEnableThrowException,
  2335. bNoAdjustAlpha
  2336. );
  2337. }
  2338. bool CExtBitmap::FromBitmap(
  2339. HBITMAP hBitmap,
  2340. LPCRECT pRectBitmapSrc, // NULL - entire bitmap
  2341. bool bEnableThrowException,
  2342. bool bNoAdjustAlpha
  2343. )
  2344. {
  2345. Empty();
  2346. if( hBitmap == NULL )
  2347. {
  2348. ASSERT( FALSE );
  2349. if( bEnableThrowException )
  2350. ::AfxThrowUserException();
  2351. return false;
  2352. } // if( hBitmap == NULL )
  2353. BITMAP _bmpInfo;
  2354. ::GetObject( hBitmap, sizeof(BITMAP), &_bmpInfo );
  2355. bool bCustomRect = false;
  2356. CRect rcSrc( 0, 0, _bmpInfo.bmWidth, _bmpInfo.bmHeight );
  2357. if( pRectBitmapSrc != NULL )
  2358. {
  2359. if( pRectBitmapSrc->left < rcSrc.left
  2360. || pRectBitmapSrc->top < rcSrc.top
  2361. || pRectBitmapSrc->right > rcSrc.right
  2362. || pRectBitmapSrc->bottom > rcSrc.bottom
  2363. )
  2364. {
  2365. ASSERT( FALSE );
  2366. if( bEnableThrowException )
  2367. ::AfxThrowUserException();
  2368. return false;
  2369. }
  2370. if( pRectBitmapSrc->left != rcSrc.left
  2371. || pRectBitmapSrc->top != rcSrc.top
  2372. || pRectBitmapSrc->right != rcSrc.right
  2373. || pRectBitmapSrc->bottom != rcSrc.bottom
  2374. )
  2375. {
  2376. rcSrc = (*pRectBitmapSrc);
  2377. bCustomRect = true;
  2378. }
  2379. } // if( pRectBitmapSrc != NULL )
  2380. if( bCustomRect )
  2381. {
  2382. CExtBitmap other;
  2383. if( ! other.FromBitmap( hBitmap, bEnableThrowException, bNoAdjustAlpha ) )
  2384. return false;
  2385. other.Make32();
  2386. m_pImageBuffer =
  2387. stat_AllocHL(
  2388. rcSrc.Width(),
  2389. rcSrc.Height(),
  2390. 32, //_bmpInfo.bmBitsPixel,
  2391. //  0,
  2392. //  0,
  2393. //  0,
  2394. //  0
  2395. 0x00FF0000,
  2396. 0x0000FF00,
  2397. 0x000000FF,
  2398. 0xFF000000,
  2399. 0 // run-time flags
  2400. );
  2401. if( m_pImageBuffer == NULL )
  2402. {
  2403. if( bEnableThrowException )
  2404. ::AfxThrowUserException();
  2405. return false;
  2406. } // if( m_pImageBuffer == NULL )
  2407. INT xDst, yDst, xSrc, ySrc = rcSrc.top, dx = rcSrc.Width(), dy = rcSrc.Height();
  2408. for( yDst = 0; yDst < dy; yDst ++, ySrc ++ )
  2409. {
  2410. xSrc = rcSrc.left;
  2411. for( xDst = 0; xDst < dx; xDst ++, xSrc ++ )
  2412. {
  2413. RGBQUAD _pixel;
  2414. VERIFY( other.GetPixel( xSrc, ySrc, _pixel ) );
  2415. //_pixel.rgbReserved = 0x80;
  2416. VERIFY( SetPixel( xDst, yDst, _pixel ) );
  2417. } // for( xDst = 0; xDst < dx; xDst ++, xSrc ++ )
  2418. } // for( yDst = 0; yDst < dy; yDst ++, ySrc ++ )
  2419. OnLoad();
  2420. return true;
  2421. } // if( bCustomRect )
  2422. else
  2423. {
  2424. if( _bmpInfo.bmBitsPixel == 32 )
  2425. m_pImageBuffer =
  2426. stat_AllocHL(
  2427. _bmpInfo.bmWidth,
  2428. _bmpInfo.bmHeight,
  2429. 32,
  2430. 0x00FF0000,
  2431. 0x0000FF00,
  2432. 0x000000FF,
  2433. 0xFF000000,
  2434. 0 // run-time flags
  2435. );
  2436. else
  2437. m_pImageBuffer =
  2438. stat_AllocHL(
  2439. _bmpInfo.bmWidth,
  2440. _bmpInfo.bmHeight,
  2441. _bmpInfo.bmBitsPixel,
  2442. 0,
  2443. 0,
  2444. 0,
  2445. 0,
  2446. 0 // run-time flags
  2447. );
  2448. if( m_pImageBuffer == NULL )
  2449. {
  2450. if( bEnableThrowException )
  2451. ::AfxThrowUserException();
  2452. return false;
  2453. } // if( m_pImageBuffer == NULL )
  2454. LPBITMAPINFOHEADER pBIH = stat_RcInfoHeader( m_pImageBuffer );
  2455. HDC hDC = ::GetDC( NULL );
  2456. int nGetDIBitsResult =
  2457. ::GetDIBits(
  2458. hDC,
  2459. hBitmap,
  2460. 0,
  2461. pBIH->biHeight, 
  2462. stat_RcSurface( m_pImageBuffer ),
  2463. stat_RcInfo( m_pImageBuffer ),
  2464. DIB_RGB_COLORS
  2465. );
  2466. ::ReleaseDC( NULL, hDC );
  2467. if( nGetDIBitsResult == 0 )
  2468. {
  2469. Empty();
  2470. if( bEnableThrowException )
  2471. ::AfxThrowUserException();
  2472. return false;
  2473. } // if( nGetDIBitsResult == 0 )
  2474. if( _bmpInfo.bmBitsPixel == 32 )
  2475. {
  2476. CSize _sizeBitmap = GetSize();
  2477. ULONG nScanLineSize = stat_RcScanLineSize( _sizeBitmap.cx, 32 );
  2478. LPBYTE p32bitColorSurface = stat_RcSurface( m_pImageBuffer ); 
  2479. for( INT nY = 0; nY < _sizeBitmap.cy; nY++ )
  2480. {
  2481. for( INT nX = 0; nX < _sizeBitmap.cx; nX++ )
  2482. {
  2483. LPLONG ptrLinePart = (LPLONG)p32bitColorSurface + nX;
  2484. if( ! bNoAdjustAlpha )
  2485. (*ptrLinePart) |= 0xFF000000;
  2486. } // for( INT nX = 0; nX < _sizeBitmap.cx; nX++ )
  2487. p32bitColorSurface += nScanLineSize;
  2488. } // for( INT nY = 0; nY < _sizeBitmap.cy; nY++ )
  2489. } // if( _bmpInfo.bmBitsPixel == 32 )
  2490. OnLoad();
  2491. return true;
  2492. } // else from if( bCustomRect )
  2493. }
  2494. bool CExtBitmap::FromBitmap(
  2495. const CExtBitmap & _other,
  2496. LPCRECT pRectBitmapSrc, // = NULL - entire bitmap
  2497. bool bEnableThrowException // = false
  2498. )
  2499. {
  2500. Empty();
  2501. if( _other.IsEmpty() )
  2502. {
  2503. ASSERT( FALSE );
  2504. if( bEnableThrowException )
  2505. ::AfxThrowUserException();
  2506. return false;
  2507. }
  2508. CSize _sizeOther = _other.GetSize();
  2509. bool bCustomRect = false;
  2510. CRect rcSrc( 0, 0, _sizeOther.cx, _sizeOther.cy );
  2511. if( pRectBitmapSrc != NULL )
  2512. {
  2513. if( pRectBitmapSrc->left < rcSrc.left
  2514. || pRectBitmapSrc->top < rcSrc.top
  2515. || pRectBitmapSrc->right > rcSrc.right
  2516. || pRectBitmapSrc->bottom > rcSrc.bottom
  2517. )
  2518. {
  2519. ASSERT( FALSE );
  2520. if( bEnableThrowException )
  2521. ::AfxThrowUserException();
  2522. return false;
  2523. }
  2524. if( pRectBitmapSrc->left != rcSrc.left
  2525. || pRectBitmapSrc->top != rcSrc.top
  2526. || pRectBitmapSrc->right != rcSrc.right
  2527. || pRectBitmapSrc->bottom != rcSrc.bottom
  2528. )
  2529. {
  2530. rcSrc = (*pRectBitmapSrc);
  2531. bCustomRect = true;
  2532. }
  2533. } // if( pRectBitmapSrc != NULL )
  2534. if( bCustomRect )
  2535. {
  2536. CExtBitmap other;
  2537. if( ! other.AssignFromOther( _other, bEnableThrowException ) )
  2538. return false;
  2539. other.Make32();
  2540. m_pImageBuffer =
  2541. stat_AllocHL(
  2542. rcSrc.Width(),
  2543. rcSrc.Height(),
  2544. 32, //_bmpInfo.bmBitsPixel,
  2545. //  0,
  2546. //  0,
  2547. //  0,
  2548. //  0
  2549. 0x00FF0000,
  2550. 0x0000FF00,
  2551. 0x000000FF,
  2552. 0xFF000000,
  2553. 0 // run-time flags
  2554. );
  2555. if( m_pImageBuffer == NULL )
  2556. {
  2557. if( bEnableThrowException )
  2558. ::AfxThrowUserException();
  2559. return false;
  2560. } // if( m_pImageBuffer == NULL )
  2561. INT xDst, yDst, xSrc, ySrc = rcSrc.top, dx = rcSrc.Width(), dy = rcSrc.Height();
  2562. for( yDst = 0; yDst < dy; yDst ++, ySrc ++ )
  2563. {
  2564. xSrc = rcSrc.left;
  2565. for( xDst = 0; xDst < dx; xDst ++, xSrc ++ )
  2566. {
  2567. RGBQUAD _pixel;
  2568. VERIFY( other.GetPixel( xSrc, ySrc, _pixel ) );
  2569. //_pixel.rgbReserved = 0x80;
  2570. VERIFY( SetPixel( xDst, yDst, _pixel ) );
  2571. } // for( xDst = 0; xDst < dx; xDst ++, xSrc ++ )
  2572. } // for( yDst = 0; yDst < dy; yDst ++, ySrc ++ )
  2573. OnLoad();
  2574. return true;
  2575. } // if( bCustomRect )
  2576. else
  2577. {
  2578. if( ! AssignFromOther( _other, bEnableThrowException ) )
  2579. return false;
  2580. return true;
  2581. } // else from if( bCustomRect )
  2582. }
  2583. bool CExtBitmap::ExtractEditableBitmap(
  2584. HBITMAP & hBitmap,
  2585. COLORREF & clrTransparent,
  2586. CArray <COLORREF,COLORREF> * pArr, // = NULL // recommended palette, item 0 is clrTransparent
  2587. COLORREF ** ppClrSurface // = NULL // if not NULL - force 32 bit
  2588. ) const
  2589. {
  2590. if( IsEmpty() )
  2591. return false;
  2592. static COLORREF arrTransparentColors[] =
  2593. { RGB(255,0,255), RGB(0,255,0), RGB(192,192,192), };
  2594. CArray <COLORREF,COLORREF> _arr;
  2595. GetBitmapColorArray( _arr );
  2596. ASSERT( _arr.GetSize() >= 1 );
  2597. COLORREF clrFoundTransparent = ((COLORREF)(-1L));
  2598. for( INT i = 0; i < sizeof(arrTransparentColors)/(sizeof(arrTransparentColors[0])); i++ )
  2599. {
  2600. COLORREF clrAnalyze = arrTransparentColors[i];
  2601. bool bAbandone = false;
  2602. for( int j = 0; j < _arr.GetSize(); j++ )
  2603. {
  2604. COLORREF clrPal = _arr[j];
  2605. if( clrAnalyze == clrPal )
  2606. {
  2607. bAbandone = true;
  2608. break;
  2609. } // if( clrAnalyze == clrPal )
  2610. } // for( int j = 0; j < _arr.GetSize(); j++ )
  2611. if( bAbandone )
  2612. continue;
  2613. clrFoundTransparent = clrAnalyze;
  2614. break;
  2615. } // for( int i = 0; i < sizeof(arrTransparentColors)/(sizeof(arrTransparentColors[0])); i++ )
  2616. if( clrFoundTransparent == ((COLORREF)(-1L)) )
  2617. {
  2618. // do not use black/white colors as transparent
  2619. for( DWORD k = 0x00000001; k < 0x00FFFFFE; k++ )
  2620. {
  2621. COLORREF clrAnalyze = ((COLORREF)(k));
  2622. bool bAbandone = false;
  2623. for( int j = 0; j < _arr.GetSize(); j++ )
  2624. {
  2625. COLORREF clrPal = _arr[j];
  2626. if( clrAnalyze == clrPal )
  2627. {
  2628. bAbandone = true;
  2629. break;
  2630. } // if( clrAnalyze == clrPal )
  2631. } // for( int j = 0; j < _arr.GetSize(); j++ )
  2632. if( bAbandone )
  2633. continue;
  2634. clrFoundTransparent = clrAnalyze;
  2635. break;
  2636. } // for( DWORD k = 0x00000001; k < 0x00FFFFFE; k++ )
  2637. } // if( clrFoundTransparent == ((COLORREF)(-1L)) )
  2638. if( clrFoundTransparent == ((COLORREF)(-1L)) )
  2639. {
  2640. ASSERT( false );
  2641. return false;
  2642. }
  2643. hBitmap = CreateBitmap( ppClrSurface, clrFoundTransparent );
  2644. if( hBitmap == NULL )
  2645. {
  2646. ASSERT( FALSE );
  2647. return false;
  2648. }
  2649. /* if( ppClrSurface != NULL )
  2650. {
  2651. COLORREF * pSurf = (*ppClrSurface);
  2652. ASSERT( pSurf != NULL );
  2653. COLORREF clrActualTransparent = m_BitmapCache.GetTransparentColor();
  2654. if( clrActualTransparent != clrFoundTransparent )
  2655. {
  2656. CSize _sizeIcon = GetSize();
  2657. ASSERT( _sizeIcon.cx > 0 && _sizeIcon.cy > 0 );
  2658. LONG nIconPixelCount = _sizeIcon.cx * _sizeIcon.cy;
  2659. COLORREF clrQuadSearch =
  2660. RGB(
  2661. GetBValue( clrActualTransparent ),
  2662. GetGValue( clrActualTransparent ),
  2663. GetRValue( clrActualTransparent )
  2664. );
  2665. COLORREF clrQuadReplace =
  2666. RGB(
  2667. GetBValue( clrFoundTransparent ),
  2668. GetGValue( clrFoundTransparent ),
  2669. GetRValue( clrFoundTransparent )
  2670. );
  2671. for( LONG nPixel = 0; nPixel < nIconPixelCount ; nPixel++, pSurf++ )
  2672. {
  2673. if( (*pSurf) == clrQuadSearch )
  2674. (*pSurf) = clrQuadReplace;
  2675. } // for( LONG nPixel = 0; nPixel < nIconPixelCount ; nPixel++, pSurf++ )
  2676. } // if( clrActualTransparent != clrFoundTransparent )
  2677. } // if( ppClrSurface != NULL )
  2678. */
  2679. clrTransparent = clrFoundTransparent;
  2680. if( pArr != NULL )
  2681. {
  2682. pArr->RemoveAll();
  2683. pArr->Append( _arr );
  2684. if( pArr->GetAt(0) != clrTransparent )
  2685. {
  2686. pArr->InsertAt( 0, clrTransparent, 1 );
  2687. for( INT i = 1; i < pArr->GetSize(); i++ )
  2688. {
  2689. if( pArr->GetAt( i ) == clrTransparent )
  2690. {
  2691. pArr->RemoveAt( i, 1 );
  2692. break;
  2693. } // if( pArr->GetAt(i) == clrTransparent )
  2694. } // for( int i = 1; i < pArr->GetSize(); i++ )
  2695. } // if( pArr->GetAt(0) != clrTransparent )
  2696. } // if( pArr != NULL )
  2697. return true;
  2698. }
  2699. bool CExtBitmap::CreateRotated9xStack(
  2700. const CExtBitmap & bmpSrcStack,
  2701. int nAngleCw90, // 0, 90, 180, 270, 360 clockwise
  2702. int nStackItemCount, // >= 1
  2703. int nSrcItemWidth,
  2704. int nSrcItemHeight,
  2705. bool bSrcStackIsHorizontal,
  2706. bool bDstStackIsHorizontal
  2707. )
  2708. {
  2709. if( bmpSrcStack.IsEmpty()
  2710. || bmpSrcStack.GetBPP() < 15
  2711. || nStackItemCount < 1
  2712. || nSrcItemWidth < 1
  2713. || nSrcItemHeight < 1
  2714. || (! (
  2715. nAngleCw90 ==   0
  2716. || nAngleCw90 ==  90
  2717. || nAngleCw90 == 180
  2718. || nAngleCw90 == 270
  2719. || nAngleCw90 == 360
  2720. ) )
  2721. )
  2722. return false;
  2723. Empty();
  2724. int nDstItemWidth  = ( nAngleCw90 == 90 || nAngleCw90 == 270 ) ? nSrcItemHeight : nSrcItemWidth;
  2725. int nDstItemHeight = ( nAngleCw90 == 90 || nAngleCw90 == 270 ) ? nSrcItemWidth : nSrcItemHeight;
  2726. ULONG nBPP = bmpSrcStack.GetBPP();
  2727. m_pImageBuffer =
  2728. stat_AllocHL(
  2729. nDstItemWidth * ( bDstStackIsHorizontal ? nStackItemCount : 1 ),
  2730. nDstItemHeight * ( bDstStackIsHorizontal ? 1 : nStackItemCount ),
  2731. nBPP,
  2732. stat_MaskRed( LPBYTE( bmpSrcStack.m_pImageBuffer ) ),
  2733. stat_MaskGreen( LPBYTE( bmpSrcStack.m_pImageBuffer ) ),
  2734. stat_MaskBlue( LPBYTE( bmpSrcStack.m_pImageBuffer ) ),
  2735. stat_MaskAlpha( LPBYTE( bmpSrcStack.m_pImageBuffer ) ),
  2736. stat_RunTimeFlagsGet( LPBYTE( bmpSrcStack.m_pImageBuffer ) )
  2737. );
  2738. if( m_pImageBuffer == NULL )
  2739. return false;
  2740. CRect rcSrc( 0, 0, nSrcItemWidth, nSrcItemHeight ), rcDst( 0, 0, nDstItemWidth, nDstItemHeight );
  2741. int nStackItemIndex, nX, nY;
  2742. for( nStackItemIndex = 0; nStackItemIndex < nStackItemCount; nStackItemIndex++ )
  2743. {
  2744. for( nY = 0; nY < nSrcItemHeight; nY++ )
  2745. {
  2746. for( nX = 0; nX < nSrcItemWidth; nX++ )
  2747. {
  2748. RGBQUAD _pixel;
  2749. VERIFY(
  2750. bmpSrcStack.GetPixel(
  2751. nX + rcSrc.left,
  2752. nY + rcSrc.top,
  2753. _pixel
  2754. )
  2755. );
  2756. switch( nAngleCw90 )
  2757. {
  2758. case 0:
  2759. case 360:
  2760. {
  2761. VERIFY(
  2762. SetPixel(
  2763. nX + rcDst.left,
  2764. nY + rcDst.top,
  2765. _pixel
  2766. )
  2767. );
  2768. }
  2769. break;
  2770. case 90:
  2771. {
  2772. VERIFY(
  2773. SetPixel(
  2774. nDstItemWidth - 1 - nY + rcDst.left,
  2775. nX + rcDst.top,
  2776. _pixel
  2777. )
  2778. );
  2779. }
  2780. break;
  2781. case 180:
  2782. {
  2783. VERIFY(
  2784. SetPixel(
  2785. nDstItemWidth - 1 - nX + rcDst.left,
  2786. nDstItemHeight - 1 - nY + rcDst.top,
  2787. _pixel
  2788. )
  2789. );
  2790. }
  2791. break;
  2792. case 270:
  2793. {
  2794. VERIFY(
  2795. SetPixel(
  2796. nY + rcDst.left,
  2797. nDstItemHeight - 1 - nX + rcDst.top,
  2798. _pixel
  2799. )
  2800. );
  2801. }
  2802. break;
  2803. } // switch( nAngleCw90 )
  2804. } // for( nX = 0; nX < nSrcItemWidth; nX++ )
  2805. } // for( nY = 0; nY < nSrcItemHeight; nY++ )
  2806. rcSrc.OffsetRect(
  2807. bSrcStackIsHorizontal ? nSrcItemWidth : 0,
  2808. bSrcStackIsHorizontal ? 0: nSrcItemHeight
  2809. );
  2810. rcDst.OffsetRect(
  2811. bDstStackIsHorizontal ? nDstItemWidth : 0,
  2812. bDstStackIsHorizontal ? 0: nDstItemHeight
  2813. );
  2814. }
  2815. return true;
  2816. }
  2817. HICON CExtBitmap::CreateHICON(
  2818. bool bReplaceSysColors, // = true
  2819. COLORREF clrTransparent // = COLORREF(-1L)
  2820. ) const
  2821. {
  2822. if( IsEmpty() )
  2823. return NULL;
  2824. CSize _sizeBitmap = GetSize();
  2825. CRect rcClone( 0, 0, _sizeBitmap.cx, _sizeBitmap.cy );
  2826. HBITMAP hBmpSrc = CreateBitmap( false );
  2827. if( hBmpSrc == NULL )
  2828. {
  2829. ASSERT( FALSE );
  2830. return NULL;
  2831. }
  2832. CBitmap _bmpDestructor;
  2833. _bmpDestructor.Attach( hBmpSrc );
  2834. BITMAP bmpDescription;
  2835. ::memset( &bmpDescription, 0, sizeof(BITMAP) );
  2836. ::GetObject( hBmpSrc, sizeof(BITMAP), &bmpDescription );
  2837. ASSERT( bmpDescription.bmWidth > 0 && bmpDescription.bmHeight > 0 );
  2838. CImageList _il;
  2839. if( !_il.Create(
  2840. bmpDescription.bmWidth,
  2841. bmpDescription.bmHeight,
  2842. ILC_COLOR32|ILC_MASK,
  2843. 0,
  2844. 1
  2845. )
  2846. )
  2847. {
  2848. // ASSERT( FALSE );
  2849. return NULL;
  2850. }
  2851. if( clrTransparent == COLORREF(-1L) )
  2852. clrTransparent = RGB(255,0,255);
  2853. COLORREF * pSurface = NULL;
  2854. HBITMAP hBmpExtracted = stat_CloneBitmap( hBmpSrc, &rcClone, &pSurface );
  2855. if( hBmpExtracted == NULL || pSurface == NULL )
  2856. {
  2857. ASSERT( FALSE );
  2858. return NULL;
  2859. }
  2860. CBitmap bmpExtracted;
  2861. bmpExtracted.Attach( hBmpExtracted );
  2862. if( bReplaceSysColors )
  2863. {
  2864. COLORREF quadClrTransparent =
  2865. RGB(
  2866. GetBValue(clrTransparent),
  2867. GetGValue(clrTransparent),
  2868. GetRValue(clrTransparent)
  2869. );
  2870. struct
  2871. {
  2872. COLORREF m_quadClrSrc;
  2873. COLORREF m_quadClrDst;
  2874. INT m_nDstSysColorIdx;
  2875. bool m_bReplace;
  2876. } _repl_arr[] =
  2877. {
  2878. { RGB(128,128,128), RGB(0,0,0), COLOR_3DSHADOW, true },
  2879. { RGB(192,192,192), RGB(0,0,0), COLOR_3DFACE, true },
  2880. { RGB(223,223,223), RGB(0,0,0), COLOR_3DLIGHT, true },
  2881. };
  2882. const int nReplCount =
  2883. sizeof(_repl_arr) / sizeof(_repl_arr[0]);
  2884. int nReplReal = 0;
  2885. for( int n = 0; n < nReplCount; n++ )
  2886. {
  2887. if( _repl_arr[n].m_quadClrSrc == quadClrTransparent )
  2888. {
  2889. _repl_arr[n].m_bReplace = false;
  2890. continue;
  2891. }
  2892. _repl_arr[n].m_quadClrDst =
  2893. ::GetSysColor( _repl_arr[n].m_nDstSysColorIdx );
  2894. _repl_arr[n].m_quadClrDst =
  2895. RGB(
  2896. GetBValue(_repl_arr[n].m_quadClrDst),
  2897. GetGValue(_repl_arr[n].m_quadClrDst),
  2898. GetRValue(_repl_arr[n].m_quadClrDst)
  2899. );
  2900. if( _repl_arr[n].m_quadClrDst == _repl_arr[n].m_quadClrSrc )
  2901. {
  2902. _repl_arr[n].m_bReplace = false;
  2903. continue;
  2904. }
  2905. nReplReal++;
  2906. } // for( int n = 0; n < nReplCount; n++ )
  2907. if( nReplReal > 0 )
  2908. {
  2909. LONG nPixelCount =
  2910. bmpDescription.bmWidth * bmpDescription.bmHeight;
  2911. for( LONG nPos = 0; nPos < nPixelCount; nPos++ )
  2912. {
  2913. if( pSurface[nPos] == quadClrTransparent )
  2914. continue;
  2915. for( int n = 0; n < nReplCount; n++ )
  2916. {
  2917. if( ! (_repl_arr[n].m_bReplace) )
  2918. continue;
  2919. if( pSurface[nPos] != _repl_arr[n].m_quadClrSrc )
  2920. continue;
  2921. pSurface[nPos] = _repl_arr[n].m_quadClrDst;
  2922. } // for( int n = 0; n < nReplCount; n++ )
  2923. } // for( LONG nPos = 0; nPos < nPixelCount; nPos++ )
  2924. } // if( nReplReal > 0 )
  2925. } // if( bReplaceSysColors )
  2926. // first method creates icon indirect
  2927. // (this way is needed for older Windows OS versions)
  2928. if( g_PaintManager.m_bIsWin9x || (!g_PaintManager.m_bIsWin2000orLater) )
  2929. {
  2930. ICONINFO ii;
  2931. ::memset( &ii, 0, sizeof(ICONINFO) );
  2932. ii.fIcon = TRUE;
  2933. ii.xHotspot = bmpDescription.bmWidth;
  2934. ii.yHotspot = bmpDescription.bmHeight;
  2935. ii.hbmColor = (HBITMAP)bmpExtracted.GetSafeHandle();
  2936. ii.hbmMask =
  2937. ::CreateBitmap(
  2938. bmpDescription.bmWidth,
  2939. bmpDescription.bmHeight,
  2940. 1,
  2941. 1,
  2942. NULL
  2943. );
  2944. ASSERT( ii.hbmMask != NULL );
  2945. if( ii.hbmMask != NULL )
  2946. {
  2947. HICON hIcon = NULL;
  2948. CDC dcMask, dcColor;
  2949. if( dcMask.CreateCompatibleDC( NULL )
  2950. && dcColor.CreateCompatibleDC( NULL )
  2951. )
  2952. {
  2953. HGDIOBJ hBmpMaskOld =
  2954. ::SelectObject( dcMask.m_hDC, ii.hbmMask );
  2955. HGDIOBJ hBmpColorOld =
  2956. ::SelectObject( dcColor.m_hDC, ii.hbmColor );
  2957. HBRUSH hStockWhiteBrush = (HBRUSH)
  2958. ::GetStockObject( WHITE_BRUSH );
  2959. CRect rcSurface(
  2960. 0,
  2961. 0,
  2962. bmpDescription.bmWidth,
  2963. bmpDescription.bmHeight
  2964. );
  2965. ::FillRect( dcMask.m_hDC, &rcSurface, hStockWhiteBrush );
  2966. INT nX, nY;
  2967. for( nX = 0; nX < bmpDescription.bmWidth; nX++ )
  2968. {
  2969. for( nY = 0; nY < bmpDescription.bmHeight; nY++ )
  2970. {
  2971. COLORREF clr = dcColor.GetPixel( nX, nY );
  2972. if( clr != clrTransparent )
  2973. dcMask.SetPixel( nX, nY, RGB(0,0,0) );
  2974. else
  2975. dcColor.SetPixel( nX, nY, RGB(0,0,0) );
  2976. } // for( nY = 0; nY < bmpDescription.bmHeight; nY++ )
  2977. } // for( nX = 0; nX < bmpDescription.bmWidth; nX++ )
  2978. ::SelectObject( dcMask.m_hDC, hBmpMaskOld );
  2979. ::SelectObject( dcColor.m_hDC, hBmpColorOld );
  2980. hIcon = ::CreateIconIndirect( &ii );
  2981. ASSERT( hIcon != NULL );
  2982. } // if( dcMask.CreateCompatibleDC( NULL ) ...
  2983. #ifdef _DEBUG
  2984. else
  2985. {
  2986. ASSERT( FALSE );
  2987. } // else from if( dcMask.CreateCompatibleDC( NULL ) )
  2988. #endif // _DEBUG
  2989. ::DeleteObject( ii.hbmMask );
  2990. if( hIcon != NULL )
  2991. return hIcon;
  2992. } // if( ii.hbmMask != NULL )
  2993. } // if( g_PaintManager.m_bIsWin9x || (!g_PaintManager.m_bIsWin2000orLater) )
  2994. // second method creates icon via image list
  2995. // (this way is better for Windows 2000 or higher NT OS branch)
  2996. int nImgIdx =
  2997. _il.Add( &bmpExtracted, clrTransparent );
  2998. if( nImgIdx < 0 )
  2999. {
  3000. // ASSERT( FALSE );
  3001. return NULL;
  3002. }
  3003. HICON hIcon = _il.ExtractIcon( nImgIdx );
  3004. // ASSERT( hIcon != NULL );
  3005. return hIcon;
  3006. }
  3007. HBITMAP CExtBitmap::CreateBitmap( 
  3008. HDC hDC,
  3009. bool bCreateDDB // = true
  3010. ) const
  3011. {
  3012. if( IsEmpty() )
  3013. return NULL;
  3014. if( hDC == NULL )
  3015. {
  3016. ASSERT( FALSE );
  3017. return NULL;
  3018. }
  3019. HBITMAP hBitmap = NULL;
  3020. if( bCreateDDB )
  3021. {
  3022. hBitmap =
  3023. ::CreateDIBitmap(
  3024. hDC,
  3025. stat_RcInfoHeader( m_pImageBuffer ),
  3026. CBM_INIT,
  3027. stat_RcSurface( m_pImageBuffer ),
  3028. stat_RcInfo( m_pImageBuffer ),
  3029. DIB_RGB_COLORS
  3030. );
  3031. }
  3032. else
  3033. {
  3034. HDC hDCSrc = ::CreateCompatibleDC( hDC );
  3035. if( hDCSrc != NULL )
  3036. {
  3037. CDC _dcDestructor;
  3038. _dcDestructor.Attach( hDCSrc );
  3039. LPBITMAPINFOHEADER pBIH = 
  3040. CExtBitmap::stat_RcInfoHeader( m_pImageBuffer );
  3041. DWORD biWidth = pBIH->biWidth;
  3042. DWORD biHeight = pBIH->biHeight;
  3043. WORD biPlanes = 1; //pBIH->biPlanes;
  3044. WORD biBitCount = 32; //pBIH->biBitCount;
  3045. DWORD biCompression = BI_RGB; // pBIH->biCompression;
  3046. DWORD biClrUsed = pBIH->biClrUsed;
  3047. DWORD biClrImportant = pBIH->biClrImportant;
  3048. BITMAPINFOHEADER bih;
  3049. ::memset( &bih, 0, sizeof( BITMAPINFOHEADER ) );
  3050. bih.biSize = sizeof( BITMAPINFOHEADER );
  3051. bih.biWidth = biWidth;
  3052. bih.biHeight = biHeight;
  3053. bih.biPlanes = biPlanes;
  3054. bih.biBitCount = biBitCount;
  3055. bih.biCompression = biCompression;
  3056. bih.biSizeImage = biWidth * biHeight;
  3057. bih.biClrUsed = biClrUsed;
  3058. bih.biClrImportant = biClrImportant;
  3059. COLORREF * pClrSurface = NULL;
  3060. hBitmap =
  3061. ::CreateDIBSection(
  3062. hDCSrc,
  3063. (LPBITMAPINFO)&bih,
  3064. DIB_RGB_COLORS,
  3065. (void **)&pClrSurface,
  3066. NULL,
  3067. NULL
  3068. );
  3069. if( hBitmap != NULL 
  3070. && pClrSurface != NULL 
  3071. )
  3072. {
  3073. HGDIOBJ hBitmapOld = ::SelectObject( hDCSrc, (HGDIOBJ)hBitmap );
  3074. Draw(
  3075. hDCSrc,
  3076. 0,0,
  3077. biWidth,
  3078. biHeight,
  3079. SRCCOPY
  3080. );
  3081. ::SelectObject( hDCSrc, (HGDIOBJ)hBitmapOld );
  3082. }
  3083. } // if( hDCSrc != NULL )
  3084. }
  3085. return hBitmap;
  3086. }
  3087. HBITMAP CExtBitmap::CreateBitmap(
  3088. bool bCreateDDB // = true
  3089. ) const
  3090. {
  3091. if( IsEmpty() )
  3092. return NULL;
  3093. HDC hDC = ::CreateCompatibleDC( NULL );
  3094. if( hDC == NULL )
  3095. return NULL;
  3096. CDC dc;
  3097. dc.Attach( hDC );
  3098. return CreateBitmap( dc.m_hDC, bCreateDDB );
  3099. }
  3100. HBITMAP CExtBitmap::CreateBitmap( 
  3101. HDC hDC, 
  3102. COLORREF ** ppClrSurface,
  3103. COLORREF clrFillBk // = COLORREF(-1L)
  3104. ) const
  3105. {
  3106. if( ppClrSurface != NULL )
  3107. (*ppClrSurface) = NULL;
  3108. if( IsEmpty() )
  3109. return NULL;
  3110. if( hDC == NULL )
  3111. {
  3112. ASSERT( FALSE );
  3113. return NULL;
  3114. }
  3115. HDC hDCSrc = ::CreateCompatibleDC( hDC );
  3116. if( hDCSrc == NULL )
  3117. {
  3118. ASSERT( FALSE );
  3119. return NULL;
  3120. }
  3121. CDC _dcDestructor;
  3122. _dcDestructor.Attach( hDCSrc );
  3123. LPBITMAPINFOHEADER pBIH = 
  3124. CExtBitmap::stat_RcInfoHeader( m_pImageBuffer );
  3125. DWORD biWidth = pBIH->biWidth;
  3126. DWORD biHeight = pBIH->biHeight;
  3127. WORD biPlanes = 1;
  3128. WORD biBitCount = 32;
  3129. DWORD biCompression = BI_RGB;
  3130. DWORD biClrUsed = pBIH->biClrUsed;
  3131. DWORD biClrImportant = pBIH->biClrImportant;
  3132. BITMAPINFOHEADER bih;
  3133. ::memset( &bih, 0, sizeof( BITMAPINFOHEADER ) );
  3134. bih.biSize = sizeof( BITMAPINFOHEADER );
  3135. bih.biWidth = biWidth;
  3136. bih.biHeight = biHeight;
  3137. bih.biPlanes = biPlanes;
  3138. bih.biBitCount = biBitCount;
  3139. bih.biCompression = biCompression;
  3140. bih.biSizeImage = biWidth * biHeight;
  3141. bih.biClrUsed = biClrUsed;
  3142. bih.biClrImportant = biClrImportant;
  3143. COLORREF * pClrSurface = NULL;
  3144. HBITMAP hBitmap =
  3145. ::CreateDIBSection(
  3146. hDCSrc,
  3147. (LPBITMAPINFO)&bih,
  3148. DIB_RGB_COLORS,
  3149. (void **)&pClrSurface,
  3150. NULL,
  3151. NULL
  3152. );
  3153. if( hBitmap != NULL && pClrSurface != NULL )
  3154. {
  3155. HGDIOBJ hBitmapOld = ::SelectObject( hDCSrc, (HGDIOBJ)hBitmap );
  3156. if( clrFillBk != COLORREF(-1L) )
  3157. {
  3158. COLORREF clrBkOld = ::SetBkColor( hDCSrc, clrFillBk );
  3159. CRect rc( 0, 0, biWidth, biHeight );
  3160. ::ExtTextOut( hDCSrc, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL );
  3161. ::SetBkColor( hDCSrc, clrBkOld );
  3162. } // if( clrFillBk != COLORREF(-1L) )
  3163. AlphaBlend(
  3164. hDCSrc,
  3165. 0,
  3166. 0,
  3167. biWidth,
  3168. biHeight
  3169. );
  3170. ::SelectObject( hDCSrc, (HGDIOBJ)hBitmapOld );
  3171. if( ppClrSurface != NULL )
  3172. (*ppClrSurface) = pClrSurface;
  3173. } // if( hBitmap != NULL && pClrSurface != NULL )
  3174. return hBitmap;
  3175. }
  3176. HBITMAP CExtBitmap::CreateBitmap(
  3177. COLORREF ** ppClrSurface,
  3178. COLORREF clrFillBk // = COLORREF(-1L)
  3179. ) const
  3180. {
  3181. if( IsEmpty() )
  3182. return NULL;
  3183. HDC hDC = ::CreateCompatibleDC( NULL );
  3184. if( hDC == NULL )
  3185. return NULL;
  3186. CDC dc;
  3187. dc.Attach( hDC );
  3188. return CreateBitmap( dc.m_hDC, ppClrSurface, clrFillBk );
  3189. }
  3190. bool CExtBitmap::g_bIsAutoPreMultiplyRGBChannels = true;
  3191. bool CExtBitmap::IsAutoPreMultiplyRGBChannels() const
  3192. {
  3193. return g_bIsAutoPreMultiplyRGBChannels;
  3194. }
  3195. void CExtBitmap::PreMultiplyRGBChannels(
  3196. bool bForward // = true
  3197. )
  3198. {
  3199. if( IsEmpty() )
  3200. return;
  3201. ULONG nBPP = GetBPP();
  3202. if( nBPP != 32 )
  3203. return;
  3204. CSize _size = GetSize();
  3205. LONG nX, nY;
  3206. for( nY = 0; nY < _size.cy; nY++ )
  3207. {
  3208. LPBYTE pScanLine = stat_RcSurface(m_pImageBuffer) + _size.cx * 4 * nY;
  3209. for( nX = 0; nX < _size.cx; nX++ )
  3210. {
  3211. int nAlpha = pScanLine[3];
  3212. if( bForward )
  3213. {
  3214. pScanLine[0] = BYTE( pScanLine[0] * nAlpha / 255 );
  3215. pScanLine[1] = BYTE( pScanLine[1] * nAlpha / 255 );
  3216. pScanLine[2] = BYTE( pScanLine[2] * nAlpha / 255 );
  3217. }
  3218. else
  3219. {
  3220. if( nAlpha != 0 )
  3221. {
  3222. //pScanLine[0] = BYTE( pScanLine[0] * 255 / nAlpha  );
  3223. //pScanLine[1] = BYTE( pScanLine[1] * 255 / nAlpha  );
  3224. //pScanLine[2] = BYTE( pScanLine[2] * 255 / nAlpha );
  3225. INT xArr[3] =
  3226. {
  3227. INT( pScanLine[0] * 255 / nAlpha  ),
  3228. INT( pScanLine[1] * 255 / nAlpha  ),
  3229. INT( pScanLine[2] * 255 / nAlpha ),
  3230. };
  3231. for( INT k = 0; k < 3; k++ )
  3232. pScanLine[ k ] = BYTE( min( 255, xArr[ k ] ) );
  3233. }
  3234. }
  3235. pScanLine += 4;
  3236. } // for( nX = 0; nX < _size.cx; nX++ )
  3237. } // for( nY = 0; nY < _size.cy; nY++ )
  3238. OnContentChanged();
  3239. }
  3240. bool CExtBitmap::PreMultipliedRGBChannelsGet() const
  3241. {
  3242. if( IsEmpty() )
  3243. return false;
  3244. return stat_PreMultipliedRGBChannelsGet( LPBYTE(m_pImageBuffer) );
  3245. }
  3246. void CExtBitmap::PreMultipliedRGBChannelsSet( bool bPreMultiplied )
  3247. {
  3248. if( IsEmpty() )
  3249. return;
  3250. stat_PreMultipliedRGBChannelsSet( LPBYTE(m_pImageBuffer), bPreMultiplied );
  3251. }
  3252. void CExtBitmap::MakeMono(
  3253. COLORREF clr, // = COLORREF(-1L)
  3254. LPCRECT pRect // = NULL
  3255. )
  3256. {
  3257. if( IsEmpty() )
  3258. return;
  3259. ULONG nBPP = GetBPP();
  3260. if( nBPP < 15 )
  3261. return;
  3262. CSize _size = GetSize();
  3263. CRect _rcFrame;
  3264. if( pRect != NULL )
  3265. {
  3266. _rcFrame = (*pRect);
  3267. if( _rcFrame.left < 0 )
  3268. _rcFrame.left = 0;
  3269. if( _rcFrame.top < 0 )
  3270. _rcFrame.top = 0;
  3271. if( _rcFrame.right > _size.cx )
  3272. _rcFrame.right = _size.cx;
  3273. if( _rcFrame.bottom > _size.cy )
  3274. _rcFrame.bottom = _size.cy;
  3275. }
  3276. else
  3277. _rcFrame.SetRect( 0, 0, _size.cx, _size.cy );
  3278. if( _rcFrame.left >= _rcFrame.right
  3279. || _rcFrame.top >= _rcFrame.bottom
  3280. )
  3281. return;
  3282. double clrH = 0.0, H = 0.0, clrS = 0.0, S = 0.0, L = 0.0;
  3283. if( clr != COLORREF(-1L) )
  3284. stat_RGBtoHSL( clr, &clrH, &clrS, &L );
  3285. LONG nX, nY;
  3286. for( nY = _rcFrame.top; nY < _rcFrame.bottom; nY++ )
  3287. {
  3288. for( nX = _rcFrame.left; nX < _rcFrame.right; nX++ )
  3289. {
  3290. RGBQUAD _pixel;
  3291. VERIFY( GetPixel( nX, nY, _pixel ) );
  3292. double lfVal =
  3293. double( _pixel.rgbBlue  ) * 0.11 // * 0.30
  3294. + double( _pixel.rgbGreen ) * 0.59 // * 0.50
  3295. + double( _pixel.rgbRed   ) * 0.30 // * 0.20
  3296. ;
  3297. if( lfVal > 255.0 )
  3298. lfVal = 255.0;
  3299. _pixel.rgbBlue = _pixel.rgbGreen = _pixel.rgbRed
  3300. = BYTE( INT( lfVal ) );
  3301. if( clr != COLORREF(-1L) )
  3302. {
  3303. stat_RGBtoHSL(
  3304. RGB( _pixel.rgbRed, _pixel.rgbGreen, _pixel.rgbBlue ),
  3305. &H,
  3306. &S,
  3307. &L
  3308. );
  3309. COLORREF clrTarget = stat_HLStoRGB( clrH, L, clrS );
  3310. _pixel.rgbRed   = GetRValue( clrTarget );
  3311. _pixel.rgbGreen = GetGValue( clrTarget );
  3312. _pixel.rgbBlue  = GetBValue( clrTarget );
  3313. } // if( clr != COLORREF(-1L) )
  3314. VERIFY( SetPixel( nX, nY, _pixel ) );
  3315. } // for( nX = _rcFrame.left; nX < _rcFrame.right; nX++ )
  3316. } // for( nY = _rcFrame.top; nY < _rcFrame.bottom; nY++ )
  3317. OnContentChanged();
  3318. }
  3319. void CExtBitmap::AlphaColor(
  3320. COLORREF clr,
  3321. COLORREF clrTolerance,
  3322. BYTE nAlpha,
  3323. LPCRECT pRect // = NULL
  3324. )
  3325. {
  3326. if( IsEmpty() )
  3327. return;
  3328. ULONG nBPP = GetBPP();
  3329. if( nBPP != 32 )
  3330. return;
  3331. if( PreMultipliedRGBChannelsGet() )
  3332. {
  3333. PreMultiplyRGBChannels( false );
  3334. PreMultipliedRGBChannelsSet( false );
  3335. }
  3336. CSize _size = GetSize();
  3337. CRect _rcFrame;
  3338. if( pRect != NULL )
  3339. {
  3340. _rcFrame = (*pRect);
  3341. if( _rcFrame.left < 0 )
  3342. _rcFrame.left = 0;
  3343. if( _rcFrame.top < 0 )
  3344. _rcFrame.top = 0;
  3345. if( _rcFrame.right > _size.cx )
  3346. _rcFrame.right = _size.cx;
  3347. if( _rcFrame.bottom > _size.cy )
  3348. _rcFrame.bottom = _size.cy;
  3349. }
  3350. else
  3351. _rcFrame.SetRect( 0, 0, _size.cx, _size.cy );
  3352. if( _rcFrame.left >= _rcFrame.right
  3353. || _rcFrame.top >= _rcFrame.bottom
  3354. )
  3355. return;
  3356. BYTE nLowRed = GetRValue( clr );
  3357. BYTE nLowGreen = GetGValue( clr );
  3358. BYTE nLowBlue = GetBValue( clr );
  3359. BYTE nHighRed = BYTE( min( 0xff, ( nLowRed + GetRValue(clrTolerance) ) ) );
  3360. BYTE nHighGreen = BYTE( min( 0xff, ( nLowGreen + GetGValue(clrTolerance) ) ) );
  3361. BYTE nHighBlue = BYTE( min( 0xff, ( nLowBlue + GetBValue(clrTolerance) ) ) );
  3362. LONG nX, nY;
  3363. for( nY = _rcFrame.top; nY < _rcFrame.bottom; nY++ )
  3364. {
  3365. for( nX = _rcFrame.left; nX < _rcFrame.right; nX++ )
  3366. {
  3367. RGBQUAD _pixel;
  3368. VERIFY( GetPixel( nX, nY, _pixel ) );
  3369. if( _pixel.rgbRed >= nLowRed && _pixel.rgbRed <= nHighRed )
  3370. {
  3371. if( _pixel.rgbGreen >= nLowGreen && _pixel.rgbGreen <= nHighGreen )
  3372. {
  3373. if( _pixel.rgbBlue >= nLowBlue && _pixel.rgbBlue <= nHighBlue )
  3374. {
  3375. _pixel.rgbReserved = nAlpha;
  3376. VERIFY( SetPixel( nX, nY, _pixel ) );
  3377. }
  3378. } // if( nColorPart >= nLowGreen && nColorPart <= nHighGreen )
  3379. } // if( nColorPart >= nLowRed && nColorPart <= nHighRed )
  3380. } // for( nX = _rcFrame.left; nX < _rcFrame.right; nX++ )
  3381. } // for( nY = _rcFrame.top; nY < _rcFrame.bottom; nY++ )
  3382. OnContentChanged();
  3383. }
  3384. void CExtBitmap::AlphaColorDistance(
  3385. COLORREF clr,
  3386. INT nDistance,
  3387. BYTE nAlpha,
  3388. LPCRECT pRect // = NULL
  3389. )
  3390. {
  3391. if( IsEmpty() )
  3392. return;
  3393. ULONG nBPP = GetBPP();
  3394. if( nBPP != 32 )
  3395. return;
  3396. if( PreMultipliedRGBChannelsGet() )
  3397. {
  3398. PreMultiplyRGBChannels( false );
  3399. PreMultipliedRGBChannelsSet( false );
  3400. }
  3401. CSize _size = GetSize();
  3402. CRect _rcFrame;
  3403. if( pRect != NULL )
  3404. {
  3405. _rcFrame = (*pRect);
  3406. if( _rcFrame.left < 0 )
  3407. _rcFrame.left = 0;
  3408. if( _rcFrame.top < 0 )
  3409. _rcFrame.top = 0;
  3410. if( _rcFrame.right > _size.cx )
  3411. _rcFrame.right = _size.cx;
  3412. if( _rcFrame.bottom > _size.cy )
  3413. _rcFrame.bottom = _size.cy;
  3414. }
  3415. else
  3416. _rcFrame.SetRect( 0, 0, _size.cx, _size.cy );
  3417. if( _rcFrame.left >= _rcFrame.right
  3418. || _rcFrame.top >= _rcFrame.bottom
  3419. )
  3420. return;
  3421. INT nSrcRed = INT( GetRValue(clr) );
  3422. INT nSrcGreen = INT( GetGValue(clr) );
  3423. INT nSrcBlue = INT( GetBValue(clr) );
  3424. LONG nX, nY;
  3425. INT nDistance2 = nDistance*nDistance;
  3426. for( nY = _rcFrame.top; nY < _rcFrame.bottom; nY++ )
  3427. {
  3428. for( nX = _rcFrame.left; nX < _rcFrame.right; nX++ )
  3429. {
  3430. RGBQUAD _pixel;
  3431. VERIFY( GetPixel( nX, nY, _pixel ) );
  3432. INT nTest2 = 
  3433.   INT(_pixel.rgbRed)*INT(nSrcRed)
  3434. + INT(_pixel.rgbGreen)*INT(nSrcGreen)
  3435. + INT(_pixel.rgbBlue)*INT(nSrcBlue)
  3436. ;
  3437. if( nTest2 <= nDistance2 )
  3438. {
  3439. _pixel.rgbReserved = nAlpha;
  3440. VERIFY( SetPixel( nX, nY, _pixel ) );
  3441. }
  3442. } // for( nX = _rcFrame.left; nX < _rcFrame.right; nX++ )
  3443. } // for( nY = _rcFrame.top; nY < _rcFrame.bottom; nY++ )
  3444. OnContentChanged();
  3445. }
  3446. void CExtBitmap::AlphaRect(
  3447. const RECT & rcFrame,
  3448. BYTE nAlpha,
  3449. COLORREF clrTransparent, // = COLORREF(-1L),
  3450. COLORREF clrOpaque // = COLORREF(-1L)
  3451. )
  3452. {
  3453. if( IsEmpty() )
  3454. return;
  3455. ULONG nBPP = GetBPP();
  3456. if( nBPP != 32 )
  3457. return;
  3458. if( PreMultipliedRGBChannelsGet() )
  3459. {
  3460. PreMultiplyRGBChannels( false );
  3461. PreMultipliedRGBChannelsSet( false );
  3462. }
  3463. CRect _rcFrame = rcFrame;
  3464. if( _rcFrame.left < 0 )
  3465. _rcFrame.left = 0;
  3466. if( _rcFrame.top < 0 )
  3467. _rcFrame.top = 0;
  3468. CSize _size = GetSize();
  3469. if( _rcFrame.right > _size.cx )
  3470. _rcFrame.right = _size.cx;
  3471. if( _rcFrame.bottom > _size.cy )
  3472. _rcFrame.bottom = _size.cy;
  3473. if( _rcFrame.left >= _rcFrame.right
  3474. || _rcFrame.top >= _rcFrame.bottom
  3475. )
  3476. return;
  3477. LONG nX, nY;
  3478. RGBQUAD _pixelAlpha = { 0, 0, 0, nAlpha };
  3479. RGBQUAD _pixelTransparent = { 0, 0, 0, 0 };
  3480. RGBQUAD _pixelOpaque = { 0, 0, 0, 0xFF };
  3481. for( nY = _rcFrame.top; nY < _rcFrame.bottom; nY++ )
  3482. {
  3483. for( nX = _rcFrame.left; nX < _rcFrame.right; nX++ )
  3484. {
  3485. if( clrTransparent != COLORREF(-1L)
  3486. || clrOpaque != COLORREF(-1L)
  3487. )
  3488. {
  3489. COLORREF clr = GetPixel( nX, nY );
  3490. if( clr == clrTransparent )
  3491. {
  3492. SetPixel( nX, nY, _pixelTransparent, false, false, false, true );
  3493. continue;
  3494. }
  3495. if( clr == clrOpaque )
  3496. {
  3497. SetPixel( nX, nY, _pixelOpaque, false, false, false, true );
  3498. continue;
  3499. }
  3500. }
  3501. SetPixel( nX, nY, _pixelAlpha, false, false, false, true );
  3502. } // for( nX = _rcFrame.left; nX < _rcFrame.right; nX++ )
  3503. } // for( nY = _rcFrame.top; nY < _rcFrame.bottom; nY++ )
  3504. OnContentChanged();
  3505. }
  3506. void CExtBitmap::AlphaFrame(
  3507. const RECT & rcFrame,
  3508. const RECT & rcPadding,
  3509. BYTE nAlpha,
  3510. COLORREF clrTransparent, // = COLORREF(-1L),
  3511. COLORREF clrOpaque // = COLORREF(-1L)
  3512. )
  3513. {
  3514. if( IsEmpty() )
  3515. return;
  3516. ULONG nBPP = GetBPP();
  3517. if( nBPP != 32 )
  3518. return;
  3519. if( PreMultipliedRGBChannelsGet() )
  3520. {
  3521. PreMultiplyRGBChannels( false );
  3522. PreMultipliedRGBChannelsSet( false );
  3523. }
  3524. CRect rcTop(
  3525. rcFrame.left,
  3526. rcFrame.top,
  3527. rcFrame.right,
  3528. rcFrame.top + rcPadding.top
  3529. );
  3530. AlphaRect(
  3531. rcTop,
  3532. nAlpha,
  3533. clrTransparent,
  3534. clrOpaque
  3535. );
  3536. CRect rcBottom(
  3537. rcFrame.left,
  3538. rcFrame.bottom - rcPadding.bottom,
  3539. rcFrame.right,
  3540. rcFrame.bottom
  3541. );
  3542. AlphaRect(
  3543. rcBottom,
  3544. nAlpha,
  3545. clrTransparent,
  3546. clrOpaque
  3547. );
  3548. CRect rcLeft(
  3549. rcFrame.left,
  3550. rcFrame.top + rcPadding.top,
  3551. rcFrame.left + rcPadding.left,
  3552. rcFrame.bottom - rcPadding.bottom
  3553. );
  3554. AlphaRect(
  3555. rcLeft,
  3556. nAlpha,
  3557. clrTransparent,
  3558. clrOpaque
  3559. );
  3560. CRect rcRight(
  3561. rcFrame.right - rcPadding.right,
  3562. rcFrame.top + rcPadding.top,
  3563. rcFrame.right,
  3564. rcFrame.bottom - rcPadding.bottom
  3565. );
  3566. AlphaRect(
  3567. rcRight,
  3568. nAlpha,
  3569. clrTransparent,
  3570. clrOpaque
  3571. );
  3572. }
  3573. int CExtBitmap::DrawImpl(
  3574. HDC hDC,
  3575. int nDstX,
  3576. int nDstY,
  3577. int nDstWidth,
  3578. int nDstHeight,
  3579. int nSrcX,
  3580. int nSrcY,
  3581. int nSrcWidth,
  3582. int nSrcHeight,
  3583. DWORD dwRop // = SRCCOPY 
  3584. ) const
  3585. {
  3586. ASSERT( hDC != NULL );
  3587. if( IsEmpty() || hDC == NULL )
  3588. return GDI_ERROR;
  3589. return
  3590. ::StretchDIBits(
  3591. hDC,
  3592. nDstX,
  3593. nDstY,
  3594. nDstWidth,
  3595. nDstHeight,
  3596. nSrcX,
  3597. nSrcY,
  3598. nSrcWidth,
  3599. nSrcHeight,
  3600. stat_RcSurface( m_pImageBuffer ),
  3601. stat_RcInfo( m_pImageBuffer ),
  3602. DIB_RGB_COLORS,
  3603. dwRop
  3604. );
  3605. }
  3606. int CExtBitmap::Draw(
  3607. HDC hDC,
  3608. int nDstX,
  3609. int nDstY,
  3610. int nDstWidth,
  3611. int nDstHeight,
  3612. int nSrcX,
  3613. int nSrcY,
  3614. int nSrcWidth,
  3615. int nSrcHeight,
  3616. DWORD dwRop // = SRCCOPY 
  3617. ) const
  3618. {
  3619. if( IsEmpty() || hDC == NULL )
  3620. return GDI_ERROR;
  3621. CSize _size = GetSize();
  3622. ::OffsetWindowOrgEx( hDC, - nDstX, - nDstY, NULL );
  3623. int nRetVal =
  3624. DrawImpl(
  3625. hDC,
  3626. 0,
  3627. nDstHeight - 1,
  3628. nDstWidth,
  3629. - nDstHeight,
  3630. nSrcX,
  3631. _size.cy - nSrcY + 1,
  3632. nSrcWidth,
  3633. - nSrcHeight,
  3634. dwRop
  3635. );
  3636. ::OffsetWindowOrgEx( hDC, nDstX, nDstY, NULL );
  3637. return nRetVal;
  3638. }
  3639. int CExtBitmap::Draw(
  3640. HDC hDC,
  3641. int nDstX,
  3642. int nDstY,
  3643. int nDstWidth,
  3644. int nDstHeight,
  3645. DWORD dwRop // = SRCCOPY
  3646. ) const
  3647. {
  3648. ASSERT( hDC != NULL );
  3649. if( IsEmpty() || hDC == NULL )
  3650. return GDI_ERROR;
  3651. CSize _size = GetSize();
  3652. return
  3653. Draw(
  3654. hDC,
  3655. nDstX,
  3656. nDstY,
  3657. nDstWidth,
  3658. nDstHeight,
  3659. 0,
  3660. 0,
  3661. _size.cx,
  3662. _size.cy,
  3663. dwRop
  3664. );
  3665. }
  3666. int CExtBitmap::Draw(
  3667. HDC hDC,
  3668. const RECT & rcDst,
  3669. const RECT & rcSrc,
  3670. DWORD dwRop // = SRCCOPY 
  3671. ) const
  3672. {
  3673. ASSERT( hDC != NULL );
  3674. if( IsEmpty() || hDC == NULL )
  3675. return GDI_ERROR;
  3676. return Draw(
  3677. hDC,
  3678. rcDst.left,
  3679. rcDst.top,
  3680. rcDst.right - rcDst.left,
  3681. rcDst.bottom - rcDst.top,
  3682. rcSrc.left,
  3683. rcSrc.top,
  3684. rcSrc.right - rcSrc.left,
  3685. rcSrc.bottom - rcSrc.top,
  3686. dwRop  
  3687. );
  3688. }
  3689. int CExtBitmap::Draw(
  3690. HDC hDC,
  3691. const RECT & rcDst,
  3692. DWORD dwRop // = SRCCOPY
  3693. ) const
  3694. {
  3695. ASSERT( hDC != NULL );
  3696. if( IsEmpty() || hDC == NULL )
  3697. return GDI_ERROR;
  3698. CSize _size = GetSize();
  3699. CRect rcSrc( 0, 0, _size.cx, _size.cy );
  3700. return
  3701. Draw(
  3702. hDC,
  3703. rcDst,
  3704. rcSrc,
  3705. dwRop
  3706. );
  3707. }
  3708. bool CExtBitmap::DrawNcFrame(
  3709. HDC hDC,
  3710. const RECT & rcDstDraw,
  3711. const RECT & rcSrcDraw,
  3712. const RECT & rcPadding,
  3713. INT nCaptionHeightDst, // = 0
  3714. INT nCaptionHeightSrc, // = 0
  3715. bool bDrawMiddlePart, // = false
  3716. bool bSmootherAsPossible, // = true
  3717. DWORD dwRop // = SRCCOPY
  3718. ) const
  3719. {
  3720. ASSERT( hDC != NULL );
  3721. ASSERT( rcPadding.left >= 0 );
  3722. ASSERT( rcPadding.right >= 0 );
  3723. ASSERT( rcPadding.top >= 0 );
  3724. ASSERT( rcPadding.bottom >= 0 );
  3725. ASSERT( nCaptionHeightDst >= 0 );
  3726. ASSERT( nCaptionHeightSrc >= 0 );
  3727. ASSERT(
  3728. ( nCaptionHeightDst == 0 && nCaptionHeightSrc == 0 )
  3729. || ( nCaptionHeightSrc >  0 && nCaptionHeightSrc >  0 )
  3730. );
  3731. if( IsEmpty() || hDC == NULL )
  3732. return false;
  3733. int nOldStretchBltMode = ::GetStretchBltMode( hDC );
  3734. ::SetStretchBltMode(
  3735. hDC,
  3736. ( bSmootherAsPossible && g_PaintManager.m_bIsWinNT )
  3737. ? HALFTONE
  3738. : COLORONCOLOR
  3739. );
  3740. if( rcPadding.top > 0 || nCaptionHeightDst > 0 )
  3741. {
  3742. CRect rcDst(
  3743. rcDstDraw.left + rcPadding.left,
  3744. rcDstDraw.top,
  3745. rcDstDraw.right - rcPadding.right,
  3746. rcDstDraw.top + rcPadding.top + nCaptionHeightDst
  3747. );
  3748. CRect rcSrc(
  3749. rcSrcDraw.left + rcPadding.left,
  3750. rcSrcDraw.top,
  3751. rcSrcDraw.right - rcPadding.right,
  3752. rcSrcDraw.top + rcPadding.top + nCaptionHeightSrc
  3753. );
  3754. if( rcDst.left < rcDst.right
  3755. && rcDst.top < rcDst.bottom
  3756. && rcSrc.left < rcSrc.right
  3757. && rcSrc.top < rcSrc.bottom
  3758. )
  3759. Draw( hDC, rcDst, rcSrc, dwRop );
  3760. if( rcPadding.left > 0 )
  3761. {
  3762. CRect rcDst(
  3763. rcDstDraw.left,
  3764. rcDstDraw.top,
  3765. rcDstDraw.left + rcPadding.left,
  3766. rcDstDraw.top + rcPadding.top
  3767. );
  3768. CRect rcSrc(
  3769. rcSrcDraw.left,
  3770. rcSrcDraw.top,
  3771. rcSrcDraw.left + rcPadding.left,
  3772. rcSrcDraw.top + rcPadding.top
  3773. );
  3774. if( rcDst.left < rcDst.right
  3775. && rcDst.top < rcDst.bottom
  3776. && rcSrc.left < rcSrc.right
  3777. && rcSrc.top < rcSrc.bottom
  3778. )
  3779. Draw( hDC, rcDst, rcSrc, dwRop );
  3780. if( nCaptionHeightDst > 0 )
  3781. {
  3782. CRect rcDst(
  3783. rcDstDraw.left,
  3784. rcDstDraw.top + rcPadding.top,
  3785. rcDstDraw.left + rcPadding.left,
  3786. rcDstDraw.top + rcPadding.top + nCaptionHeightDst
  3787. );
  3788. CRect rcSrc(
  3789. rcSrcDraw.left,
  3790. rcSrcDraw.top + rcPadding.top,
  3791. rcSrcDraw.left + rcPadding.left,
  3792. rcSrcDraw.top + rcPadding.top + nCaptionHeightSrc
  3793. );
  3794. if( rcDst.left < rcDst.right
  3795. && rcDst.top < rcDst.bottom
  3796. && rcSrc.left < rcSrc.right
  3797. && rcSrc.top < rcSrc.bottom
  3798. )
  3799. Draw( hDC, rcDst, rcSrc, dwRop );
  3800. }
  3801. }
  3802. if( rcPadding.right > 0 )
  3803. {
  3804. CRect rcDst(
  3805. rcDstDraw.right - rcPadding.right,
  3806. rcDstDraw.top,
  3807. rcDstDraw.right,
  3808. rcDstDraw.top + rcPadding.top
  3809. );
  3810. CRect rcSrc(
  3811. rcSrcDraw.right - rcPadding.right,
  3812. rcSrcDraw.top,
  3813. rcSrcDraw.right,
  3814. rcSrcDraw.top + rcPadding.top
  3815. );
  3816. if( rcDst.left < rcDst.right
  3817. && rcDst.top < rcDst.bottom
  3818. && rcSrc.left < rcSrc.right
  3819. && rcSrc.top < rcSrc.bottom
  3820. )
  3821. Draw( hDC, rcDst, rcSrc, dwRop );
  3822. if( nCaptionHeightDst > 0 )
  3823. {
  3824. CRect rcDst(
  3825. rcDstDraw.right - rcPadding.right,
  3826. rcDstDraw.top + rcPadding.top,
  3827. rcDstDraw.right,
  3828. rcDstDraw.top + rcPadding.top + nCaptionHeightDst
  3829. );
  3830. CRect rcSrc(
  3831. rcSrcDraw.right - rcPadding.right,
  3832. rcSrcDraw.top + rcPadding.top,
  3833. rcSrcDraw.right,
  3834. rcSrcDraw.top + rcPadding.top + nCaptionHeightSrc
  3835. );
  3836. if( rcDst.left < rcDst.right
  3837. && rcDst.top < rcDst.bottom
  3838. && rcSrc.left < rcSrc.right
  3839. && rcSrc.top < rcSrc.bottom
  3840. )
  3841. Draw( hDC, rcDst, rcSrc, dwRop );
  3842. }
  3843. }
  3844. }
  3845. if( rcPadding.bottom > 0 )
  3846. {
  3847. CRect rcDst(
  3848. rcDstDraw.left + rcPadding.left,
  3849. rcDstDraw.bottom - rcPadding.bottom,
  3850. rcDstDraw.right - rcPadding.right,
  3851. rcDstDraw.bottom
  3852. );
  3853. CRect rcSrc(
  3854. rcSrcDraw.left + rcPadding.left,
  3855. rcSrcDraw.bottom - rcPadding.bottom,
  3856. rcSrcDraw.right - rcPadding.right,
  3857. rcSrcDraw.bottom
  3858. );
  3859. if( rcDst.left < rcDst.right
  3860. && rcDst.top < rcDst.bottom
  3861. && rcSrc.left < rcSrc.right
  3862. && rcSrc.top < rcSrc.bottom
  3863. )
  3864. Draw( hDC, rcDst, rcSrc, dwRop );
  3865. }
  3866. if( rcPadding.left > 0 )
  3867. {
  3868. CRect rcDst(
  3869. rcDstDraw.left,
  3870. rcDstDraw.top + rcPadding.top + nCaptionHeightDst,
  3871. rcDstDraw.left + rcPadding.left,
  3872. rcDstDraw.bottom - rcPadding.bottom
  3873. );
  3874. CRect rcSrc(
  3875. rcSrcDraw.left,
  3876. rcSrcDraw.top + rcPadding.top + nCaptionHeightSrc,
  3877. rcSrcDraw.left + rcPadding.left,
  3878. rcSrcDraw.bottom - rcPadding.bottom
  3879. );
  3880. if( rcDst.left < rcDst.right
  3881. && rcDst.top < rcDst.bottom
  3882. && rcSrc.left < rcSrc.right
  3883. && rcSrc.top < rcSrc.bottom
  3884. )
  3885. Draw( hDC, rcDst, rcSrc, dwRop );
  3886. if( rcPadding.bottom > 0 )
  3887. {
  3888. CRect rcDst(
  3889. rcDstDraw.left,
  3890. rcDstDraw.bottom - rcPadding.bottom,
  3891. rcDstDraw.left + rcPadding.left,
  3892. rcDstDraw.bottom
  3893. );
  3894. CRect rcSrc(
  3895. rcSrcDraw.left,
  3896. rcSrcDraw.bottom - rcPadding.bottom,
  3897. rcSrcDraw.left + rcPadding.left,
  3898. rcSrcDraw.bottom
  3899. );
  3900. if( rcDst.left < rcDst.right
  3901. && rcDst.top < rcDst.bottom
  3902. && rcSrc.left < rcSrc.right
  3903. && rcSrc.top < rcSrc.bottom
  3904. )
  3905. Draw( hDC, rcDst, rcSrc, dwRop );
  3906. }
  3907. }
  3908. if( rcPadding.right > 0 )
  3909. {
  3910. CRect rcDst(
  3911. rcDstDraw.right - rcPadding.right,
  3912. rcDstDraw.top + rcPadding.top + nCaptionHeightDst,
  3913. rcDstDraw.right,
  3914. rcDstDraw.bottom - rcPadding.bottom
  3915. );
  3916. CRect rcSrc(
  3917. rcSrcDraw.right - rcPadding.right,
  3918. rcSrcDraw.top + rcPadding.top + nCaptionHeightSrc,
  3919. rcSrcDraw.right,
  3920. rcSrcDraw.bottom - rcPadding.bottom
  3921. );
  3922. if( rcDst.left < rcDst.right
  3923. && rcDst.top < rcDst.bottom
  3924. && rcSrc.left < rcSrc.right
  3925. && rcSrc.top < rcSrc.bottom
  3926. )
  3927. Draw( hDC, rcDst, rcSrc, dwRop );
  3928. if( rcPadding.bottom > 0 )
  3929. {
  3930. CRect rcDst(
  3931. rcDstDraw.right - rcPadding.right,
  3932. rcDstDraw.bottom - rcPadding.bottom,
  3933. rcDstDraw.right,
  3934. rcDstDraw.bottom
  3935. );
  3936. CRect rcSrc(
  3937. rcSrcDraw.right - rcPadding.right,
  3938. rcSrcDraw.bottom - rcPadding.bottom,
  3939. rcSrcDraw.right,
  3940. rcSrcDraw.bottom
  3941. );
  3942. if( rcDst.left < rcDst.right
  3943. && rcDst.top < rcDst.bottom
  3944. && rcSrc.left < rcSrc.right
  3945. && rcSrc.top < rcSrc.bottom
  3946. )
  3947. Draw( hDC, rcDst, rcSrc, dwRop );
  3948. }
  3949. }
  3950. if( bDrawMiddlePart )
  3951. {
  3952. CRect rcDst(
  3953. rcDstDraw.left + rcPadding.left,
  3954. rcDstDraw.top + rcPadding.top + nCaptionHeightDst,
  3955. rcDstDraw.right - rcPadding.right,
  3956. rcDstDraw.bottom - rcPadding.bottom
  3957. );
  3958. CRect rcSrc(
  3959. rcSrcDraw.left + rcPadding.left,
  3960. rcSrcDraw.top + rcPadding.top + nCaptionHeightSrc,
  3961. rcSrcDraw.right - rcPadding.right,
  3962. rcSrcDraw.bottom - rcPadding.bottom
  3963. );
  3964. if( rcDst.left < rcDst.right
  3965. && rcDst.top < rcDst.bottom
  3966. && rcSrc.left < rcSrc.right
  3967. && rcSrc.top < rcSrc.bottom
  3968. )
  3969. Draw( hDC, rcDst, rcSrc, dwRop );
  3970. }
  3971. ::SetStretchBltMode(
  3972. hDC,
  3973. nOldStretchBltMode
  3974. );
  3975. return true;
  3976. }
  3977. bool CExtBitmap::DrawNcFrame(
  3978. HDC hDC,
  3979. const RECT & rcDstDraw,
  3980. const RECT & rcPadding,
  3981. INT nCaptionHeightDst, // = 0
  3982. INT nCaptionHeightSrc, // = 0
  3983. bool bDrawMiddlePart, // = false
  3984. bool bSmootherAsPossible, // = true
  3985. DWORD dwRop // = SRCCOPY
  3986. ) const
  3987. {
  3988. ASSERT( hDC != NULL );
  3989. ASSERT( rcPadding.left >= 0 );
  3990. ASSERT( rcPadding.right >= 0 );
  3991. ASSERT( rcPadding.top >= 0 );
  3992. ASSERT( rcPadding.bottom >= 0 );
  3993. ASSERT( nCaptionHeightDst >= 0 );
  3994. ASSERT( nCaptionHeightSrc >= 0 );
  3995. ASSERT(
  3996. ( nCaptionHeightDst == 0 && nCaptionHeightSrc == 0 )
  3997. || ( nCaptionHeightSrc >  0 && nCaptionHeightSrc >  0 )
  3998. );
  3999. if( IsEmpty() || hDC == NULL )
  4000. return false;
  4001. CSize _size = GetSize();
  4002. CRect rcSrcDraw( 0, 0, _size.cx, _size.cy );
  4003. return
  4004. DrawNcFrame(
  4005. hDC,
  4006. rcDstDraw,
  4007. rcSrcDraw,
  4008. rcPadding,
  4009. nCaptionHeightDst,
  4010. nCaptionHeightSrc,
  4011. bDrawMiddlePart,
  4012. bSmootherAsPossible,
  4013. dwRop
  4014. );
  4015. }
  4016. bool CExtBitmap::DrawSkinParts(
  4017. HDC hDC,
  4018. const RECT & rcDstDraw,
  4019. const RECT & rcSrcDraw,
  4020. const RECT & rcPadding,
  4021. e_DrawMethod_t eDM,
  4022. bool bDrawMiddlePart, // = true
  4023. bool bSmootherAsPossible, // = false
  4024. DWORD dwRop // = SRCCOPY
  4025. ) const
  4026. {
  4027. if( eDM == __EDM_HOLLOW )
  4028. return true;
  4029. ASSERT( hDC != NULL );
  4030. ASSERT( rcPadding.left >= 0 );
  4031. ASSERT( rcPadding.right >= 0 );
  4032. ASSERT( rcPadding.top >= 0 );
  4033. ASSERT( rcPadding.bottom >= 0 );
  4034. if( IsEmpty() || hDC == NULL )
  4035. return false;
  4036. int nOldStretchBltMode = ::GetStretchBltMode( hDC );
  4037. ::SetStretchBltMode(
  4038. hDC,
  4039. ( bSmootherAsPossible && g_PaintManager.m_bIsWinNT )
  4040. ? HALFTONE
  4041. : COLORONCOLOR
  4042. );
  4043. if( eDM == __EDM_CENTER )
  4044. {
  4045. //CSize _size = GetSize();
  4046. CSize _size( rcSrcDraw.right - rcSrcDraw.left, rcSrcDraw.bottom - rcSrcDraw.top );
  4047. CRect rcDst(
  4048. CPoint(
  4049. rcDstDraw.left + ( rcDstDraw.right - rcDstDraw.left - _size.cx ) / 2, 
  4050. rcDstDraw.top + ( rcDstDraw.bottom - rcDstDraw.top - _size.cy ) / 2
  4051. ),
  4052. _size
  4053. );
  4054. if( ::RectVisible( hDC, &rcDst ) )
  4055. Draw(
  4056. hDC,
  4057. rcDst,
  4058. rcSrcDraw,
  4059. dwRop
  4060. );
  4061. return true;
  4062. } // if( eDM == __EDM_CENTER )
  4063. // left - top
  4064. if( rcPadding.left > 0 && rcPadding.top > 0 )
  4065. {
  4066. CRect rcDst(
  4067. rcDstDraw.left,
  4068. rcDstDraw.top,
  4069. rcDstDraw.left + rcPadding.left,
  4070. rcDstDraw.top + rcPadding.top
  4071. );
  4072. if( ::RectVisible( hDC, &rcDst ) )
  4073. {
  4074. CRect rcSrc(
  4075. rcSrcDraw.left,
  4076. rcSrcDraw.top,
  4077. rcSrcDraw.left + rcPadding.left,
  4078. rcSrcDraw.top + rcPadding.top
  4079. );
  4080. Draw(
  4081. hDC,
  4082. rcDst,
  4083. rcSrc,
  4084. dwRop
  4085. );
  4086. } // if( ::RectVisible( hDC, &rcDst ) )
  4087. } // if( rcPadding.left > 0 && rcPadding.top > 0 )
  4088. // middle - top
  4089. if( rcPadding.top > 0 )
  4090. {
  4091. CRect rcDst(
  4092. rcDstDraw.left + rcPadding.left,
  4093. rcDstDraw.top,
  4094. rcDstDraw.right - rcPadding.right,
  4095. rcDstDraw.top + rcPadding.top
  4096. );
  4097. if( ::RectVisible( hDC, &rcDst ) )
  4098. {
  4099. CRect rcSrc(
  4100. rcSrcDraw.left + rcPadding.left,
  4101. rcSrcDraw.top,
  4102. rcSrcDraw.right - rcPadding.right,
  4103. rcSrcDraw.top + rcPadding.top
  4104. );
  4105. if( eDM == __EDM_TILE_H || eDM == __EDM_TILE )
  4106. {
  4107. INT nSrcWidth = rcSrc.right - rcSrc.left;
  4108. INT nSrcHeight = rcSrc.bottom - rcSrc.top;
  4109. INT nDstWidth = rcDst.right - rcDst.left;
  4110. INT nDstHeight = rcDst.bottom - rcDst.top;
  4111. if( nSrcWidth != 0 && nSrcHeight != 0 && nDstWidth != 0 && nDstHeight != 0 )
  4112. {
  4113. INT nLastStepPx = nDstWidth % nSrcWidth;
  4114. INT nLastStep = ( nLastStepPx != 0 ) ? 1 : 0;
  4115. INT nStepCount = nDstWidth / nSrcWidth + nLastStep;
  4116. INT nStepIndex;
  4117. CRect rcDstStep(
  4118. rcDst.left,
  4119. rcDst.top,
  4120. rcDst.left + nSrcWidth,
  4121. rcDst.top + nSrcHeight
  4122. );
  4123. CRect rcSrcA = rcSrc;
  4124. for( nStepIndex = 0; nStepIndex < nStepCount; nStepIndex ++ )
  4125. {
  4126. if( nLastStep != 0
  4127. && nStepIndex == ( nStepCount - 1 )
  4128. && rcDstStep.right > rcDst.right
  4129. )
  4130. {
  4131. INT nDiff = rcDstStep.right - rcDst.right;
  4132. rcDstStep.right -= nDiff;
  4133. rcSrcA.right -= nDiff;
  4134. }
  4135. Draw(
  4136. hDC,
  4137. rcDstStep,
  4138. rcSrcA,
  4139. dwRop
  4140. );
  4141. rcDstStep.OffsetRect( nSrcWidth, 0 );
  4142. } // for( nStepIndex = 0; nStepIndex < nStepCount; nStepIndex ++ )
  4143. } // if( nSrcWidth != 0 && nSrcHeight != 0 && nDstWidth != 0 && nDstHeight != 0 )
  4144. } // if( eDM == __EDM_TILE_H || eDM == __EDM_TILE )
  4145. else
  4146. Draw(
  4147. hDC,
  4148. rcDst,
  4149. rcSrc,
  4150. dwRop
  4151. );
  4152. } // if( ::RectVisible( hDC, &rcDst ) )
  4153. } // if( rcPadding.top > 0 )
  4154. // right - top
  4155. if( rcPadding.right > 0 && rcPadding.top > 0 )
  4156. {
  4157. CRect rcDst(
  4158. rcDstDraw.right - rcPadding.right,
  4159. rcDstDraw.top,
  4160. rcDstDraw.right,
  4161. rcDstDraw.top + rcPadding.top
  4162. );
  4163. if( ::RectVisible( hDC, &rcDst ) )
  4164. {
  4165. CRect rcSrc(
  4166. rcSrcDraw.right - rcPadding.right,
  4167. rcSrcDraw.top,
  4168. rcSrcDraw.right,
  4169. rcSrcDraw.top + rcPadding.top
  4170. );
  4171. Draw(
  4172. hDC,
  4173. rcDst,
  4174. rcSrc,
  4175. dwRop
  4176. );
  4177. } // if( ::RectVisible( hDC, &rcDst ) )
  4178. } // if( rcPadding.right > 0 && rcPadding.top > 0 )
  4179. // left - middle
  4180. if( rcPadding.left > 0 )
  4181. {
  4182. CRect rcDst(
  4183. rcDstDraw.left,
  4184. rcDstDraw.top + rcPadding.top,
  4185. rcDstDraw.left + rcPadding.left,
  4186. rcDstDraw.bottom - rcPadding.bottom
  4187. );
  4188. if( ::RectVisible( hDC, &rcDst ) )
  4189. {
  4190. CRect rcSrc(
  4191. rcSrcDraw.left,
  4192. rcSrcDraw.top + rcPadding.top,
  4193. rcSrcDraw.left + rcPadding.left,
  4194. rcSrcDraw.bottom - rcPadding.bottom
  4195. );
  4196. if( eDM == __EDM_TILE_V || eDM == __EDM_TILE )
  4197. {
  4198. INT nSrcWidth = rcSrc.right - rcSrc.left;
  4199. INT nSrcHeight = rcSrc.bottom - rcSrc.top;
  4200. INT nDstWidth = rcDst.right - rcDst.left;
  4201. INT nDstHeight = rcDst.bottom - rcDst.top;
  4202. INT nLastStepPx = nDstHeight % nSrcHeight;
  4203. if( nSrcWidth != 0 && nSrcHeight != 0 && nDstWidth != 0 && nDstHeight != 0 )
  4204. {
  4205. INT nLastStep = ( nLastStepPx != 0 ) ? 1 : 0;
  4206. INT nStepCount = nDstHeight / nSrcHeight + nLastStep;
  4207. INT nStepIndex;
  4208. CRect rcDstStep(
  4209. rcDst.left,
  4210. rcDst.top,
  4211. rcDst.left + nSrcWidth,
  4212. rcDst.top + nSrcHeight
  4213. );
  4214. CRect rcSrcA = rcSrc;
  4215. for( nStepIndex = 0; nStepIndex < nStepCount; nStepIndex ++ )
  4216. {
  4217. if( nLastStep != 0
  4218. && nStepIndex == ( nStepCount - 1 )
  4219. && rcDstStep.bottom > rcDst.bottom
  4220. )
  4221. {
  4222. INT nDiff = rcDstStep.bottom - rcDst.bottom;
  4223. rcDstStep.bottom -= nDiff;
  4224. rcSrcA.bottom -= nDiff;
  4225. }
  4226. Draw(
  4227. hDC,
  4228. rcDstStep,
  4229. rcSrcA,
  4230. dwRop
  4231. );
  4232. rcDstStep.OffsetRect( 0, nSrcHeight );
  4233. } // for( nStepIndex = 0; nStepIndex < nStepCount; nStepIndex ++ )
  4234. } // if( nSrcWidth != 0 && nSrcHeight != 0 && nDstWidth != 0 && nDstHeight != 0 )
  4235. } // if( eDM == __EDM_TILE_V || eDM == __EDM_TILE )
  4236. else
  4237. Draw(
  4238. hDC,
  4239. rcDst,
  4240. rcSrc,
  4241. dwRop
  4242. );
  4243. } // if( ::RectVisible( hDC, &rcDst ) )
  4244. } // if( rcPadding.left > 0 )
  4245. // right - middle
  4246. if( rcPadding.right > 0 )
  4247. {
  4248. CRect rcDst(
  4249. rcDstDraw.right - rcPadding.right,
  4250. rcDstDraw.top + rcPadding.top,
  4251. rcDstDraw.right,
  4252. rcDstDraw.bottom - rcPadding.bottom
  4253. );
  4254. if( ::RectVisible( hDC, &rcDst ) )
  4255. {
  4256. CRect rcSrc(
  4257. rcSrcDraw.right - rcPadding.right,
  4258. rcSrcDraw.top + rcPadding.top,
  4259. rcSrcDraw.right,
  4260. rcSrcDraw.bottom - rcPadding.bottom
  4261. );
  4262. if( eDM == __EDM_TILE_V || eDM == __EDM_TILE )
  4263. {
  4264. INT nSrcWidth = rcSrc.right - rcSrc.left;
  4265. INT nSrcHeight = rcSrc.bottom - rcSrc.top;
  4266. INT nDstWidth = rcDst.right - rcDst.left;
  4267. INT nDstHeight = rcDst.bottom - rcDst.top;
  4268. if( nSrcWidth != 0 && nSrcHeight != 0 && nDstWidth != 0 && nDstHeight != 0 )
  4269. {
  4270. INT nLastStepPx = nDstHeight % nSrcHeight;
  4271. INT nLastStep = ( nLastStepPx != 0 ) ? 1 : 0;
  4272. INT nStepCount = nDstHeight / nSrcHeight + nLastStep;
  4273. INT nStepIndex;
  4274. CRect rcDstStep(
  4275. rcDst.left,
  4276. rcDst.top,
  4277. rcDst.left + nSrcWidth,
  4278. rcDst.top + nSrcHeight
  4279. );
  4280. CRect rcSrcA = rcSrc;
  4281. for( nStepIndex = 0; nStepIndex < nStepCount; nStepIndex ++ )
  4282. {
  4283. if( nLastStep != 0
  4284. && nStepIndex == ( nStepCount - 1 )
  4285. && rcDstStep.bottom > rcDst.bottom
  4286. )
  4287. {
  4288. INT nDiff = rcDstStep.bottom - rcDst.bottom;
  4289. rcDstStep.bottom -= nDiff;
  4290. rcSrcA.bottom -= nDiff;
  4291. }
  4292. Draw(
  4293. hDC,
  4294. rcDstStep,
  4295. rcSrcA,
  4296. dwRop
  4297. );
  4298. rcDstStep.OffsetRect( 0, nSrcHeight );
  4299. } // for( nStepIndex = 0; nStepIndex < nStepCount; nStepIndex ++ )
  4300. } // if( nSrcWidth != 0 && nSrcHeight != 0 && nDstWidth != 0 && nDstHeight != 0 )
  4301. } // if( eDM == __EDM_TILE_V || eDM == __EDM_TILE )
  4302. else
  4303. Draw(
  4304. hDC,
  4305. rcDst,
  4306. rcSrc,
  4307. dwRop
  4308. );
  4309. } // if( ::RectVisible( hDC, &rcDst ) )
  4310. } // if( rcPadding.right > 0 )
  4311. // left - bottom
  4312. if( rcPadding.left > 0 && rcPadding.bottom > 0 )
  4313. {
  4314. CRect rcDst(
  4315. rcDstDraw.left,
  4316. rcDstDraw.bottom - rcPadding.bottom,
  4317. rcDstDraw.left + rcPadding.left,
  4318. rcDstDraw.bottom
  4319. );
  4320. if( ::RectVisible( hDC, &rcDst ) )
  4321. {
  4322. CRect rcSrc(
  4323. rcSrcDraw.left,
  4324. rcSrcDraw.bottom - rcPadding.bottom,
  4325. rcSrcDraw.left + rcPadding.left,
  4326. rcSrcDraw.bottom
  4327. );
  4328. Draw(
  4329. hDC,
  4330. rcDst,
  4331. rcSrc,
  4332. dwRop
  4333. );
  4334. } // if( ::RectVisible( hDC, &rcDst ) )
  4335. } // if( rcPadding.left > 0 && rcPadding.bottom > 0 )
  4336. // middle - bottom
  4337. if( rcPadding.bottom > 0 )
  4338. {
  4339. CRect rcDst(
  4340. rcDstDraw.left + rcPadding.left,
  4341. rcDstDraw.bottom - rcPadding.bottom,
  4342. rcDstDraw.right - rcPadding.right,
  4343. rcDstDraw.bottom
  4344. );
  4345. if( ::RectVisible( hDC, &rcDst ) )
  4346. {
  4347. CRect rcSrc(
  4348. rcSrcDraw.left + rcPadding.left,
  4349. rcSrcDraw.bottom - rcPadding.bottom,
  4350. rcSrcDraw.right - rcPadding.right,
  4351. rcSrcDraw.bottom
  4352. );
  4353. if( eDM == __EDM_TILE_H || eDM == __EDM_TILE )
  4354. {
  4355. INT nSrcWidth = rcSrc.right - rcSrc.left;
  4356. INT nSrcHeight = rcSrc.bottom - rcSrc.top;
  4357. INT nDstWidth = rcDst.right - rcDst.left;
  4358. INT nDstHeight = rcDst.bottom - rcDst.top;
  4359. if( nSrcWidth != 0 && nSrcHeight != 0 && nDstWidth != 0 && nDstHeight != 0 )
  4360. {
  4361. INT nLastStepPx = nDstWidth % nSrcWidth;
  4362. INT nLastStep = ( nLastStepPx != 0 ) ? 1 : 0;
  4363. INT nStepCount = nDstWidth / nSrcWidth + nLastStep;
  4364. INT nStepIndex;
  4365. CRect rcDstStep(
  4366. rcDst.left,
  4367. rcDst.top,
  4368. rcDst.left + nSrcWidth,
  4369. rcDst.top + nSrcHeight
  4370. );
  4371. CRect rcSrcA = rcSrc;
  4372. for( nStepIndex = 0; nStepIndex < nStepCount; nStepIndex ++ )
  4373. {
  4374. if( nLastStep != 0
  4375. && nStepIndex == ( nStepCount - 1 )
  4376. && rcDstStep.right > rcDst.right
  4377. )
  4378. {
  4379. INT nDiff = rcDstStep.right - rcDst.right;
  4380. rcDstStep.right -= nDiff;
  4381. rcSrcA.right -= nDiff;
  4382. }
  4383. Draw(
  4384. hDC,
  4385. rcDstStep,
  4386. rcSrcA,
  4387. dwRop
  4388. );
  4389. rcDstStep.OffsetRect( nSrcWidth, 0 );
  4390. } // for( nStepIndex = 0; nStepIndex < nStepCount; nStepIndex ++ )
  4391. } // if( nSrcWidth != 0 && nSrcHeight != 0 && nDstWidth != 0 && nDstHeight != 0 )
  4392. } // if( eDM == __EDM_TILE_H || eDM == __EDM_TILE )
  4393. else
  4394. Draw(
  4395. hDC,
  4396. rcDst,
  4397. rcSrc,
  4398. dwRop
  4399. );
  4400. } // if( ::RectVisible( hDC, &rcDst ) )
  4401. } // if( rcPadding.bottom > 0 )
  4402. // right - bottom
  4403. if( rcPadding.right > 0 && rcPadding.bottom > 0 )
  4404. {
  4405. CRect rcDst(
  4406. rcDstDraw.right - rcPadding.right,
  4407. rcDstDraw.bottom - rcPadding.bottom,
  4408. rcDstDraw.right,
  4409. rcDstDraw.bottom
  4410. );
  4411. if( ::RectVisible( hDC, &rcDst ) )
  4412. {
  4413. CRect rcSrc(
  4414. rcSrcDraw.right - rcPadding.right,
  4415. rcSrcDraw.bottom - rcPadding.bottom,
  4416. rcSrcDraw.right,
  4417. rcSrcDraw.bottom
  4418. );
  4419. Draw(
  4420. hDC,
  4421. rcDst,
  4422. rcSrc,
  4423. dwRop
  4424. );
  4425. } // if( ::RectVisible( hDC, &rcDst ) )
  4426. } // if( rcPadding.right > 0 && rcPadding.bottom > 0 )
  4427. // central part
  4428. if( bDrawMiddlePart )
  4429. {
  4430. CRect rcDst(
  4431. rcDstDraw.left + rcPadding.left,
  4432. rcDstDraw.top + rcPadding.top,
  4433. rcDstDraw.right - rcPadding.right,
  4434. rcDstDraw.bottom - rcPadding.bottom
  4435. );
  4436. if( ::RectVisible( hDC, &rcDst ) )
  4437. {
  4438. CRect rcSrc(
  4439. rcSrcDraw.left + rcPadding.left,
  4440. rcSrcDraw.top + rcPadding.top,
  4441. rcSrcDraw.right - rcPadding.right,
  4442. rcSrcDraw.bottom - rcPadding.bottom
  4443. );
  4444. if( eDM == __EDM_TILE_H )
  4445. {
  4446. INT nSrcWidth = rcSrc.right - rcSrc.left;
  4447. INT nSrcHeight = rcSrc.bottom - rcSrc.top;
  4448. INT nDstWidth = rcDst.right - rcDst.left;
  4449. INT nDstHeight = rcDst.bottom - rcDst.top;
  4450. INT nLastStepPx = nDstWidth % nSrcWidth;
  4451. if( nSrcWidth != 0 && nSrcHeight != 0 && nDstWidth != 0 && nDstHeight != 0 )
  4452. {
  4453. INT nLastStep = ( nLastStepPx != 0 ) ? 1 : 0;
  4454. INT nStepCount = nDstWidth / nSrcWidth + nLastStep;
  4455. INT nStepIndex;
  4456. CRect rcDstStep(
  4457. rcDst.left,
  4458. rcDst.top,
  4459. rcDst.left + nSrcWidth,
  4460. rcDst.top + nDstHeight
  4461. );
  4462. CRect rcSrcA = rcSrc;
  4463. for( nStepIndex = 0; nStepIndex < nStepCount; nStepIndex ++ )
  4464. {
  4465. if( nLastStep != 0
  4466. && nStepIndex == ( nStepCount - 1 )
  4467. && rcDstStep.right > rcDst.right
  4468. )
  4469. {
  4470. INT nDiff = rcDstStep.right - rcDst.right;
  4471. rcDstStep.right -= nDiff;
  4472. rcSrcA.right -= nDiff;
  4473. }
  4474. Draw(
  4475. hDC,
  4476. rcDstStep,
  4477. rcSrcA,
  4478. dwRop
  4479. );
  4480. rcDstStep.OffsetRect( nSrcWidth, 0 );
  4481. } // for( nStepIndex = 0; nStepIndex < nStepCount; nStepIndex ++ )
  4482. } // if( nSrcWidth != 0 && nSrcHeight != 0 && nDstWidth != 0 && nDstHeight != 0 )
  4483. } // if( eDM == __EDM_TILE_H )
  4484. else if( eDM == __EDM_TILE_V )
  4485. {
  4486. INT nSrcWidth = rcSrc.right - rcSrc.left;
  4487. INT nSrcHeight = rcSrc.bottom - rcSrc.top;
  4488. INT nDstWidth = rcDst.right - rcDst.left;
  4489. INT nDstHeight = rcDst.bottom - rcDst.top;
  4490. if( nSrcWidth != 0 && nSrcHeight != 0 && nDstWidth != 0 && nDstHeight != 0 )
  4491. {
  4492. INT nLastStepPx = nDstHeight % nSrcHeight;
  4493. INT nLastStep = ( nLastStepPx != 0 ) ? 1 : 0;
  4494. INT nStepCount = nDstHeight / nSrcHeight + nLastStep;
  4495. INT nStepIndex;
  4496. CRect rcDstStep(
  4497. rcDst.left,
  4498. rcDst.top,
  4499. rcDst.left + nDstWidth,
  4500. rcDst.top + nSrcHeight
  4501. );
  4502. CRect rcSrcA = rcSrc;
  4503. for( nStepIndex = 0; nStepIndex < nStepCount; nStepIndex ++ )
  4504. {
  4505. if( nLastStep != 0
  4506. && nStepIndex == ( nStepCount - 1 )
  4507. && rcDstStep.bottom > rcDst.bottom
  4508. )
  4509. {
  4510. INT nDiff = rcDstStep.bottom - rcDst.bottom;
  4511. rcDstStep.bottom -= nDiff;
  4512. rcSrcA.bottom -= nDiff;
  4513. }
  4514. Draw(
  4515. hDC,
  4516. rcDstStep,
  4517. rcSrcA,
  4518. dwRop
  4519. );
  4520. rcDstStep.OffsetRect( 0, nSrcHeight );
  4521. } // for( nStepIndex = 0; nStepIndex < nStepCount; nStepIndex ++ )
  4522. } // if( nSrcWidth != 0 && nSrcHeight != 0 && nDstWidth != 0 && nDstHeight != 0 )
  4523. } // else if( eDM == __EDM_TILE_V )
  4524. else if( eDM == __EDM_TILE )
  4525. {
  4526. INT nSrcWidth = rcSrc.right - rcSrc.left;
  4527. INT nSrcHeight = rcSrc.bottom - rcSrc.top;
  4528. INT nDstWidth = rcDst.right - rcDst.left;
  4529. INT nDstHeight = rcDst.bottom - rcDst.top;
  4530. if( nSrcWidth != 0 && nSrcHeight != 0 && nDstWidth != 0 && nDstHeight != 0 )
  4531. {
  4532. INT nLastStepPxH = nDstWidth % nSrcWidth;
  4533. INT nLastStepPxV = nDstHeight % nSrcHeight;
  4534. INT nLastStepH = ( nLastStepPxH != 0 ) ? 1 : 0;
  4535. INT nLastStepV = ( nLastStepPxV != 0 ) ? 1 : 0;
  4536. INT nStepCountH = nDstWidth / nSrcWidth + nLastStepH;
  4537. INT nStepCountV = nDstHeight / nSrcHeight + nLastStepV;
  4538. INT nStepIndexH, nStepIndexV;
  4539. CRect rcDstStep(
  4540. rcDst.left,
  4541. rcDst.top,
  4542. rcDst.left + nSrcWidth,
  4543. rcDst.top + nSrcHeight
  4544. );
  4545. for( nStepIndexV = 0; nStepIndexV < nStepCountV; nStepIndexV ++ )
  4546. {
  4547. CRect rcDstStepA = rcDstStep;
  4548. CRect rcSrcA = rcSrc;
  4549. if( nLastStepV != 0
  4550. && nStepIndexV == ( nStepCountV - 1 )
  4551. && rcDstStepA.bottom > rcDst.bottom
  4552. )
  4553. {
  4554. INT nDiff = rcDstStepA.bottom - rcDst.bottom;
  4555. rcDstStepA.bottom -= nDiff;
  4556. rcSrcA.bottom -= nDiff;
  4557. }
  4558. for( nStepIndexH = 0; nStepIndexH < nStepCountH; nStepIndexH ++ )
  4559. {
  4560. if( nLastStepH != 0
  4561. && nStepIndexH == ( nStepCountH - 1 )
  4562. && rcDstStepA.right > rcDst.right
  4563. )
  4564. {
  4565. INT nDiff = rcDstStepA.right - rcDst.right;
  4566. rcDstStepA.right -= nDiff;
  4567. rcSrcA.right -= nDiff;
  4568. }
  4569. Draw(
  4570. hDC,
  4571. rcDstStepA,
  4572. rcSrcA,
  4573. dwRop
  4574. );
  4575. rcDstStepA.OffsetRect( nSrcWidth, 0 );
  4576. } // for( nStepIndexH = 0; nStepIndexH < nStepCountH; nStepIndexH ++ )
  4577. rcDstStep.OffsetRect( 0, nSrcHeight );
  4578. } // for( nStepIndexV = 0; nStepIndexV < nStepCountV; nStepIndexV ++ )
  4579. } // if( nSrcWidth != 0 && nSrcHeight != 0 && nDstWidth != 0 && nDstHeight != 0 )
  4580. } // else if( eDM == __EDM_TILE )
  4581. else
  4582. Draw(
  4583. hDC,
  4584. rcDst,
  4585. rcSrc,
  4586. dwRop
  4587. );
  4588. } // if( ::RectVisible( hDC, &rcDst ) )
  4589. } // if( bDrawMiddlePart )
  4590. ::SetStretchBltMode(
  4591. hDC,
  4592. nOldStretchBltMode
  4593. );
  4594. return true;
  4595. }
  4596. bool CExtBitmap::DrawSkinParts(
  4597. HDC hDC,
  4598. const RECT & rcDstDraw,
  4599. const RECT & rcPadding,
  4600. e_DrawMethod_t eDM,
  4601. bool bDrawMiddlePart, // = true
  4602. bool bSmootherAsPossible, // = false
  4603. DWORD dwRop // = SRCCOPY
  4604. ) const
  4605. {
  4606. ASSERT( hDC != NULL );
  4607. ASSERT( rcPadding.left >= 0 );
  4608. ASSERT( rcPadding.right >= 0 );
  4609. ASSERT( rcPadding.top >= 0 );
  4610. ASSERT( rcPadding.bottom >= 0 );
  4611. if( IsEmpty() || hDC == NULL )
  4612. return false;
  4613. CSize _size = GetSize();
  4614. RECT rcSrcDraw = { 0, 0, _size.cx, _size.cy };
  4615. return
  4616. DrawSkinParts(
  4617. hDC,
  4618. rcDstDraw,
  4619. rcSrcDraw,
  4620. rcPadding,
  4621. eDM,
  4622. bDrawMiddlePart,
  4623. bSmootherAsPossible,
  4624. dwRop
  4625. );
  4626. }
  4627. int CExtBitmap::AlphaBlend(
  4628. HDC hDC,
  4629. const RECT & rcDst,
  4630. const RECT & rcSrc,
  4631. BYTE nSCA // = 0xFF 
  4632. ) const
  4633. {
  4634. ASSERT( hDC != NULL );
  4635. if( IsEmpty() || hDC == NULL )
  4636. return GDI_ERROR;
  4637. return
  4638. AlphaBlend(
  4639. hDC,
  4640. rcDst.left,
  4641. rcDst.top,
  4642. rcDst.right - rcDst.left,
  4643. rcDst.bottom - rcDst.top,
  4644. rcSrc.left,
  4645. rcSrc.top,
  4646. rcSrc.right - rcSrc.left,
  4647. rcSrc.bottom - rcSrc.top,
  4648. nSCA
  4649. );
  4650. }
  4651. int CExtBitmap::AlphaBlend(
  4652. HDC hDC,
  4653. const RECT & rcDst,
  4654. BYTE nSCA // = 0xFF
  4655. ) const
  4656. {
  4657. ASSERT( hDC != NULL );
  4658. if( IsEmpty() || hDC == NULL )
  4659. return GDI_ERROR;
  4660. CSize _size = GetSize();
  4661. CRect rcSrc( 0, 0, _size.cx, _size.cy );
  4662. return
  4663. AlphaBlend(
  4664. hDC,
  4665. rcDst,
  4666. rcSrc,
  4667. nSCA
  4668. );
  4669. }
  4670. int CExtBitmap::AlphaBlend(
  4671. HDC hDC,
  4672. int nDstX,
  4673. int nDstY,
  4674. int nDstWidth,
  4675. int nDstHeight,
  4676. int nSrcX,
  4677. int nSrcY,
  4678. int nSrcWidth,
  4679. int nSrcHeight,
  4680. BYTE nSCA // = 0xFF
  4681. ) const
  4682. {
  4683. ASSERT( hDC != NULL );
  4684. if( IsEmpty()
  4685. || hDC == NULL
  4686. )
  4687. return GDI_ERROR;
  4688. ULONG nBPP = GetBPP(), nMaskAlpha = stat_MaskAlpha( m_pImageBuffer );
  4689. if( nBPP != 32
  4690. || nMaskAlpha == 0
  4691. )
  4692. {
  4693. CSize _size = GetSize();
  4694. return
  4695. Draw(
  4696. hDC,
  4697. nDstX,
  4698. nDstY,
  4699. nDstWidth,
  4700. nDstHeight,
  4701. nSrcX,
  4702. nSrcY,
  4703. nSrcWidth,
  4704. nSrcHeight
  4705. );
  4706. }
  4707. // if( g_PaintManager.m_bIsWin2000orLater )
  4708. // {
  4709. // int nDeviceShadeBlendCaps = ::GetDeviceCaps( hDC, __EXT_MFC_SHADEBLENDCAPS );
  4710. // const int nRequiredCaps = __EXT_MFC_SB_PIXEL_ALPHA|__EXT_MFC_SB_CONST_ALPHA;
  4711. // if( (nDeviceShadeBlendCaps&nRequiredCaps) != nRequiredCaps )
  4712. // {
  4713. // CRect rcSurfaceCache( nDstX, nDstY, nDstX + nDstWidth, nDstY + nDstHeight );
  4714. // CDC * pDC = CDC::FromHandle( hDC );
  4715. // CExtMemoryDC dc(
  4716. // pDC,
  4717. // &rcSurfaceCache,
  4718. // CExtMemoryDC::MDCOPT_DEFAULT
  4719. // | CExtMemoryDC::MDCOPT_DESKTOP_COMPATIBILITY
  4720. // | CExtMemoryDC::MDCOPT_FORCE_DIB
  4721. // );
  4722. // if( dc.GetSafeHdc() == NULL )
  4723. // return GDI_ERROR;
  4724. // ASSERT( ! dc.IsPrinting() );
  4725. //#if (defined _DEBUG)
  4726. // int nDebugCheckShadeBlendCaps = ::GetDeviceCaps( dc.m_hDC, __EXT_MFC_SHADEBLENDCAPS );
  4727. // ASSERT( (nDebugCheckShadeBlendCaps&nRequiredCaps) == nRequiredCaps );
  4728. //#endif // (defined _DEBUG)
  4729. // return
  4730. // AlphaBlend(
  4731. // dc.GetSafeHdc(),
  4732. // nDstX,
  4733. // nDstY,
  4734. // nDstWidth,
  4735. // nDstHeight,
  4736. // nSrcX,
  4737. // nSrcY,
  4738. // nSrcWidth,
  4739. // nSrcHeight,
  4740. // nSCA
  4741. // );
  4742. // } // if( (nDeviceShadeBlendCaps&nRequiredCaps) != nRequiredCaps )
  4743. // } // if( g_PaintManager.m_bIsWin2000orLater )
  4744. bool bAutoPreMultiplyEnabled = IsAutoPreMultiplyRGBChannels();
  4745. bool bPreMultiplied = PreMultipliedRGBChannelsGet();
  4746. if( g_PaintManager.m_pfnMsImgAlphaBlend != NULL )
  4747. {
  4748. bool bRTL = false;
  4749. if( (RunTimeFlagsGet()&__EXT_BMP_FLAG_NO_RTL_DETECTION) == 0 )
  4750. {
  4751. if( CDC::FromHandle(hDC)->GetLayout() == LAYOUT_RTL )
  4752.   bRTL = true;
  4753. }
  4754. if( ! bRTL )
  4755. {
  4756. const CExtBitmap * pBmpRenderSurfaceCreator = this;
  4757. CExtBitmap _bmpCrt;
  4758. if( ! bPreMultiplied )
  4759. {
  4760. if( bAutoPreMultiplyEnabled )
  4761. {
  4762. ( const_cast < CExtBitmap * > ( this ) ) -> PreMultipliedRGBChannelsSet( true );
  4763. ( const_cast < CExtBitmap * > ( this ) ) -> PreMultiplyRGBChannels();
  4764. } // if( bAutoPreMultiplyEnabled )
  4765. else
  4766. {
  4767. _bmpCrt = (*this);
  4768. if( _bmpCrt.IsEmpty()
  4769. || (! _bmpCrt.Make32() )
  4770. )
  4771. return GDI_ERROR;
  4772. _bmpCrt.PreMultiplyRGBChannels();
  4773. pBmpRenderSurfaceCreator = &_bmpCrt;
  4774. } // else from if( bAutoPreMultiplyEnabled )
  4775. } // if( ! bPreMultiplied )
  4776. int nRetVal = GDI_ERROR;
  4777. HDC hSrcDC = ::CreateCompatibleDC( hDC );
  4778. if( hSrcDC != NULL )
  4779. {
  4780. HBITMAP hBmp = pBmpRenderSurfaceCreator->CreateBitmap( hDC, false );
  4781. if( hBmp != NULL )
  4782. {
  4783. HGDIOBJ hOld = ::SelectObject( hSrcDC, hBmp );
  4784. CExtPaintManager::CExtPaintManagerAutoPtr::__EXT_MFC_BLENDFUNCTION
  4785. _bf = { AC_SRC_OVER, 0, nSCA, __EXT_MFC_AC_SRC_ALPHA };
  4786. if( g_PaintManager.m_pfnMsImgAlphaBlend(
  4787. hDC,
  4788. nDstX,
  4789. nDstY,
  4790. nDstWidth,
  4791. nDstHeight,
  4792. hSrcDC,
  4793. nSrcX,
  4794. nSrcY,
  4795. nSrcWidth,
  4796. nSrcHeight,
  4797. _bf
  4798. )
  4799. )
  4800. nRetVal = 0;
  4801. ::SelectObject( hSrcDC, hOld );
  4802. ::DeleteObject( hBmp );
  4803. } // if( hBmp != NULL )
  4804. ::DeleteDC( hSrcDC );
  4805. } // if( hSrcDC != NULL )
  4806. if( nRetVal == 0 )
  4807. return nRetVal;
  4808. _bmpCrt;
  4809. } // if( ! bRTL )
  4810. } // else if( g_PaintManager.m_pfnMsImgAlphaBlend != NULL )
  4811. HDC hSrcDC = ::CreateCompatibleDC( NULL );
  4812. if( hSrcDC == NULL )
  4813. {
  4814. //ASSERT( FALSE );
  4815. return GDI_ERROR;
  4816. }
  4817. HDC hDstDC = ::CreateCompatibleDC( NULL );
  4818. if( hDstDC == NULL )
  4819. {