Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

579 lines
17 KiB

  1. #include "stdafx.h"
  2. #include "global.h"
  3. #include "pbrush.h"
  4. #include "pbrusdoc.h"
  5. #include "pbrusfrm.h"
  6. #include "pbrusvw.h"
  7. #include "minifwnd.h"
  8. #include "bmobject.h"
  9. #include "imgsuprt.h"
  10. #include "imgwnd.h"
  11. #include "imgbrush.h"
  12. #include "imgwell.h"
  13. #include "imgtools.h"
  14. #include "t_fhsel.h"
  15. #include "toolbox.h"
  16. #include "mmsystem.h"
  17. #ifdef _DEBUG
  18. #undef THIS_FILE
  19. static CHAR BASED_CODE THIS_FILE[] = __FILE__;
  20. #endif
  21. #include "memtrace.h"
  22. CImgBrush theImgBrush;
  23. CImgBrush::CImgBrush() : m_bCuttingFromImage(FALSE), m_bOpaque(TRUE)
  24. {
  25. }
  26. CImgBrush::~CImgBrush()
  27. {
  28. // cleanup old region if exists
  29. if (m_cRgnPolyFreeHandSel.GetSafeHandle() != NULL)
  30. m_cRgnPolyFreeHandSel.DeleteObject();
  31. if (m_cRgnPolyFreeHandSelBorder.GetSafeHandle() != NULL)
  32. m_cRgnPolyFreeHandSelBorder.DeleteObject();
  33. if (m_hbmOld)
  34. m_dc.SelectObject( CBitmap::FromHandle( m_hbmOld ) );
  35. if (m_hbmMaskOld)
  36. m_dc.SelectObject( CBitmap::FromHandle( m_hbmMaskOld ) );
  37. m_dc.DeleteDC();
  38. m_bitmap.DeleteObject();
  39. m_maskDC.DeleteDC();
  40. m_maskBitmap.DeleteObject();
  41. }
  42. BOOL CImgBrush::CopyTo(CImgBrush& destBrush)
  43. {
  44. if (destBrush.m_hbmOld)
  45. destBrush.m_dc.SelectObject( CBitmap::FromHandle( destBrush.m_hbmOld ) );
  46. if (destBrush.m_hbmMaskOld)
  47. destBrush.m_maskDC.SelectObject( CBitmap::FromHandle( destBrush.m_hbmMaskOld ) );
  48. destBrush.m_hbmOld = NULL;
  49. destBrush.m_hbmMaskOld = NULL;
  50. destBrush.m_dc.DeleteDC();
  51. destBrush.m_bitmap.DeleteObject();
  52. destBrush.m_maskDC.DeleteDC();
  53. destBrush.m_maskBitmap.DeleteObject();
  54. if (m_dc.m_hDC != NULL)
  55. {
  56. if (! destBrush.m_dc.CreateCompatibleDC( NULL )
  57. || ! destBrush.m_bitmap.CreateCompatibleBitmap(&m_dc, m_size.cx, m_size.cy))
  58. {
  59. theApp.SetGdiEmergency(FALSE);
  60. return FALSE;
  61. }
  62. destBrush.m_hbmOld = (HBITMAP)((destBrush.m_dc.SelectObject( &destBrush.m_bitmap ))->GetSafeHandle());
  63. CPalette* ppalOldSrc = SetBrushPalette( &m_dc, TRUE ); // Background ??
  64. CPalette* ppalOldDest = SetBrushPalette( &destBrush.m_dc, TRUE ); // Background ??
  65. destBrush.m_dc.BitBlt( 0, 0, m_size.cx, m_size.cy, &m_dc, 0, 0, SRCCOPY );
  66. if (ppalOldSrc)
  67. m_dc.SelectPalette( ppalOldSrc, TRUE ); // Background ??
  68. if (ppalOldDest)
  69. destBrush.m_dc.SelectPalette( ppalOldDest, TRUE ); // Background ??
  70. }
  71. if (m_maskDC.m_hDC != NULL)
  72. {
  73. if (! destBrush.m_maskDC.CreateCompatibleDC(NULL)
  74. || ! destBrush.m_maskBitmap.CreateCompatibleBitmap(&m_maskDC, m_size.cx,
  75. m_size.cy))
  76. {
  77. theApp.SetGdiEmergency(FALSE);
  78. return FALSE;
  79. }
  80. destBrush.m_hbmMaskOld = (HBITMAP)((destBrush.m_maskDC.SelectObject(
  81. &destBrush.m_maskBitmap))->GetSafeHandle());
  82. destBrush.m_maskDC.BitBlt(0, 0, m_size.cx, m_size.cy, &m_maskDC, 0, 0, SRCCOPY);
  83. }
  84. destBrush.m_size = m_size;
  85. destBrush.m_bFirstDrag = m_bFirstDrag;
  86. destBrush.m_bLastDragWasASmear = m_bLastDragWasASmear;
  87. destBrush.m_bLastDragWasFirst = m_bLastDragWasFirst;
  88. destBrush.m_bMakingSelection = m_bMakingSelection;
  89. destBrush.m_bMoveSel = m_bMoveSel;
  90. destBrush.m_bSmearSel = m_bSmearSel;
  91. destBrush.m_bOpaque = m_bOpaque;
  92. destBrush.m_rcDraggedFrom = m_rcDraggedFrom;
  93. destBrush.m_pImg = m_pImg;
  94. destBrush.m_rcSelection = m_rcSelection;
  95. destBrush.m_handle = m_handle;
  96. return TRUE;
  97. }
  98. void CImgBrush::CenterHandle()
  99. {
  100. m_handle.cx = m_size.cx / 2;
  101. m_handle.cy = m_size.cy / 2;
  102. }
  103. void CImgBrush::TopLeftHandle()
  104. {
  105. m_handle.cx = 0;
  106. m_handle.cy = 0;
  107. }
  108. CPalette* CImgBrush::SetBrushPalette( CDC* pdc, BOOL bForce )
  109. {
  110. CPalette* ppal = NULL;
  111. CPalette* ppalOld = NULL;
  112. if (theApp.m_pPalette
  113. && theApp.m_pPalette->m_hObject)
  114. ppal = theApp.m_pPalette;
  115. if (ppal != NULL)
  116. {
  117. ppalOld = pdc->SelectPalette( ppal, bForce );
  118. pdc->RealizePalette();
  119. }
  120. return ppalOld;
  121. }
  122. HPALETTE CImgBrush::SetBrushPalette( HDC hdc, BOOL bForce )
  123. {
  124. CPalette* ppal = NULL;
  125. HPALETTE hpalOld = NULL;
  126. if (theApp.m_pPalette
  127. && theApp.m_pPalette->m_hObject)
  128. ppal = theApp.m_pPalette;
  129. if (ppal != NULL)
  130. {
  131. hpalOld = ::SelectPalette( hdc, (HPALETTE)ppal->m_hObject, bForce );
  132. RealizePalette( hdc );
  133. }
  134. return hpalOld;
  135. }
  136. BOOL CImgBrush::SetSize( CSize newSize, BOOL bStretchToFit )
  137. {
  138. BOOL bFlipX;
  139. BOOL bFlipY;
  140. if (newSize.cx == m_size.cx
  141. && newSize.cy == m_size.cy)
  142. return TRUE;
  143. if (bFlipX = (newSize.cx < 0))
  144. newSize.cx = -newSize.cx;
  145. if (bFlipY = (newSize.cy < 0))
  146. newSize.cy = -newSize.cy;
  147. if (newSize.cx == 0)
  148. newSize.cx = 1;
  149. if (newSize.cy == 0)
  150. newSize.cy = 1;
  151. if (CImgTool::GetCurrentID() != IDMX_TEXTTOOL)
  152. {
  153. CDC newDC;
  154. CBitmap newBitmap;
  155. CDC newMaskDC;
  156. CBitmap newMaskBitmap;
  157. //REARCHITECT Potential for DC && Bitmap leaks here on partial failure!!
  158. if (! newDC.CreateCompatibleDC ( &m_dc )
  159. || ! newBitmap.CreateCompatibleBitmap( &m_dc, newSize.cx, newSize.cy )
  160. || ! newMaskDC.CreateCompatibleDC ( &m_dc )
  161. || ! newMaskBitmap.CreateBitmap(newSize.cx, newSize.cy, 1, 1, NULL ))
  162. return FALSE;
  163. CBitmap* pbmOld = newDC.SelectObject( &newBitmap );
  164. CPalette* ppalOldSrc = SetBrushPalette( &m_dc, FALSE );
  165. CPalette* ppalOldDest = SetBrushPalette( &newDC, FALSE );
  166. newDC.SetStretchBltMode(COLORONCOLOR);
  167. if (bStretchToFit)
  168. {
  169. StretchCopy( newDC.m_hDC, bFlipX ? newSize.cx : 0,
  170. bFlipY ? newSize.cy : 0,
  171. bFlipX ? -newSize.cx : newSize.cx,
  172. bFlipY ? -newSize.cy : newSize.cy,
  173. m_dc.m_hDC, 0, 0, m_size.cx, m_size.cy );
  174. }
  175. else
  176. {
  177. StretchCopy( newDC.m_hDC, bFlipX ? newSize.cx : 0,
  178. bFlipY ? newSize.cy : 0,
  179. m_size.cx, m_size.cy,
  180. m_dc.m_hDC, 0, 0, m_size.cx, m_size.cy );
  181. }
  182. COLORREF crOldBk = newDC.SetBkColor( crRight );
  183. CBitmap* pbmOldMask = newMaskDC.SelectObject( &newMaskBitmap );
  184. if (CImgTool::GetCurrentID() == IDMB_PICKRGNTOOL)
  185. {
  186. CFreehandSelectTool* pTool = (CFreehandSelectTool*)CImgTool::GetCurrent();
  187. if (pTool->ExpandPolyRegion( newSize.cx, newSize.cy ))
  188. {
  189. newMaskDC.PatBlt( 0, 0, newSize.cx, newSize.cy, BLACKNESS );
  190. if (m_cRgnPolyFreeHandSel.GetSafeHandle())
  191. newMaskDC.FillRgn( &m_cRgnPolyFreeHandSel,
  192. CBrush::FromHandle( (HBRUSH)::GetStockObject( WHITE_BRUSH ) ) );
  193. }
  194. }
  195. else
  196. {
  197. newMaskDC.PatBlt( 0, 0, newSize.cx, newSize.cy, WHITENESS );
  198. }
  199. newMaskDC.BitBlt( 0, 0, newSize.cx, newSize.cy, &newDC, 0, 0, DSna );
  200. newDC.SetBkColor( crOldBk );
  201. if (ppalOldSrc)
  202. m_dc.SelectPalette( ppalOldSrc, FALSE );
  203. if (ppalOldDest)
  204. newDC.SelectPalette( ppalOldDest, FALSE );
  205. if (m_hbmOld)
  206. m_dc.SelectObject( CBitmap::FromHandle( m_hbmOld ) );
  207. if (m_hbmMaskOld)
  208. m_maskDC.SelectObject( CBitmap::FromHandle( m_hbmMaskOld ) );
  209. m_dc.DeleteDC();
  210. m_maskDC.DeleteDC();
  211. m_bitmap.DeleteObject();
  212. m_maskBitmap.DeleteObject();
  213. m_dc.Attach( newDC.Detach() );
  214. m_bitmap.Attach( newBitmap.Detach() );
  215. m_maskDC.Attach( newMaskDC.Detach() );
  216. m_maskBitmap.Attach( newMaskBitmap.Detach() );
  217. m_hbmOld = (HBITMAP)(pbmOld->GetSafeHandle());
  218. m_hbmMaskOld = (HBITMAP)(pbmOldMask->GetSafeHandle());
  219. }
  220. m_size.cx = newSize.cx;
  221. m_size.cy = newSize.cy;
  222. return TRUE;
  223. }
  224. #if defined(DEBUGSHOWBITMAPS)
  225. void DebugShowBitmap(HDC hdcSrc, int x, int y, int wid, int hgt)
  226. {
  227. HDC hdcDst = GetDC(NULL);
  228. BitBlt(hdcDst, 0, 0, wid, hgt, hdcSrc, x, y, SRCCOPY);
  229. ReleaseDC(NULL, hdcDst);
  230. }
  231. #endif
  232. BOOL QuickColorToMono(CDC* pdcMono, int xMono, int yMono, int cx, int cy,
  233. CDC *pdcColor, int xColor, int yColor, DWORD dwROP, COLORREF crTrans)
  234. {
  235. RGBQUAD rgb[256];
  236. int nColors = GetDIBColorTable(pdcColor->m_hDC, 0, 256, &rgb[0]);
  237. if (nColors == 0)
  238. {
  239. return(FALSE);
  240. }
  241. RGBQUAD rgbWhite;
  242. rgbWhite.rgbRed = 255;
  243. rgbWhite.rgbGreen = 255;
  244. rgbWhite.rgbBlue = 255;
  245. rgbWhite.rgbReserved = 0;
  246. RGBQUAD rgbBlack;
  247. rgbBlack.rgbRed = 0;
  248. rgbBlack.rgbGreen = 0;
  249. rgbBlack.rgbBlue = 0;
  250. rgbBlack.rgbReserved = 0;
  251. RGBQUAD rgbTemp[256];
  252. switch ((BYTE)((crTrans)>>24))
  253. {
  254. case 0:
  255. case 2:
  256. {
  257. RGBQUAD rgbTrans;
  258. rgbTrans.rgbRed = GetRValue(crTrans);
  259. rgbTrans.rgbGreen = GetGValue(crTrans);
  260. rgbTrans.rgbBlue = GetBValue(crTrans);
  261. rgbTrans.rgbReserved = 0;
  262. for (int nColor=nColors-1; nColor>=0; --nColor)
  263. {
  264. if (memcmp(&rgb[nColor], &rgbTrans, sizeof(rgbTrans)) == 0)
  265. {
  266. rgbTemp[nColor] = rgbWhite;
  267. }
  268. else
  269. {
  270. rgbTemp[nColor] = rgbBlack;
  271. }
  272. }
  273. break;
  274. }
  275. // We can put support for different COLORREF formats here
  276. default:
  277. return(FALSE);
  278. }
  279. SetDIBColorTable(pdcColor->m_hDC, 0, nColors, &rgbTemp[0]);
  280. pdcMono->BitBlt(xMono, yMono, cx, cy, pdcColor, xColor, yColor, dwROP);
  281. SetDIBColorTable(pdcColor->m_hDC, 0, nColors, &rgb[0]);
  282. return(TRUE);
  283. }
  284. #define COLORTOMONOBUG
  285. #ifdef COLORTOMONOBUG
  286. void CImgBrush::ColorToMonoBitBlt(CDC* pdcMono, int xMono, int yMono, int cx, int cy,
  287. CDC *pdcColor, int xColor, int yColor, DWORD dwROP, COLORREF transparentColor)
  288. {
  289. if (QuickColorToMono(pdcMono, xMono, yMono, cx, cy,
  290. pdcColor, xColor, yColor, dwROP, transparentColor))
  291. {
  292. return;
  293. }
  294. CDC dcColor;
  295. CTempBitmap bmColor;
  296. CBitmap* pbmOldColor = NULL;
  297. // Use a moderate-sized intermediate bitmap
  298. int cyStep = 0xffff / cx;
  299. cyStep = max(1, min(cy, cyStep));
  300. HDC hdcScreen = GetDC(NULL);
  301. BOOL bError = (!dcColor.CreateCompatibleDC(NULL)
  302. || !bmColor.CreateCompatibleBitmap(CDC::FromHandle(hdcScreen), cx, cyStep)
  303. || (pbmOldColor = dcColor.SelectObject(&bmColor))==NULL);
  304. ReleaseDC(NULL, hdcScreen);
  305. if (bError)
  306. {
  307. theApp.SetGdiEmergency(FALSE);
  308. return;
  309. }
  310. CPalette* ppalOld = SetBrushPalette( pdcColor, FALSE );
  311. CPalette* ppalOldColor = SetBrushPalette( &dcColor, FALSE );
  312. dcColor.SetBkColor( transparentColor );
  313. int yStep;
  314. for (yStep=0; yStep<cy; yStep+=cyStep)
  315. {
  316. if (cyStep > cy - yStep)
  317. {
  318. cyStep = cy - yStep;
  319. }
  320. dcColor.BitBlt(0, 0, cx, cyStep, pdcColor, xColor, yColor+yStep, SRCCOPY);
  321. pdcMono->BitBlt(xMono, yMono+yStep, cx, cyStep, &dcColor, 0, 0, dwROP);
  322. DebugShowBitmap(pdcMono->m_hDC, xMono, yMono, cx, cy);
  323. }
  324. if (ppalOld)
  325. {
  326. pdcColor->SelectPalette( ppalOld, FALSE );
  327. }
  328. dcColor.SelectObject(pbmOldColor);
  329. if (ppalOldColor)
  330. {
  331. dcColor.SelectPalette( ppalOldColor, FALSE );
  332. }
  333. }
  334. #endif // COLORTOMONOBUG
  335. void CImgBrush::RecalcMask( COLORREF transparentColor )
  336. {
  337. if (! m_dc.GetSafeHdc() || ! m_maskDC.m_hDC)
  338. return;
  339. #ifndef COLORTOMONOBUG
  340. CPalette* ppalOld = SetBrushPalette( &m_dc, FALSE );
  341. COLORREF oldBkColor = m_dc.SetBkColor( transparentColor );
  342. #endif // COLORTOMONOBUG
  343. if (CImgTool::GetCurrentID() == IDMB_PICKRGNTOOL)
  344. {
  345. m_maskDC.PatBlt( 0, 0, m_size.cx, m_size.cy, BLACKNESS );
  346. if (m_cRgnPolyFreeHandSel.GetSafeHandle())
  347. m_maskDC.FillRgn( &m_cRgnPolyFreeHandSel,
  348. CBrush::FromHandle( (HBRUSH)::GetStockObject( WHITE_BRUSH ) ) );
  349. if (! m_bOpaque) // can't test true, since bitfield
  350. #ifdef COLORTOMONOBUG
  351. ColorToMonoBitBlt(&m_maskDC, 0, 0, m_size.cx, m_size.cy,
  352. &m_dc, 0, 0, DSna, transparentColor);
  353. #else // COLORTOMONOBUG
  354. m_maskDC.BitBlt( 0, 0, m_size.cx, m_size.cy, &m_dc, 0, 0, DSna );
  355. #endif // COLORTOMONOBUG
  356. }
  357. else
  358. {
  359. #ifdef COLORTOMONOBUG
  360. ColorToMonoBitBlt(&m_maskDC, 0, 0, m_size.cx, m_size.cy,
  361. &m_dc, 0, 0, NOTSRCCOPY, transparentColor);
  362. #else // COLORTOMONOBUG
  363. m_maskDC.BitBlt( 0, 0, m_size.cx, m_size.cy, &m_dc, 0, 0, NOTSRCCOPY );
  364. #endif // COLORTOMONOBUG
  365. }
  366. #ifndef COLORTOMONOBUG
  367. m_dc.SetBkColor( oldBkColor );
  368. if (ppalOld)
  369. m_dc.SelectPalette( ppalOld, FALSE );
  370. #endif // COLORTOMONOBUG
  371. }
  372. void GetMonoBltColors(HDC hDC, HBITMAP hBM, COLORREF& crNewBk, COLORREF& crNewText)
  373. {
  374. crNewBk = RGB(0xff, 0xff, 0xff);
  375. crNewText = RGB(0x00, 0x00, 0x00);
  376. RGBQUAD rq;
  377. if (GetDIBColorTable(hDC, 0, 1, &rq) == 1)
  378. {
  379. if (hBM == NULL)
  380. {
  381. hBM = (HBITMAP) GetCurrentObject(hDC, OBJ_BITMAP);
  382. }
  383. WORD nMaxIndex = 0xff;
  384. BITMAP bm;
  385. if (GetObject(hBM, sizeof(bm), &bm))
  386. {
  387. nMaxIndex = (1 << bm.bmBitsPixel) - 1;
  388. }
  389. crNewBk = DIBINDEX(nMaxIndex);
  390. crNewText = DIBINDEX(0x00);
  391. }
  392. }
  393. // This handles drawing the brush with Draw Opaque turned off.
  394. //
  395. void CImgBrush::BltMatte(IMG* pimg, CPoint topLeft)
  396. {
  397. COLORREF crNewBk, crNewText;
  398. GetMonoBltColors(pimg->hDC, pimg->hBitmap, crNewBk, crNewText);
  399. COLORREF crOldBk = SetBkColor(pimg->hDC, crNewBk);
  400. COLORREF crOldText = SetTextColor(pimg->hDC, crNewText);
  401. CPalette* ppalOld = SetBrushPalette( &m_dc, FALSE ); // Background ??
  402. // Copying from a bitmap...
  403. DebugShowBitmap(pimg->hDC, topLeft.x, topLeft.y, m_size.cx, m_size.cy);
  404. BitBlt(pimg->hDC, topLeft.x, topLeft.y, m_size.cx, m_size.cy,
  405. m_dc.m_hDC, 0, 0, DSx);
  406. DebugShowBitmap(pimg->hDC, topLeft.x, topLeft.y, m_size.cx, m_size.cy);
  407. BitBlt(pimg->hDC, topLeft.x, topLeft.y, m_size.cx, m_size.cy,
  408. m_maskDC.m_hDC, 0, 0, DSna);
  409. DebugShowBitmap(pimg->hDC, topLeft.x, topLeft.y, m_size.cx, m_size.cy);
  410. BitBlt(pimg->hDC, topLeft.x, topLeft.y, m_size.cx, m_size.cy,
  411. m_dc.m_hDC, 0, 0, DSx);
  412. DebugShowBitmap(pimg->hDC, topLeft.x, topLeft.y, m_size.cx, m_size.cy);
  413. if (ppalOld)
  414. m_dc.SelectPalette( ppalOld, FALSE ); // Background ??
  415. SetBkColor(pimg->hDC, crOldBk);
  416. SetTextColor(pimg->hDC, crOldText);
  417. }
  418. // This handles drawing the brush with Draw Opaque turned on.
  419. //
  420. void CImgBrush::BltReplace(IMG* pimg, CPoint topLeft)
  421. {
  422. int iToolID = CImgTool::GetCurrentID();
  423. if (iToolID == IDMB_PICKRGNTOOL)
  424. {
  425. BltMatte( pimg, topLeft );
  426. }
  427. else
  428. {
  429. CPalette* ppalOld = SetBrushPalette( &m_dc, FALSE ); // Background ??
  430. BitBlt(pimg->hDC, topLeft.x, topLeft.y, m_size.cx, m_size.cy,
  431. m_dc.m_hDC, 0, 0, SRCCOPY);
  432. if (ppalOld)
  433. m_dc.SelectPalette( ppalOld, FALSE ); // Background ??
  434. }
  435. }
  436. // This handles erasing with the brush (draws mask in solid color).
  437. //
  438. void CImgBrush::BltColor(IMG* pimg, CPoint topLeft, COLORREF color)
  439. {
  440. COLORREF crOldBk = SetBkColor(pimg->hDC, color);
  441. COLORREF crOldText = SetTextColor(pimg->hDC, RGB(0, 0, 0));
  442. BitBlt(pimg->hDC, topLeft.x, topLeft.y, m_size.cx, m_size.cy,
  443. m_maskDC.m_hDC, 0, 0, DSx);
  444. SetBkColor(pimg->hDC, RGB(255, 255, 255));
  445. BitBlt(pimg->hDC, topLeft.x, topLeft.y, m_size.cx, m_size.cy,
  446. m_maskDC.m_hDC, 0, 0, DSna);
  447. SetBkColor(pimg->hDC, color);
  448. BitBlt(pimg->hDC, topLeft.x, topLeft.y, m_size.cx, m_size.cy,
  449. m_maskDC.m_hDC, 0, 0, DSx);
  450. SetTextColor(pimg->hDC, crOldText);
  451. SetBkColor(pimg->hDC, crOldBk);
  452. }