Leaked source code of windows server 2003
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.

2993 lines
87 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 "imgwell.h"
  12. #include "imgtools.h"
  13. #include "t_fhsel.h"
  14. #include "toolbox.h"
  15. #include "imgbrush.h"
  16. #include "imgdlgs.h"
  17. #ifdef _DEBUG
  18. #undef THIS_FILE
  19. static CHAR BASED_CODE THIS_FILE[] = __FILE__;
  20. #endif // _DEBUG
  21. #include "memtrace.h"
  22. BOOL g_bUseTrans = FALSE;
  23. BOOL g_bCustomBrush = FALSE;
  24. BOOL fDraggingBrush = FALSE;
  25. IMG* pImgCur = NULL;
  26. #define NUM_DEF_COLORS 28
  27. extern COLORREF colorColorsDef[NUM_DEF_COLORS];
  28. COLORREF crLeft = 0;
  29. COLORREF crRight = RGB( 0xff, 0xff, 0xff );
  30. COLORREF crTrans = TRANS_COLOR_NONE; // transparent color
  31. int theLeft;
  32. int theRight;
  33. int theTrans;
  34. int wCombineMode;
  35. HDC hRubberDC;
  36. HBITMAP hRubberBM;
  37. int cxRubberWidth;
  38. int cyRubberHeight;
  39. IMG* pRubberImg;
  40. BOOL EnsureUndoSize(IMG* pImg);
  41. static int cxUndoWidth, cyUndoHeight;
  42. static BYTE cUndoPlanes, cUndoBitCount;
  43. HBITMAP g_hUndoImgBitmap = NULL;
  44. HPALETTE g_hUndoPalette = NULL;
  45. COLORREF std2Colors [] =
  46. {
  47. RGB(000, 000, 000), // 0 - black
  48. RGB(255, 255, 255) // 1 - white
  49. };
  50. COLORREF std16Colors [] =
  51. {
  52. RGB( 0, 0, 0), // Black
  53. RGB(128, 0, 0), // Dark Red
  54. RGB( 0, 128, 0), // Dark Green
  55. RGB(128, 128, 0), // Pea Green
  56. RGB( 0, 0, 128), // Dark Blue
  57. RGB(128, 0, 128), // Lavender
  58. RGB( 0, 128, 128), // Slate
  59. RGB(192, 192, 192), // Light Gray
  60. RGB(128, 128, 128), // Dark Gray
  61. RGB(255, 0, 0), // Bright Red
  62. RGB( 0, 255, 0), // Bright Green
  63. RGB(255, 255, 0), // Yellow
  64. RGB( 0, 0, 255), // Bright Blue
  65. RGB(255, 0, 255), // Magenta
  66. RGB( 0, 255, 255), // Cyan
  67. RGB(255, 255, 255) // 1 - white
  68. };
  69. /***************************************************************************/
  70. IMG* CreateImg(int cxWidth, int cyHeight, int cPlanes, int cBitCount, int cXPelsPerMeter, int cYPelsPerMeter, BOOL bPalette )
  71. {
  72. IMG* pimg = NULL;
  73. CTempBitmap bmNew;
  74. HBITMAP hbmOld = NULL;
  75. CClientDC dcScreen(NULL);
  76. if (! cPlanes )
  77. {
  78. cPlanes = dcScreen.GetDeviceCaps( PLANES );
  79. }
  80. if (! cBitCount)
  81. {
  82. cBitCount = dcScreen.GetDeviceCaps( BITSPIXEL );
  83. }
  84. CDC cDC;
  85. cDC.CreateCompatibleDC( &dcScreen );
  86. if (!cDC.m_hDC)
  87. {
  88. return NULL;
  89. }
  90. if (cPlanes * cBitCount > 1)
  91. {
  92. cDC.SetStretchBltMode(HALFTONE);
  93. }
  94. // Set these to 0 to not create a bitmap
  95. if (cxWidth && cyHeight)
  96. {
  97. BOOL bMono = (cPlanes == 1 && cBitCount == 1);
  98. COLORREF* pcrColors = NULL;
  99. int nColors = 0;
  100. cBitCount *= cPlanes;
  101. if (cBitCount <= 1)
  102. {
  103. cBitCount = 1;
  104. pcrColors = std2Colors;
  105. nColors = 2;
  106. }
  107. else if (cBitCount <= 4)
  108. {
  109. cBitCount = 4;
  110. pcrColors = std16Colors;
  111. nColors = 16;
  112. }
  113. else if (cBitCount <= 8)
  114. {
  115. cBitCount = 8;
  116. pcrColors = colorColorsDef;
  117. nColors = NUM_DEF_COLORS;
  118. }
  119. else
  120. {
  121. // I don't want to deal with 15 or 16 bit images
  122. cBitCount = 24;
  123. }
  124. HBITMAP hbmNew = NULL;
  125. if (cBitCount == 4)
  126. {
  127. // Just create a DDB if in 16 colors
  128. hbmNew = CreateCompatibleBitmap( dcScreen.m_hDC, cxWidth, cyHeight);
  129. }
  130. else
  131. {
  132. struct BMHDR
  133. {
  134. BITMAPINFOHEADER bmInfo;
  135. RGBQUAD rgb[256];
  136. } DIBHdr =
  137. {
  138. sizeof(BITMAPINFOHEADER),
  139. cxWidth,
  140. cyHeight,
  141. 1,
  142. (WORD)cBitCount,
  143. BI_RGB,
  144. 0,
  145. 0,
  146. nColors,
  147. nColors,
  148. } ;
  149. if (cBitCount <= 8)
  150. {
  151. RGBQUAD* prgb;
  152. COLORREF* pcr;
  153. int n;
  154. pcr = pcrColors;
  155. prgb = DIBHdr.rgb;
  156. for (n=nColors; n>0; --n, ++pcr, ++prgb)
  157. {
  158. prgb->rgbRed = GetRValue(*pcr);
  159. prgb->rgbGreen = GetGValue(*pcr);
  160. prgb->rgbBlue = GetBValue(*pcr);
  161. prgb->rgbReserved = 0;
  162. }
  163. }
  164. LPVOID lpNewBits;
  165. hbmNew = CreateDIBSection(cDC.m_hDC, (LPBITMAPINFO)&DIBHdr,
  166. DIB_RGB_COLORS, &lpNewBits, NULL, 0);
  167. }
  168. if (!hbmNew)
  169. {
  170. return NULL;
  171. }
  172. bmNew.Attach(hbmNew);
  173. }
  174. TRY
  175. {
  176. pimg = new IMG;
  177. }
  178. CATCH (CMemoryException, e)
  179. {
  180. TRACE( TEXT("CreateImg: Can't alloc an IMG\n") );
  181. return NULL;
  182. }
  183. END_CATCH
  184. pimg->cxWidth = cxWidth;
  185. pimg->cyHeight = cyHeight;
  186. pimg->cPlanes = cPlanes;
  187. pimg->cBitCount = cBitCount;
  188. pimg->cXPelsPerMeter = cXPelsPerMeter;
  189. pimg->cYPelsPerMeter = cYPelsPerMeter;
  190. pimg->hDC = (HDC)cDC.Detach();
  191. pimg->hBitmap = (HBITMAP)bmNew.Detach();
  192. pimg->hBitmapOld = NULL;
  193. pimg->m_pFirstImgWnd = NULL;
  194. pimg->bDirty = FALSE;
  195. pimg->m_hPalOld = NULL;
  196. pimg->m_pPalette = NULL;
  197. pimg->m_bTileGrid = g_bDefaultTileGrid;
  198. pimg->m_cxTile = g_defaultTileGridSize.cx;
  199. pimg->m_cyTile = g_defaultTileGridSize.cy;
  200. BYTE cRed = GetRValue( crRight );
  201. BYTE cGreen = GetGValue( crRight );
  202. BYTE cBlue = GetBValue( crRight );
  203. if (theApp.m_bPaletted)
  204. {
  205. crRight = PALETTERGB( cRed, cGreen, cBlue );
  206. }
  207. else
  208. {
  209. crRight = RGB( cRed, cGreen, cBlue );
  210. }
  211. if (pimg->hBitmap)
  212. {
  213. pimg->hBitmapOld = (HBITMAP)SelectObject(pimg->hDC, pimg->hBitmap);
  214. ClearImg( pimg );
  215. }
  216. return(pimg);
  217. }
  218. /***************************************************************************/
  219. BOOL ClearImg(IMG* pimg)
  220. {
  221. #if 1
  222. HBRUSH hNewBrush;
  223. HBRUSH hOldBrush = NULL;
  224. HPALETTE hpalOld = NULL;
  225. pimg->m_nLastChanged = -1;
  226. if ((hNewBrush = ::CreateSolidBrush( crRight )) == NULL)
  227. return FALSE;
  228. if (pimg->m_pPalette)
  229. {
  230. hpalOld = SelectPalette( pimg->hDC, (HPALETTE)pimg->m_pPalette->m_hObject, FALSE );
  231. RealizePalette( pimg->hDC );
  232. }
  233. hOldBrush = (HBRUSH)SelectObject( pimg->hDC, hNewBrush );
  234. PatBlt( pimg->hDC, 0, 0, pimg->cxWidth, pimg->cyHeight, PATCOPY );
  235. if (hOldBrush)
  236. SelectObject(pimg->hDC, hOldBrush);
  237. DeleteObject( hNewBrush );
  238. if (hpalOld)
  239. SelectPalette( pimg->hDC, hpalOld, FALSE );
  240. return TRUE;
  241. #else
  242. BOOL bResult = FALSE;
  243. HBRUSH hNewBrush = ::CreateSolidBrush( crRight );
  244. if ( hNewBrush )
  245. {
  246. HBRUSH hOldBrush = (HBRUSH)SelectObject( pimg->hDC, hNewBrush );
  247. if ( hOldBrush )
  248. {
  249. HPALETTE hpalOld = SelectPalette( pimg->hDC,
  250. (HPALETTE)pimg->m_pPalette->m_hObject,
  251. FALSE );
  252. if ( hpalOld )
  253. {
  254. RealizePalette( pimg->hDC );
  255. PatBlt( pimg->hDC, 0, 0, pimg->cxWidth, pimg->cyHeight, PATCOPY );
  256. pimg->m_nLastChanged = -1;
  257. bResult = TRUE;
  258. SelectPalette( pimg->hDC, hpalOld, FALSE );
  259. }
  260. SelectObject(pimg->hDC, hOldBrush);
  261. }
  262. DeleteObject( hNewBrush );
  263. }
  264. return bResult;
  265. #endif
  266. }
  267. /***************************************************************************/
  268. void FreeImg(IMG* pimg)
  269. {
  270. if (! pimg)
  271. return;
  272. if (pimg == theImgBrush.m_pImg)
  273. theImgBrush.m_pImg = NULL;
  274. if (pimg->hDC)
  275. {
  276. if (pimg->hBitmapOld)
  277. SelectObject( pimg->hDC, pimg->hBitmapOld );
  278. if (pimg->m_hPalOld)
  279. SelectPalette( pimg->hDC, pimg->m_hPalOld, FALSE ); // Background ??
  280. DeleteDC(pimg->hDC);
  281. }
  282. if (pimg->hBitmap)
  283. DeleteObject(pimg->hBitmap);
  284. if (theApp.m_pPalette == pimg->m_pPalette)
  285. theApp.m_pPalette = NULL;
  286. if (pimg->m_pPalette)
  287. delete pimg->m_pPalette;
  288. if (pimg->m_pBitmapObj->m_pImg == pimg)
  289. pimg->m_pBitmapObj->m_pImg = NULL;
  290. if (pImgCur == pimg)
  291. pImgCur = NULL;
  292. if (pRubberImg == pimg)
  293. pRubberImg = NULL;
  294. delete pimg;
  295. }
  296. /***************************************************************************/
  297. void SelectImg(IMG* pimg)
  298. {
  299. if (pimg == pImgCur)
  300. return;
  301. if (theImgBrush.m_pImg)
  302. HideBrush();
  303. pImgCur = pimg;
  304. SetupRubber(pimg);
  305. }
  306. /***************************************************************************/
  307. void DirtyImg( IMG* pimg )
  308. {
  309. CPBDoc* pDoc = (CPBDoc*)((CFrameWnd*)AfxGetMainWnd())->GetActiveDocument();
  310. if (pDoc)
  311. {
  312. pDoc->SetModifiedFlag( TRUE );
  313. if (theApp.m_bEmbedded)
  314. pDoc->NotifyChanged();
  315. }
  316. pimg->bDirty = TRUE;
  317. pimg->m_pBitmapObj->SetDirty( TRUE );
  318. }
  319. /***************************************************************************/
  320. void CleanupImages()
  321. {
  322. FreeImg( pImgCur );
  323. CleanupImgUndo();
  324. CleanupImgRubber();
  325. }
  326. /***************************************************************************/
  327. void InvalImgRect(IMG* pimg, CRect* prc)
  328. {
  329. CImgWnd* pImgWnd;
  330. CImgWnd* pNextImgWnd;
  331. CRect rc;
  332. rc.SetRect(0, 0, pimg->cxWidth, pimg->cyHeight);
  333. if (prc)
  334. rc &= *prc;
  335. for (pImgWnd = pimg->m_pFirstImgWnd; pImgWnd;
  336. pImgWnd = pNextImgWnd)
  337. {
  338. CRect rcWnd;
  339. pNextImgWnd = pImgWnd->m_pNextImgWnd;
  340. if (prc)
  341. {
  342. rcWnd = rc;
  343. pImgWnd->ImageToClient(rcWnd);
  344. if (pImgWnd->IsGridVisible())
  345. {
  346. rcWnd.right += 1;
  347. rcWnd.bottom += 1;
  348. }
  349. }
  350. pImgWnd->InvalidateRect(prc == NULL ? NULL : &rcWnd, FALSE);
  351. }
  352. }
  353. /***************************************************************************/
  354. void CommitImgRect(IMG* pimg, CRect* prc)
  355. {
  356. ASSERT(hRubberDC);
  357. if (hRubberDC == NULL)
  358. return;
  359. CRect rc;
  360. if (prc == NULL)
  361. {
  362. SetRect( &rc, 0, 0, pimg->cxWidth, pimg->cyHeight );
  363. prc = &rc;
  364. }
  365. HPALETTE hpalOld = NULL;
  366. if (theApp.m_pPalette
  367. && theApp.m_pPalette->m_hObject)
  368. {
  369. hpalOld = SelectPalette( hRubberDC, (HPALETTE)theApp.m_pPalette->m_hObject, FALSE ); // Background ??
  370. RealizePalette( hRubberDC );
  371. }
  372. BitBlt(hRubberDC, prc->left, prc->top,
  373. prc->Width(), prc->Height(),
  374. pimg->hDC, prc->left, prc->top, SRCCOPY);
  375. if (hpalOld)
  376. SelectPalette( hRubberDC, hpalOld, FALSE ); // Background ??
  377. }
  378. void SelInScreenFirst(CPalette* pPal)
  379. {
  380. // HACK: Select into screen DC first for GDI bug
  381. CWindowDC hdcScreen(NULL);
  382. hdcScreen.SelectPalette(pPal, TRUE);
  383. hdcScreen.RealizePalette();
  384. }
  385. BOOL CreateSafePalette(CPalette* pPal, LPLOGPALETTE lpLogPal)
  386. {
  387. if (!pPal->CreatePalette(lpLogPal))
  388. {
  389. return(FALSE);
  390. }
  391. SelInScreenFirst(pPal);
  392. return(TRUE);
  393. }
  394. /***************************************************************************/
  395. BOOL ReplaceImgPalette( IMG* pImg, LPLOGPALETTE lpLogPal )
  396. {
  397. if (pImg->m_hPalOld)
  398. {
  399. ::SelectPalette( pImg->hDC, pImg->m_hPalOld, FALSE );
  400. pImg->m_hPalOld = NULL;
  401. }
  402. if (pImg->m_pPalette)
  403. delete pImg->m_pPalette;
  404. pImg->m_pPalette = new CPalette;
  405. if (pImg->m_pPalette
  406. && CreateSafePalette(pImg->m_pPalette, lpLogPal ))
  407. {
  408. pImg->m_hPalOld = ::SelectPalette( pImg->hDC,
  409. (HPALETTE)pImg->m_pPalette->GetSafeHandle(), FALSE );
  410. ::RealizePalette( pImg->hDC );
  411. InvalImgRect( pImg, NULL );
  412. }
  413. else
  414. {
  415. if (pImg->m_pPalette)
  416. delete pImg->m_pPalette;
  417. pImg->m_pPalette = NULL;
  418. }
  419. return (pImg->m_pPalette != NULL);
  420. }
  421. /***************************************************************************/
  422. void CleanupImgRubber()
  423. {
  424. if (hRubberDC)
  425. {
  426. DeleteDC(hRubberDC);
  427. hRubberDC = NULL;
  428. }
  429. if (hRubberBM)
  430. {
  431. DeleteObject(hRubberBM);
  432. hRubberBM = NULL;
  433. }
  434. pRubberImg = NULL;
  435. cxRubberWidth = 0;
  436. cyRubberHeight = 0;
  437. }
  438. /***************************************************************************/
  439. void IdleImage()
  440. {
  441. if (g_pMouseImgWnd)
  442. {
  443. CRect rcImage(0, 0, g_pMouseImgWnd->GetImg()->cxWidth,
  444. g_pMouseImgWnd->GetImg()->cyHeight);
  445. g_pMouseImgWnd->ImageToClient( rcImage );
  446. CRect rcClient;
  447. g_pMouseImgWnd->GetClientRect( &rcClient );
  448. rcClient &= rcImage;
  449. CPoint pt;
  450. GetCursorPos( &pt );
  451. CPoint ptClient = pt;
  452. g_pMouseImgWnd->ScreenToClient( &ptClient );
  453. if (CWnd::WindowFromPoint( pt ) != g_pMouseImgWnd
  454. || ! rcClient.PtInRect( ptClient ))
  455. {
  456. extern MTI mti;
  457. CImgTool::GetCurrent()->OnLeave( g_pMouseImgWnd, &mti );
  458. g_pMouseImgWnd = NULL;
  459. if (! CImgTool::IsDragging() &&
  460. ::IsWindow(((CPBFrame*)theApp.m_pMainWnd)->m_statBar.m_hWnd) )
  461. ((CPBFrame*)theApp.m_pMainWnd)->m_statBar.ClearPosition();
  462. }
  463. }
  464. if (fDraggingBrush)
  465. {
  466. CPoint pt;
  467. CRect rcClient;
  468. CPoint ptClient;
  469. CImgWnd* pImgWnd;
  470. GetCursorPos(&pt);
  471. pImgWnd = g_pDragBrushWnd;
  472. if (pImgWnd == NULL)
  473. return;
  474. CRect rcImage(0, 0, pImgWnd->GetImg()->cxWidth,
  475. pImgWnd->GetImg()->cyHeight);
  476. pImgWnd->ImageToClient( rcImage );
  477. pImgWnd->GetClientRect( &rcClient );
  478. rcClient &= rcImage;
  479. ptClient = pt;
  480. pImgWnd->ScreenToClient( &ptClient );
  481. if ( CWnd::WindowFromPoint(pt) != pImgWnd
  482. || ! rcClient.PtInRect(ptClient))
  483. {
  484. if (fDraggingBrush && theImgBrush.m_pImg == NULL)
  485. HideBrush();
  486. pImgWnd->UpdPos( CPoint(-1, -1) );
  487. }
  488. else
  489. if (GetCapture() == NULL)
  490. {
  491. CPoint imagePt = ptClient;
  492. pImgWnd->ClientToImage( imagePt );
  493. if (! g_bBrushVisible && fDraggingBrush
  494. && CImgTool::GetCurrent()->UsesBrush())
  495. {
  496. pImgWnd->ShowBrush( imagePt );
  497. }
  498. }
  499. }
  500. }
  501. /***************************************************************************/
  502. void HideBrush()
  503. {
  504. if (! g_bBrushVisible)
  505. return;
  506. g_bBrushVisible = FALSE;
  507. CImgWnd* pImgWnd = g_pDragBrushWnd;
  508. ASSERT(pImgWnd);
  509. if (pImgWnd == NULL)
  510. return;
  511. IMG* pimg = pImgWnd->GetImg();
  512. if (pimg == NULL)
  513. return;
  514. HPALETTE hpalOld = pImgWnd->SetImgPalette( hRubberDC, FALSE ); // Background ??
  515. BitBlt( pimg->hDC, rcDragBrush.left,
  516. rcDragBrush.top,
  517. rcDragBrush.Width(),
  518. rcDragBrush.Height(),
  519. hRubberDC, rcDragBrush.left,
  520. rcDragBrush.top, SRCCOPY );
  521. if (hpalOld)
  522. SelectPalette( hRubberDC, hpalOld, FALSE ); // Background ??
  523. InvalImgRect( pimg, &rcDragBrush );
  524. }
  525. /***************************************************************************/
  526. void FixRect(RECT * prc)
  527. {
  528. int t;
  529. if (prc->left > prc->right)
  530. {
  531. t = prc->left;
  532. prc->left = prc->right;
  533. prc->right = t;
  534. }
  535. if (prc->top > prc->bottom)
  536. {
  537. t = prc->top;
  538. prc->top = prc->bottom;
  539. prc->bottom = t;
  540. }
  541. }
  542. /***************************************************************************/
  543. BOOL SetupRubber(IMG* pimg)
  544. {
  545. if (cxRubberWidth < pimg->cxWidth
  546. || cyRubberHeight < pimg->cyHeight)
  547. {
  548. HBITMAP hOldBitmap, hNewBitmap;
  549. HideBrush();
  550. if (hRubberDC == NULL
  551. && (hRubberDC = CreateCompatibleDC( pimg->hDC )) == NULL)
  552. return FALSE;
  553. hNewBitmap = CreateCompatibleBitmap( pimg->hDC, pimg->cxWidth, pimg->cyHeight );
  554. if (hNewBitmap == NULL)
  555. {
  556. return FALSE;
  557. }
  558. hRubberBM = hNewBitmap;
  559. hOldBitmap = (HBITMAP) SelectObject( hRubberDC, hRubberBM );
  560. if (hOldBitmap)
  561. {
  562. DeleteObject( hOldBitmap );
  563. }
  564. cxRubberWidth = pimg->cxWidth;
  565. cyRubberHeight = pimg->cyHeight;
  566. }
  567. if (pRubberImg != pimg)
  568. {
  569. HideBrush();
  570. HPALETTE hpalOld = NULL;
  571. if (theApp.m_pPalette
  572. && theApp.m_pPalette->m_hObject)
  573. {
  574. hpalOld = SelectPalette( hRubberDC, (HPALETTE)theApp.m_pPalette->m_hObject, FALSE );
  575. RealizePalette( hRubberDC );
  576. }
  577. BitBlt( hRubberDC, 0, 0, pimg->cxWidth,
  578. pimg->cyHeight, pimg->hDC, 0, 0, SRCCOPY );
  579. if (hpalOld)
  580. SelectPalette( hRubberDC, hpalOld, FALSE ); // Background ??
  581. }
  582. pRubberImg = pimg;
  583. return TRUE;
  584. }
  585. /***************************************************************************/
  586. CPalette* CreatePalette( const COLORREF* colors, int nColors )
  587. {
  588. CPalette* pPal = new CPalette;
  589. if (pPal)
  590. {
  591. LPLOGPALETTE pLogPal = (LPLOGPALETTE) LocalAlloc(
  592. LMEM_FIXED, sizeof (LOGPALETTE) + sizeof (PALETTEENTRY) * nColors);
  593. if (pLogPal)
  594. {
  595. pLogPal->palVersion = 0x300;
  596. pLogPal->palNumEntries = (WORD)nColors;
  597. for (int i = 0; i < nColors; i++)
  598. {
  599. pLogPal->palPalEntry[i] = *(PALETTEENTRY*)colors++;
  600. pLogPal->palPalEntry[i].peFlags = 0;
  601. }
  602. if (! CreateSafePalette(pPal, pLogPal ))
  603. {
  604. theApp.SetGdiEmergency();
  605. delete pPal;
  606. pPal = NULL;
  607. }
  608. LocalFree(pLogPal);
  609. }
  610. else
  611. {
  612. theApp.SetMemoryEmergency();
  613. delete pPal;
  614. pPal = NULL;
  615. }
  616. }
  617. return pPal;
  618. }
  619. /***************************************************************************/
  620. CPalette* GetStd16Palette()
  621. {
  622. return CreatePalette( std16Colors, 16 );
  623. }
  624. /***************************************************************************/
  625. CPalette* GetStd2Palette()
  626. {
  627. return CreatePalette( std2Colors, 2 );
  628. }
  629. /***************************************************************************/
  630. CPalette* GetStd256Palette()
  631. {
  632. return CreatePalette( colorColorsDef, NUM_DEF_COLORS );
  633. }
  634. /***************************************************************************/
  635. CPalette *PaletteFromDS(HDC hdc)
  636. {
  637. DWORD adw[257];
  638. int i,n;
  639. CPalette *pPal = new CPalette;
  640. if ( n = GetDIBColorTable(hdc, 0, 256, (LPRGBQUAD)&adw[1]) )
  641. {
  642. for (i=1; i<=n; i++)
  643. adw[i] = RGB(GetBValue(adw[i]),GetGValue(adw[i]),GetRValue(adw[i]));
  644. adw[0] = MAKELONG(0x300, n);
  645. CreateSafePalette(pPal, (LPLOGPALETTE)&adw[0]);
  646. }
  647. else
  648. {
  649. // No Palette in Bitmap! Use default half-tone palette
  650. pPal->Attach(CreateHalftonePalette( NULL ));
  651. }
  652. return pPal;
  653. }
  654. /////////////////////////////////////////////////////////////////////////////
  655. //
  656. // Packed-DIB Handling Functions
  657. //
  658. // A packed-DIB is a bucket of bits usually consisting of a BITMAPINFOHEADER
  659. // structure followed by an array of RGBQUAD structures followed by the words
  660. // that make up the image. An alternate form consists of a BITMAPCOREHEADER
  661. // structure followed by an array of RGBTRIPLE structures and the image words.
  662. // This format is used by OS/2, but is supported by Windows. The only way
  663. // to tell which format the DIB is using is to check the first word against
  664. // the sizes of the header structures (pretty clever eh?).
  665. //
  666. // This is very similar to a DIB as stored in a file. In fact, a DIB file is
  667. // a BITMAPFILEHEADER structure followed by a packed DIB.
  668. //
  669. // These functions make dealing with packed-DIBs in memory easier.
  670. //
  671. #define WIDTHBYTES(bits) ((((bits) + 31) / 32) * 4)
  672. /***************************************************************************/
  673. void FreeDib(HGLOBAL hDib)
  674. {
  675. ASSERT( hDib );
  676. if (hDib)
  677. GlobalFree(hDib);
  678. }
  679. /***************************************************************************/
  680. HGLOBAL DibFromBitmap( HBITMAP hBitmap, DWORD dwStyle, WORD wBits,
  681. CPalette* pPal, HBITMAP hMaskBitmap, DWORD& dwLen,
  682. LONG cXPelsPerMeter, LONG cYPelsPerMeter )
  683. {
  684. ASSERT(hBitmap);
  685. if (hBitmap == NULL)
  686. return NULL;
  687. ASSERT(hMaskBitmap == NULL || dwStyle == BI_RGB);
  688. HBITMAP hbm;
  689. BITMAP bm;
  690. BITMAPINFOHEADER bi;
  691. LPBITMAPINFOHEADER lpbi;
  692. HDC hDC;
  693. DWORD dwSmallLen;
  694. HPALETTE hPal = (HPALETTE)(pPal->GetSafeHandle());
  695. if (theApp.m_bPaletted && ! hPal)
  696. hPal = (HPALETTE)::GetStockObject( DEFAULT_PALETTE );
  697. GetObject( hBitmap, sizeof( bm ), (LPSTR)&bm );
  698. if (wBits == 0)
  699. wBits = bm.bmPlanes * bm.bmBitsPixel;
  700. if (wBits <= 1)
  701. wBits = 1;
  702. else
  703. if (wBits <= 4)
  704. wBits = 4;
  705. else
  706. if (wBits <= 8)
  707. wBits = 8;
  708. else
  709. wBits = 24;
  710. bi.biSize = sizeof( BITMAPINFOHEADER );
  711. bi.biWidth = bm.bmWidth;
  712. bi.biHeight = bm.bmHeight;
  713. bi.biPlanes = 1;
  714. bi.biBitCount = wBits;
  715. bi.biCompression = dwStyle;
  716. bi.biSizeImage = 0;
  717. // bi.biXPelsPerMeter = theApp.ScreenDeviceInfo.ixPelsPerDM * 10;
  718. // bi.biYPelsPerMeter = theApp.ScreenDeviceInfo.iyPelsPerDM * 10;
  719. // HDC hdc = GetDC(NULL);
  720. // bi.biXPelsPerMeter = MulDiv(::GetDeviceCaps(hdc, LOGPIXELSX),10000, 254);
  721. // bi.biYPelsPerMeter = MulDiv(::GetDeviceCaps(hdc, LOGPIXELSY),10000, 254);
  722. // ReleaseDC (NULL, hdc);
  723. bi.biXPelsPerMeter = cXPelsPerMeter;
  724. bi.biYPelsPerMeter = cYPelsPerMeter;
  725. bi.biClrUsed = 0;
  726. bi.biClrImportant = 0;
  727. dwSmallLen = dwLen = bi.biSize + PaletteSize( (LPSTR) &bi );
  728. lpbi = (LPBITMAPINFOHEADER) GlobalAlloc(GPTR, dwLen);
  729. if (lpbi == NULL)
  730. {
  731. theApp.SetMemoryEmergency();
  732. return NULL;
  733. }
  734. *lpbi = bi;
  735. hbm = CreateBitmap( 2, 2, bm.bmPlanes, bm.bmBitsPixel, NULL );
  736. hDC = CreateCompatibleDC( NULL );
  737. if (hbm == NULL || hDC == NULL)
  738. {
  739. if (hbm)
  740. DeleteObject( hbm );
  741. theApp.SetGdiEmergency();
  742. return NULL;
  743. }
  744. HPALETTE hPalOld = NULL;
  745. HANDLE hbmOld = SelectObject( hDC, hbm );
  746. if (hPal)
  747. {
  748. hPalOld = SelectPalette( hDC, hPal, FALSE );
  749. RealizePalette( hDC );
  750. }
  751. // Compute the byte size of the DIB...
  752. GetDIBits( hDC, hBitmap, 0, (WORD)bi.biHeight, NULL, (LPBITMAPINFO)lpbi, DIB_RGB_COLORS );
  753. bi = *lpbi;
  754. // If the driver did not fill in the biSizeImage field, make one up
  755. // NOTE: This size will be too big if the bitmap is compressed!
  756. // NOTE: This happens with the Paradise 800x600x256 driver...
  757. if (bi.biSizeImage == 0)
  758. {
  759. TRACE( TEXT("Display driver bug! We have to compute DIB size...") );
  760. bi.biSizeImage = WIDTHBYTES( (DWORD)bi.biWidth * wBits ) * bi.biHeight;
  761. if (dwStyle != BI_RGB)
  762. bi.biSizeImage = (bi.biSizeImage * 3) / 2;
  763. }
  764. dwLen = bi.biSize + PaletteSize( (LPSTR)&bi ) + bi.biSizeImage;
  765. if (hMaskBitmap)
  766. dwLen += (LONG)WIDTHBYTES( bi.biWidth ) * bi.biHeight;
  767. CHAR* hpv = (CHAR*) GlobalAlloc(GPTR, dwLen);
  768. if (! hpv)
  769. {
  770. theApp.SetMemoryEmergency();
  771. GlobalFree(lpbi);
  772. if (hbmOld)
  773. DeleteObject( SelectObject( hDC, hbmOld ) );
  774. if (hPalOld)
  775. SelectPalette( hDC, hPalOld, FALSE );
  776. DeleteDC( hDC );
  777. return NULL;
  778. }
  779. memcpy( hpv, (void*)lpbi, dwSmallLen );
  780. GlobalFree(lpbi);
  781. lpbi = (LPBITMAPINFOHEADER)hpv;
  782. LPSTR lpBits = (LPSTR)lpbi + lpbi->biSize + PaletteSize((LPSTR)lpbi);
  783. DWORD biSizeImage = lpbi->biSizeImage;
  784. if (hMaskBitmap)
  785. {
  786. // Do the mask first so the dib ends up with the main bitmap's
  787. // size and palette when we're done...
  788. LONG cbAdjust = ((LONG)WIDTHBYTES( bi.biWidth * wBits )) * bi.biHeight;
  789. lpBits += cbAdjust;
  790. WORD biBitCount = lpbi->biBitCount;
  791. lpbi->biBitCount = 1;
  792. lpbi->biSizeImage = 0;
  793. if (GetDIBits( hDC, hMaskBitmap, 0, (WORD)bi.biHeight, lpBits,
  794. (LPBITMAPINFO)lpbi, DIB_RGB_COLORS ) == 0)
  795. {
  796. GlobalFree(hpv);
  797. if (hbmOld)
  798. DeleteObject( SelectObject( hDC, hbmOld ) );
  799. if (hPalOld)
  800. SelectPalette( hDC, hPalOld, FALSE );
  801. DeleteDC(hDC);
  802. return NULL;
  803. }
  804. biSizeImage += lpbi->biSizeImage;
  805. lpbi->biBitCount = biBitCount;
  806. lpBits -= cbAdjust;
  807. }
  808. if (GetDIBits( hDC, hBitmap, 0, (WORD)bi.biHeight, lpBits,
  809. (LPBITMAPINFO)lpbi, DIB_RGB_COLORS ) == 0)
  810. {
  811. GlobalFree(hpv);
  812. if (hbmOld)
  813. DeleteObject( SelectObject( hDC, hbmOld ) );
  814. if (hPalOld)
  815. SelectPalette( hDC, hPalOld, FALSE );
  816. DeleteDC(hDC);
  817. return NULL;
  818. }
  819. lpbi->biSizeImage = biSizeImage;
  820. if (hMaskBitmap)
  821. lpbi->biHeight *= 2;
  822. if (hbmOld)
  823. DeleteObject( SelectObject( hDC, hbmOld ) );
  824. if (hPalOld)
  825. SelectPalette( hDC, hPalOld, FALSE );
  826. DeleteDC( hDC );
  827. return (LPSTR)lpbi;
  828. }
  829. /***************************************************************************/
  830. UINT DIBBitsPixel(LPSTR lpbi)
  831. {
  832. // Calculate the number of colors in the color table based on
  833. // the number of bits per pixel for the DIB.
  834. if (IS_WIN30_DIB(lpbi))
  835. {
  836. return(((LPBITMAPINFOHEADER)lpbi)->biBitCount);
  837. }
  838. else
  839. {
  840. return(((LPBITMAPCOREHEADER)lpbi)->bcBitCount);
  841. }
  842. }
  843. WORD DIBNumColors(LPSTR lpbi, BOOL bJustUsed)
  844. {
  845. WORD wBitCount;
  846. // If this is a Windows style DIB, the number of colors in the
  847. // color table can be less than the number of bits per pixel
  848. // allows for (i.e. lpbi->biClrUsed can be set to some value).
  849. // If this is the case, return the appropriate value.
  850. if (IS_WIN30_DIB( lpbi ) && bJustUsed)
  851. {
  852. DWORD dwClrUsed = ((LPBITMAPINFOHEADER)lpbi)->biClrUsed;
  853. if (dwClrUsed != 0)
  854. return (WORD)dwClrUsed;
  855. }
  856. // Calculate the number of colors in the color table based on
  857. // the number of bits per pixel for the DIB.
  858. wBitCount = (WORD)DIBBitsPixel(lpbi);
  859. switch (wBitCount)
  860. {
  861. case 1:
  862. return 2;
  863. case 4:
  864. return 16;
  865. case 8:
  866. return 256;
  867. default:
  868. return 0;
  869. }
  870. }
  871. /***************************************************************************/
  872. WORD PaletteSize(LPSTR lpbi)
  873. {
  874. if (IS_WIN30_DIB(lpbi) &&
  875. ((LPBITMAPINFOHEADER)lpbi)->biCompression==BI_BITFIELDS)
  876. {
  877. // Images with bitfields have 3 DWORD's that specify the RGB components
  878. // (respectively) of each pixel.
  879. if (((LPBITMAPINFOHEADER)lpbi)->biSize >= sizeof(BITMAPV4HEADER))
  880. {
  881. return 0;
  882. }
  883. else
  884. return(3 * sizeof(DWORD));
  885. }
  886. return DIBNumColors(lpbi,TRUE) *
  887. (IS_WIN30_DIB(lpbi) ? sizeof(RGBQUAD) : sizeof(RGBTRIPLE));
  888. }
  889. /***************************************************************************/
  890. LPSTR FindDIBBits(LPSTR lpbi, DWORD dwOffBits)
  891. {
  892. DWORD dwAfterHdr = *(LPDWORD)lpbi + PaletteSize(lpbi);
  893. DWORD dwOff;
  894. #if 0
  895. if (dwOffBits && dwAfterHdr != dwOffBits)
  896. {
  897. MessageBeep(0);
  898. }
  899. #endif
  900. dwOff = max(dwOffBits, dwAfterHdr);
  901. return(lpbi + dwOff);
  902. }
  903. /***************************************************************************/
  904. DWORD DIBWidth(LPSTR lpDIB)
  905. {
  906. LPBITMAPINFOHEADER lpbmi = (LPBITMAPINFOHEADER)lpDIB;
  907. LPBITMAPCOREHEADER lpbmc = (LPBITMAPCOREHEADER)lpDIB;
  908. if (lpbmi->biSize >= sizeof (BITMAPINFOHEADER))
  909. return (DWORD) abs(lpbmi->biWidth);
  910. else
  911. return (DWORD) abs(lpbmc->bcWidth);
  912. }
  913. /***************************************************************************/
  914. DWORD DIBHeight(LPSTR lpDIB)
  915. {
  916. LPBITMAPINFOHEADER lpbmi = (LPBITMAPINFOHEADER)lpDIB;
  917. LPBITMAPCOREHEADER lpbmc = (LPBITMAPCOREHEADER)lpDIB;
  918. if (lpbmi->biSize >= sizeof (BITMAPINFOHEADER))
  919. return (DWORD) abs(lpbmi->biHeight);
  920. else
  921. return (DWORD) abs(lpbmc->bcHeight);
  922. }
  923. /***************************************************************************/
  924. HBITMAP DIBToBitmap( LPSTR lpDIBHdr, CPalette* pPal, HDC hdc )
  925. {
  926. ASSERT( lpDIBHdr );
  927. ASSERT( hdc );
  928. if (! lpDIBHdr || ! hdc)
  929. return NULL;
  930. LPBYTE lpDIBBits = (LPBYTE)FindDIBBits( lpDIBHdr,0 );
  931. CPalette* ppalOld = NULL;
  932. CBitmap* pbmOld = NULL;
  933. CBitmap bmTemp;
  934. CDC dc;
  935. dc.Attach( hdc );
  936. if (bmTemp.CreateCompatibleBitmap( &dc, 2, 2 ))
  937. pbmOld = dc.SelectObject( &bmTemp );
  938. if (pPal)
  939. {
  940. ASSERT( pPal->m_hObject );
  941. #ifdef FORCEBACKPALETTE
  942. ppalOld = dc.SelectPalette( pPal, TRUE );
  943. #else
  944. ppalOld = dc.SelectPalette( pPal, FALSE );
  945. #endif
  946. dc.RealizePalette();
  947. }
  948. HBITMAP hBitmap = CreateDIBitmap( dc.m_hDC, (LPBITMAPINFOHEADER)lpDIBHdr,
  949. CBM_INIT, lpDIBBits,
  950. (LPBITMAPINFO)lpDIBHdr, DIB_RGB_COLORS );
  951. if (ppalOld)
  952. dc.SelectPalette( ppalOld, FALSE );
  953. if (pbmOld)
  954. dc.SelectObject( pbmOld );
  955. if (bmTemp.m_hObject)
  956. bmTemp.DeleteObject();
  957. dc.Detach();
  958. return hBitmap;
  959. }
  960. /***************************************************************************/
  961. BOOL ShouldUseDDB(HDC hdc, LPBITMAPINFO lpDIBHdr)
  962. {
  963. if (!IS_WIN30_DIB(lpDIBHdr))
  964. {
  965. // I don't want to write special code to deal with this case
  966. return(FALSE);
  967. }
  968. if (lpDIBHdr->bmiHeader.biPlanes*lpDIBHdr->bmiHeader.biBitCount != 4)
  969. {
  970. // No DDB for mono or 8bit or more
  971. return(FALSE);
  972. }
  973. UINT cBitCount = GetDeviceCaps( hdc, BITSPIXEL )
  974. * GetDeviceCaps( hdc, PLANES );
  975. if (cBitCount > 4)
  976. {
  977. return(FALSE);
  978. }
  979. RGBQUAD *lpPal = lpDIBHdr->bmiColors;
  980. for (int i=DIBNumColors((LPSTR)lpDIBHdr, TRUE); i>0; --i, ++lpPal)
  981. {
  982. COLORREF cr = RGB(lpPal->rgbRed, lpPal->rgbGreen, lpPal->rgbBlue);
  983. if (GetNearestColor(hdc, cr) != cr)
  984. {
  985. return(FALSE);
  986. }
  987. }
  988. // OK, so this is a WIN30 DIB, the screen is 16 or less colors, it is
  989. // either an uncompressed or RLE DIB, and all the colors in the DIB can
  990. // be shown on the screen. I guess we can use a DDB.
  991. return(TRUE);
  992. }
  993. /***************************************************************************/
  994. HBITMAP DIBToDS( LPSTR lpDIB, DWORD dwOffBits, HDC hdc )
  995. {
  996. ASSERT( lpDIB );
  997. ASSERT( hdc );
  998. if (! lpDIB || ! hdc)
  999. {
  1000. return NULL;
  1001. }
  1002. LPVOID lpNewBits;
  1003. LPBITMAPINFO lpDIBHdr = (LPBITMAPINFO)lpDIB;
  1004. LPBYTE lpDIBBits = (LPBYTE)FindDIBBits( lpDIB, dwOffBits );
  1005. {
  1006. // New block just to scope dcScreen
  1007. CClientDC dcScreen(NULL);
  1008. if (ShouldUseDDB(dcScreen.m_hDC, lpDIBHdr))
  1009. {
  1010. return(CreateDIBitmap( dcScreen.m_hDC, &lpDIBHdr->bmiHeader,
  1011. CBM_INIT, lpDIBBits, lpDIBHdr, DIB_RGB_COLORS ));
  1012. }
  1013. }
  1014. // Compressed DIB sections are not allowed
  1015. DWORD dwCompression = lpDIBHdr->bmiHeader.biCompression;
  1016. if (IS_WIN30_DIB(lpDIB))
  1017. {
  1018. lpDIBHdr->bmiHeader.biCompression = BI_RGB;
  1019. }
  1020. HBITMAP hBitmap = CreateDIBSection( hdc, lpDIBHdr, DIB_RGB_COLORS,
  1021. &lpNewBits, NULL, 0);
  1022. if (IS_WIN30_DIB(lpDIB))
  1023. {
  1024. lpDIBHdr->bmiHeader.biCompression = dwCompression;
  1025. }
  1026. if (hBitmap)
  1027. {
  1028. HBITMAP hbmOld = (HBITMAP)SelectObject(hdc, hBitmap);
  1029. if (hbmOld)
  1030. {
  1031. UINT uWid = DIBWidth(lpDIB);
  1032. UINT uHgt = DIBHeight(lpDIB);
  1033. // Fill with white in case the bitmap has any jumps in it.
  1034. PatBlt(hdc, 0, 0, uWid, uHgt, WHITENESS);
  1035. // StretchDIBits(hdc, 0, 0, uWid, uHgt, 0, 0, uWid, uHgt, lpDIBBits,
  1036. // (LPBITMAPINFO)lpDIBHdr, DIB_RGB_COLORS, SRCCOPY);
  1037. SetDIBitsToDevice (hdc,0,0,uWid, uHgt,0,0,0,abs(uHgt),lpDIBBits,
  1038. (LPBITMAPINFO)lpDIBHdr, DIB_RGB_COLORS);
  1039. SelectObject(hdc, hbmOld);
  1040. return(hBitmap);
  1041. }
  1042. DeleteObject(hBitmap);
  1043. }
  1044. return(NULL);
  1045. }
  1046. //------------------------------------------------------------------------------
  1047. // SetNewPalette - Used solely by GetRainbowPalette below for initialization.
  1048. //------------------------------------------------------------------------------
  1049. static void SetNewPalette( PALETTEENTRY* const pPal, PWORD pwRainbowColors,
  1050. UINT R, UINT G, UINT B )
  1051. {
  1052. if (*pwRainbowColors < 256)
  1053. {
  1054. WORD wC;
  1055. for (wC = 0; wC < *pwRainbowColors; wC++)
  1056. if (((UINT)GetRValue( *(DWORD*)&pPal[ wC ] ) /* + 1 & ~1 */ ) == (R /* + 1 & ~1 */ )
  1057. && ((UINT)GetGValue( *(DWORD*)&pPal[ wC ] ) /* + 1 & ~1 */ ) == (G /* + 1 & ~1 */ )
  1058. && ((UINT)GetBValue( *(DWORD*)&pPal[ wC ] ) /* + 1 & ~1 */ ) == (B /* + 1 & ~1 */ ))
  1059. return;
  1060. pPal[*pwRainbowColors].peRed = (BYTE)R;
  1061. pPal[*pwRainbowColors].peGreen = (BYTE)G;
  1062. pPal[*pwRainbowColors].peBlue = (BYTE)B;
  1063. pPal[*pwRainbowColors].peFlags = 0;
  1064. (*pwRainbowColors)++;
  1065. }
  1066. }
  1067. /***************************************************************************/
  1068. CPalette* CreateDIBPalette(LPSTR lpbi)
  1069. {
  1070. LPLOGPALETTE lpPal;
  1071. CPalette* pPal = NULL;
  1072. int iLoop;
  1073. int wNumColors;
  1074. LPBITMAPINFO lpbmi;
  1075. LPBITMAPCOREINFO lpbmc;
  1076. BOOL bWinStyleDIB;
  1077. BOOL bGetDriverDefaults = FALSE;
  1078. ASSERT( lpbi );
  1079. if (lpbi == NULL)
  1080. return NULL;
  1081. lpbmi = (LPBITMAPINFO)lpbi;
  1082. lpbmc = (LPBITMAPCOREINFO)lpbi;
  1083. wNumColors = (int)DIBNumColors(lpbi, TRUE);
  1084. bWinStyleDIB = IS_WIN30_DIB(lpbi);
  1085. if (! wNumColors)
  1086. {
  1087. if (! theApp.m_bPaletted)
  1088. return NULL;
  1089. bGetDriverDefaults = TRUE;
  1090. wNumColors = 256;
  1091. }
  1092. lpPal = (LPLOGPALETTE)new CHAR [sizeof( LOGPALETTE ) + sizeof( PALETTEENTRY ) * (wNumColors - 1)];
  1093. if (lpPal == NULL)
  1094. {
  1095. theApp.SetMemoryEmergency();
  1096. return NULL;
  1097. }
  1098. if (bGetDriverDefaults)
  1099. {
  1100. #define DIM( X ) (sizeof(X) / sizeof(X[0]))
  1101. // GetRainbowPalette - Based on
  1102. // Fran Finnegan's column in Microsoft Systems Journal, Sept.-Oct., 1991 (#5).
  1103. static BYTE C[] = { 255, 238, 221,
  1104. 204, 187, 170,
  1105. 153, 136, 119,
  1106. 102, 85, 68,
  1107. 51, 34, 17,
  1108. 0
  1109. };
  1110. PALETTEENTRY* pPal = &(lpPal->palPalEntry[0]);
  1111. WORD wColors = 0;
  1112. int iC;
  1113. int iR;
  1114. int iG;
  1115. int iB;
  1116. for (iC = 0; iC < DIM( C ); iC++)
  1117. SetNewPalette( pPal, &wColors, C[ iC ], C[ iC ], C[ iC ] );
  1118. for (iR = 0; iR < DIM( C ); iR += 3)
  1119. for (iG = 0; iG < DIM( C ); iG += 3)
  1120. for (iB = 0; iB < DIM( C ); iB += 3)
  1121. SetNewPalette( pPal, &wColors, C[ iR ], C[ iG ], C[ iB ] );
  1122. for (iC = 0; iC < DIM( C ); iC++)
  1123. {
  1124. SetNewPalette( pPal, &wColors, C[ iC ], 0, 0 );
  1125. SetNewPalette( pPal, &wColors, 0, C[ iC ], 0 );
  1126. SetNewPalette( pPal, &wColors, 0, 0, C[ iC ] );
  1127. }
  1128. }
  1129. else
  1130. for (iLoop = 0; iLoop < wNumColors; iLoop++)
  1131. {
  1132. if (bWinStyleDIB)
  1133. {
  1134. lpPal->palPalEntry[iLoop].peRed = lpbmi->bmiColors[iLoop].rgbRed;
  1135. lpPal->palPalEntry[iLoop].peGreen = lpbmi->bmiColors[iLoop].rgbGreen;
  1136. lpPal->palPalEntry[iLoop].peBlue = lpbmi->bmiColors[iLoop].rgbBlue;
  1137. lpPal->palPalEntry[iLoop].peFlags = 0;
  1138. }
  1139. else
  1140. {
  1141. lpPal->palPalEntry[iLoop].peRed = lpbmc->bmciColors[iLoop].rgbtRed;
  1142. lpPal->palPalEntry[iLoop].peGreen = lpbmc->bmciColors[iLoop].rgbtGreen;
  1143. lpPal->palPalEntry[iLoop].peBlue = lpbmc->bmciColors[iLoop].rgbtBlue;
  1144. lpPal->palPalEntry[iLoop].peFlags = 0;
  1145. }
  1146. }
  1147. lpPal->palVersion = 0x300;
  1148. lpPal->palNumEntries = (WORD)wNumColors;
  1149. pPal = new CPalette;
  1150. if (pPal == NULL || ! CreateSafePalette(pPal, lpPal ))
  1151. {
  1152. if (pPal)
  1153. delete pPal;
  1154. pPal = NULL;
  1155. }
  1156. delete [] (CHAR*)lpPal;
  1157. return pPal;
  1158. }
  1159. /***************************************************************************/
  1160. void Draw3dRect(HDC hDC, RECT * prc)
  1161. {
  1162. CDC* pDC = CDC::FromHandle(hDC);
  1163. CBrush* pOldBrush = pDC->SelectObject( GetSysBrush( COLOR_BTNSHADOW ) );
  1164. pDC->PatBlt(prc->left, prc->top, prc->right - prc->left - 1, 1, PATCOPY);
  1165. pDC->PatBlt(prc->left, prc->top + 1, 1, prc->bottom - prc->top - 2, PATCOPY);
  1166. pDC->SelectObject(GetSysBrush( COLOR_BTNHIGHLIGHT ));
  1167. pDC->PatBlt(prc->left + 1, prc->bottom - 1,
  1168. prc->right - prc->left - 1, 1, PATCOPY);
  1169. pDC->PatBlt(prc->right - 1, prc->top + 1,
  1170. 1, prc->bottom - prc->top - 1, PATCOPY);
  1171. pDC->SelectObject(pOldBrush);
  1172. }
  1173. /***************************************************************************/
  1174. // DrawBitmap:
  1175. // See header file for usage.
  1176. void DrawBitmap(CDC* dc, CBitmap* bmSrc, CRect* rc,
  1177. DWORD dwROP /* = SRCCOPY */, CDC* memdc /* = NULL */)
  1178. {
  1179. CBitmap* obm;
  1180. CDC* odc = (memdc? memdc : (new CDC));
  1181. if (!memdc)
  1182. odc->CreateCompatibleDC(dc);
  1183. obm = odc->SelectObject(bmSrc);
  1184. BITMAP bms;
  1185. bmSrc->GetObject(sizeof (BITMAP), (LPSTR)(LPBITMAP)(&bms));
  1186. if (rc)
  1187. {
  1188. dc->BitBlt(rc->left + ((rc->right - rc->left - bms.bmWidth) >> 1),
  1189. rc->top + ((rc->bottom - rc->top - bms.bmHeight) >> 1),
  1190. bms.bmWidth, bms.bmHeight, odc, 0, 0, dwROP);
  1191. }
  1192. else
  1193. {
  1194. dc->BitBlt(0, 0, bms.bmWidth, bms.bmHeight, odc, 0, 0, dwROP);
  1195. }
  1196. odc->SelectObject(obm);
  1197. if (!memdc)
  1198. {
  1199. odc->DeleteDC();
  1200. delete odc;
  1201. }
  1202. }
  1203. /***************************************************************************/
  1204. BOOL EnsureUndoSize(IMG* pimg)
  1205. {
  1206. if (cxUndoWidth < pimg->cxWidth || cyUndoHeight < pimg->cyHeight ||
  1207. (int)cUndoPlanes != pimg->cPlanes ||
  1208. (int)cUndoBitCount != pimg->cBitCount)
  1209. {
  1210. HBITMAP hNewUndoImgBitmap = NULL;
  1211. // HBITMAP hNewUndoMaskBitmap = NULL;
  1212. HPALETTE hNewUndoPalette = NULL;
  1213. hNewUndoImgBitmap = CreateCompatibleBitmap( pimg->hDC, pimg->cxWidth, pimg->cyHeight );
  1214. if (hNewUndoImgBitmap == NULL)
  1215. {
  1216. TRACE(TEXT("EnsureUndoSize: Create image bitmap failed!\n"));
  1217. return FALSE;
  1218. }
  1219. // hNewUndoMaskBitmap = CreateBitmap( pimg->cxWidth, pimg->cyHeight, 1, 1, NULL );
  1220. // if (hNewUndoMaskBitmap == NULL)
  1221. // {
  1222. // TRACE(TEXT("EnsureUndoSize: Create mask bitmap failed!\n"));
  1223. // DeleteObject( hNewUndoImgBitmap );
  1224. // return FALSE;
  1225. // }
  1226. // if (theApp.m_pPalette)
  1227. // {
  1228. // LOGPALETTE256 logPal;
  1229. // logPal.palVersion = 0x300;
  1230. // logPal.palNumEntries = theApp.m_pPalette->GetPaletteEntries( 0, 256,
  1231. // &logPal.palPalEntry[0] );
  1232. // theApp.m_pPalette->GetPaletteEntries( 0, logPal.palNumEntries,
  1233. // &logPal.palPalEntry[0] );
  1234. // hNewUndoPalette = ::CreatePalette( (LPLOGPALETTE)&logPal );
  1235. // if (! hNewUndoPalette)
  1236. // {
  1237. // TRACE("EnsureUndoSize: Create palette bitmap failed!\n");
  1238. // DeleteObject( hNewUndoImgBitmap );
  1239. // DeleteObject( hNewUndoMaskBitmap );
  1240. // return FALSE;
  1241. // }
  1242. // }
  1243. if (g_hUndoImgBitmap)
  1244. DeleteObject(g_hUndoImgBitmap);
  1245. // if (g_hUndoPalette)
  1246. // DeleteObject(g_hUndoPalette);
  1247. g_hUndoImgBitmap = hNewUndoImgBitmap;
  1248. // g_hUndoPalette = hNewUndoPalette;
  1249. cxUndoWidth = pimg->cxWidth;
  1250. cyUndoHeight = pimg->cyHeight;
  1251. cUndoPlanes = (BYTE)pimg->cPlanes;
  1252. cUndoBitCount = (BYTE)pimg->cBitCount;
  1253. }
  1254. return TRUE;
  1255. }
  1256. /***************************************************************************/
  1257. void CleanupImgUndo()
  1258. {
  1259. if (g_hUndoImgBitmap)
  1260. DeleteObject(g_hUndoImgBitmap);
  1261. if (g_hUndoPalette)
  1262. DeleteObject(g_hUndoPalette);
  1263. g_hUndoImgBitmap = NULL;
  1264. g_hUndoPalette = NULL;
  1265. cxUndoWidth = 0;
  1266. cyUndoHeight = 0;
  1267. cUndoPlanes = 0;
  1268. cUndoBitCount = 0;
  1269. }
  1270. /***************************************************************************/
  1271. BOOL SetUndo(IMG* pimg)
  1272. {
  1273. BOOL bSuccess = FALSE;
  1274. HDC hTempDC = NULL;
  1275. HBITMAP hOldBitmap = NULL;
  1276. CRect rect;
  1277. if (! EnsureUndoSize( pimg ))
  1278. goto LReturn;
  1279. rect.SetRect( 0, 0, pimg->cxWidth, pimg->cyHeight );
  1280. hTempDC = CreateCompatibleDC( pimg->hDC );
  1281. if (hTempDC == NULL)
  1282. {
  1283. TRACE( TEXT("SetUndo: CreateCompatibleDC failed\n") );
  1284. goto LReturn;
  1285. }
  1286. hOldBitmap = (HBITMAP)SelectObject( hTempDC, g_hUndoImgBitmap );
  1287. BitBlt( hTempDC, 0, 0, rect.Width(), rect.Height(),
  1288. pimg->hDC, rect.left, rect.top, SRCCOPY );
  1289. SelectObject( hTempDC, hOldBitmap );
  1290. DeleteDC( hTempDC );
  1291. bSuccess = TRUE;
  1292. LReturn:
  1293. return bSuccess;
  1294. }
  1295. /***************************************************************************/
  1296. void DrawBrush(IMG* pimg, CPoint pt, BOOL bDraw)
  1297. {
  1298. int nStrokeWidth = CImgTool::GetCurrent()->GetStrokeWidth();
  1299. if (g_bCustomBrush)
  1300. {
  1301. CRect rc(pt.x, pt.y,
  1302. pt.x + theImgBrush.m_size.cx, pt.y + theImgBrush.m_size.cy);
  1303. rc -= (CPoint)theImgBrush.m_handle;
  1304. theImgBrush.m_rcSelection = rc;
  1305. int nCombineMode;
  1306. COLORREF cr;
  1307. if (bDraw)
  1308. {
  1309. nCombineMode = (theImgBrush.m_bOpaque) ? combineReplace : combineMatte;
  1310. cr = crLeft;
  1311. }
  1312. else
  1313. {
  1314. nCombineMode = combineColor;
  1315. cr = crRight;
  1316. }
  1317. if (CImgTool::GetCurrentID() == IDMX_TEXTTOOL)
  1318. {
  1319. // extern CTextTool g_textTool;
  1320. // g_textTool.Render(CDC::FromHandle(pimg->hDC), rc, TRUE, TRUE);
  1321. }
  1322. else
  1323. {
  1324. switch (nCombineMode)
  1325. {
  1326. #ifdef DEBUG
  1327. default:
  1328. ASSERT(FALSE);
  1329. #endif
  1330. case combineColor:
  1331. theImgBrush.BltColor(pimg, rc.TopLeft(), cr);
  1332. break;
  1333. case combineMatte:
  1334. theImgBrush.BltMatte(pimg, rc.TopLeft());
  1335. break;
  1336. case combineReplace:
  1337. theImgBrush.BltReplace(pimg, rc.TopLeft());
  1338. break;
  1339. }
  1340. }
  1341. InvalImgRect (pimg, &rc);
  1342. CommitImgRect(pimg, &rc);
  1343. }
  1344. else
  1345. {
  1346. DrawImgLine(pimg, pt, pt, bDraw ? crLeft : crRight,
  1347. CImgTool::GetCurrent()->GetStrokeWidth(),
  1348. CImgTool::GetCurrent()->GetStrokeShape(), TRUE);
  1349. rcDragBrush.left = pt.x - nStrokeWidth / 2;
  1350. rcDragBrush.top = pt.y - nStrokeWidth / 2;
  1351. rcDragBrush.right = rcDragBrush.left + nStrokeWidth;
  1352. rcDragBrush.bottom = rcDragBrush.top + nStrokeWidth;
  1353. }
  1354. }
  1355. /***************************************************************************/
  1356. void DrawDCLine(HDC hDC, CPoint pt1, CPoint pt2,
  1357. COLORREF color, int nWidth, int nShape,
  1358. CRect& rc)
  1359. {
  1360. HPEN hOldPen;
  1361. HBRUSH hBrush;
  1362. HBRUSH hOldBrush;
  1363. int sx;
  1364. int sy;
  1365. int ex;
  1366. int ey;
  1367. int nWidthD2 = nWidth / 2;
  1368. sx = pt1.x;
  1369. sy = pt1.y;
  1370. ex = pt2.x;
  1371. ey = pt2.y;
  1372. if (hDC)
  1373. {
  1374. hBrush = ::CreateSolidBrush( color );
  1375. hOldBrush = (HBRUSH)SelectObject( hDC, hBrush );
  1376. if (nWidth == 1)
  1377. {
  1378. HPEN hPen = CreatePen(PS_SOLID, 1, (COLORREF)color);
  1379. if (hPen)
  1380. {
  1381. hOldPen = (HPEN)SelectObject(hDC, hPen);
  1382. ::MoveToEx(hDC, sx, sy, NULL);
  1383. LineTo(hDC, ex, ey);
  1384. SetPixel(hDC, ex, ey, color);
  1385. SelectObject(hDC, hOldPen);
  1386. DeleteObject(hPen);
  1387. }
  1388. }
  1389. else
  1390. {
  1391. // hOldPen = (HPEN)SelectObject(hDC, GetStockObject( NULL_PEN ));
  1392. BrushLine( CDC::FromHandle(hDC),
  1393. CPoint(sx - nWidthD2, sy - nWidthD2),
  1394. CPoint(ex - nWidthD2, ey - nWidthD2), nWidth, nShape);
  1395. // SelectObject( hDC, hOldPen );
  1396. }
  1397. SelectObject(hDC, hOldBrush);
  1398. DeleteObject(hBrush);
  1399. }
  1400. if (sx < ex)
  1401. {
  1402. rc.left = sx;
  1403. rc.right = ex + 1;
  1404. }
  1405. else
  1406. {
  1407. rc.left = ex;
  1408. rc.right = sx + 1;
  1409. }
  1410. if (sy < ey)
  1411. {
  1412. rc.top = sy;
  1413. rc.bottom = ey + 1;
  1414. }
  1415. else
  1416. {
  1417. rc.top = ey;
  1418. rc.bottom = sy + 1;
  1419. }
  1420. rc.left -= nWidth * 2;
  1421. rc.top -= nWidth * 2;
  1422. rc.right += nWidth * 2;
  1423. rc.bottom += nWidth * 2;
  1424. }
  1425. void DrawImgLine(IMG* pimg, CPoint pt1, CPoint pt2,
  1426. COLORREF color, int nWidth, int nShape,
  1427. BOOL bCommit)
  1428. {
  1429. CRect rc;
  1430. DrawDCLine(pimg->hDC, pt1, pt2, color, nWidth, nShape, rc);
  1431. InvalImgRect(pimg, &rc);
  1432. if (bCommit)
  1433. {
  1434. CommitImgRect(pimg, &rc);
  1435. }
  1436. }
  1437. /***************************************************************************/
  1438. void FillImgRect( HDC hDC, CRect* prc, COLORREF cr )
  1439. {
  1440. FixRect( prc );
  1441. CPoint pt1 = prc->TopLeft();
  1442. CPoint pt2 = prc->BottomRight();
  1443. StandardiseCoords( &pt1, &pt2 );
  1444. int sx = pt1.x;
  1445. int sy = pt1.y;
  1446. int ex = pt2.x;
  1447. int ey = pt2.y;
  1448. CRect rc( sx, sy, ex, ey );
  1449. HBRUSH hBr = ::CreateSolidBrush( cr );
  1450. if (! hBr)
  1451. {
  1452. theApp.SetGdiEmergency();
  1453. return;
  1454. }
  1455. if (CImgTool::GetCurrentID() == IDMB_PICKRGNTOOL)
  1456. {
  1457. if (theImgBrush.m_cRgnPolyFreeHandSel.GetSafeHandle())
  1458. {
  1459. // offset bitmap in the imgwnd from selection boundary
  1460. theImgBrush.m_cRgnPolyFreeHandSel.OffsetRgn( rc.left, rc.top );
  1461. ::FillRgn( hDC, (HRGN)theImgBrush.m_cRgnPolyFreeHandSel.m_hObject,
  1462. hBr );
  1463. // offset back to selection boundary
  1464. theImgBrush.m_cRgnPolyFreeHandSel.OffsetRgn( -rc.left, -rc.top );
  1465. }
  1466. }
  1467. else
  1468. {
  1469. HPEN hPen = CreatePen( PS_NULL, 0, 0 );
  1470. if (hPen)
  1471. {
  1472. HPEN hOldPen = (HPEN)SelectObject( hDC, hPen );
  1473. HBRUSH hOldBr = (HBRUSH)SelectObject( hDC, hBr );
  1474. Rectangle( hDC, sx, sy, ex, ey );
  1475. SelectObject( hDC, hOldPen);
  1476. DeleteObject( hPen );
  1477. SelectObject( hDC, hOldBr );
  1478. }
  1479. }
  1480. DeleteObject( hBr );
  1481. *prc = rc;
  1482. }
  1483. /***************************************************************************/
  1484. void BrushLine(CDC* pDC, CPoint fromPt, CPoint toPt, int nWidth, int nShape)
  1485. {
  1486. CPen* pOldPen = (CPen*) pDC->SelectStockObject(NULL_PEN);
  1487. CSize brushSize(nWidth, nWidth);
  1488. int octant;
  1489. if (nShape == slantedRightBrush || nShape == slantedLeftBrush)
  1490. {
  1491. int dx = abs(toPt.x - fromPt.x);
  1492. int dy = abs(toPt.y - fromPt.y);
  1493. if (toPt.x > fromPt.x)
  1494. {
  1495. if (toPt.y < fromPt.y)
  1496. octant = (dx > dy) ? 0 : 1;
  1497. else
  1498. octant = (dx > dy) ? 7 : 6;
  1499. }
  1500. else
  1501. {
  1502. if (toPt.y < fromPt.y)
  1503. octant = (dx > dy) ? 3 : 2;
  1504. else
  1505. octant = (dx > dy) ? 4 : 5;
  1506. }
  1507. }
  1508. switch (nShape)
  1509. {
  1510. case squareBrush:
  1511. PolyTo(pDC, fromPt, toPt, brushSize);
  1512. break;
  1513. case roundBrush:
  1514. if (toPt != fromPt)
  1515. {
  1516. CRect tan;
  1517. CPoint polyPts [4];
  1518. if (!GetTanPt(brushSize, (CPoint)(toPt - fromPt), tan))
  1519. return;
  1520. polyPts[0].x = fromPt.x + tan.left;
  1521. polyPts[1].x = fromPt.x + tan.right;
  1522. polyPts[2].x = toPt.x + tan.right;
  1523. polyPts[3].x = toPt.x + tan.left;
  1524. polyPts[0].y = fromPt.y + tan.top;
  1525. polyPts[1].y = fromPt.y + tan.bottom;
  1526. polyPts[2].y = toPt.y + tan.bottom;
  1527. polyPts[3].y = toPt.y + tan.top;
  1528. pDC->Polygon(polyPts, 4);
  1529. Mylipse(pDC->m_hDC, fromPt.x, fromPt.y,
  1530. fromPt.x + brushSize.cx, fromPt.y + brushSize.cy, TRUE);
  1531. }
  1532. Mylipse(pDC->m_hDC, toPt.x, toPt.y,
  1533. toPt.x + brushSize.cx, toPt.y + brushSize.cy, TRUE);
  1534. break;
  1535. case slantedLeftBrush:
  1536. {
  1537. CPoint polyPts [6];
  1538. fromPt.x -= 1;
  1539. toPt.x -= 1;
  1540. switch (octant)
  1541. {
  1542. case 0:
  1543. polyPts[0].x = fromPt.x;
  1544. polyPts[1].x = fromPt.x + 1;
  1545. polyPts[2].x = toPt.x + 1;
  1546. polyPts[3].x = toPt.x + brushSize.cy + 1;
  1547. polyPts[4].x = toPt.x + brushSize.cy;
  1548. polyPts[5].x = fromPt.x + brushSize.cy;
  1549. polyPts[0].y = polyPts[1].y = fromPt.y + brushSize.cy;
  1550. polyPts[2].y = toPt.y + brushSize.cy;
  1551. polyPts[3].y = polyPts[4].y = toPt.y;
  1552. polyPts[5].y = fromPt.y;
  1553. break;
  1554. case 1:
  1555. polyPts[0].x = fromPt.x;
  1556. polyPts[1].x = fromPt.x + 1;
  1557. polyPts[2].x = fromPt.x + brushSize.cy + 1;
  1558. polyPts[3].x = toPt.x + brushSize.cy + 1;
  1559. polyPts[4].x = toPt.x + brushSize.cy;
  1560. polyPts[5].x = toPt.x;
  1561. polyPts[0].y = polyPts[1].y = fromPt.y + brushSize.cy;
  1562. polyPts[2].y = fromPt.y;
  1563. polyPts[3].y = polyPts[4].y = toPt.y;
  1564. polyPts[5].y = toPt.y + brushSize.cy;
  1565. break;
  1566. case 2:
  1567. case 3:
  1568. polyPts[0].x = fromPt.x + 1;
  1569. polyPts[1].x = fromPt.x;
  1570. polyPts[2].x = toPt.x;
  1571. polyPts[3].x = toPt.x + brushSize.cy;
  1572. polyPts[4].x = toPt.x + brushSize.cy + 1;
  1573. polyPts[5].x = fromPt.x + brushSize.cy + 1;
  1574. polyPts[0].y = polyPts[1].y = fromPt.y + brushSize.cy;
  1575. polyPts[2].y = toPt.y + brushSize.cy;
  1576. polyPts[3].y = polyPts[4].y = toPt.y;
  1577. polyPts[5].y = fromPt.y;
  1578. break;
  1579. case 4:
  1580. polyPts[0].x = fromPt.x + brushSize.cy + 1;
  1581. polyPts[1].x = fromPt.x + brushSize.cy;
  1582. polyPts[2].x = toPt.x + brushSize.cy;
  1583. polyPts[3].x = toPt.x;
  1584. polyPts[4].x = toPt.x + 1;
  1585. polyPts[5].x = fromPt.x + 1;
  1586. polyPts[0].y = polyPts[1].y = fromPt.y;
  1587. polyPts[2].y = toPt.y;
  1588. polyPts[3].y = polyPts[4].y = toPt.y + brushSize.cy;
  1589. polyPts[5].y = fromPt.y + brushSize.cy;
  1590. break;
  1591. case 5:
  1592. polyPts[0].x = fromPt.x + brushSize.cy + 1;
  1593. polyPts[1].x = fromPt.x + brushSize.cy;
  1594. polyPts[2].x = fromPt.x;
  1595. polyPts[3].x = toPt.x;
  1596. polyPts[4].x = toPt.x + 1;
  1597. polyPts[5].x = toPt.x + brushSize.cy + 1;
  1598. polyPts[0].y = polyPts[1].y = fromPt.y;
  1599. polyPts[2].y = fromPt.y + brushSize.cy;
  1600. polyPts[3].y = polyPts[4].y = toPt.y + brushSize.cy;
  1601. polyPts[5].y = toPt.y;
  1602. break;
  1603. default:
  1604. polyPts[0].x = fromPt.x + brushSize.cy;
  1605. polyPts[1].x = fromPt.x + brushSize.cy + 1;
  1606. polyPts[2].x = toPt.x + brushSize.cy + 1;
  1607. polyPts[3].x = toPt.x + 1;
  1608. polyPts[4].x = toPt.x;
  1609. polyPts[5].x = fromPt.x;
  1610. polyPts[0].y = polyPts[1].y = fromPt.y;
  1611. polyPts[2].y = toPt.y;
  1612. polyPts[3].y = polyPts[4].y = toPt.y + brushSize.cy;
  1613. polyPts[5].y = fromPt.y + brushSize.cy;
  1614. break;
  1615. }
  1616. pDC->Polygon(polyPts, 6);
  1617. }
  1618. break;
  1619. case slantedRightBrush:
  1620. {
  1621. CPoint polyPts [6];
  1622. switch (octant)
  1623. {
  1624. case 0:
  1625. case 1:
  1626. polyPts[0].x = fromPt.x + brushSize.cy;
  1627. polyPts[1].x = fromPt.x + brushSize.cy + 1;
  1628. polyPts[2].x = toPt.x + brushSize.cy + 1;
  1629. polyPts[3].x = toPt.x + 1;
  1630. polyPts[4].x = toPt.x;
  1631. polyPts[5].x = fromPt.x;
  1632. polyPts[0].y = polyPts[1].y = fromPt.y + brushSize.cy;
  1633. polyPts[2].y = toPt.y + brushSize.cy;
  1634. polyPts[3].y = polyPts[4].y = toPt.y;
  1635. polyPts[5].y = fromPt.y;
  1636. break;
  1637. case 2 :
  1638. polyPts[0].x = fromPt.x + brushSize.cy + 1;
  1639. polyPts[1].x = fromPt.x + brushSize.cy;
  1640. polyPts[2].x = fromPt.x;
  1641. polyPts[3].x = toPt.x;
  1642. polyPts[4].x = toPt.x + 1;
  1643. polyPts[5].x = toPt.x + brushSize.cy + 1;
  1644. polyPts[0].y = polyPts[1].y = fromPt.y + brushSize.cy;
  1645. polyPts[2].y = fromPt.y;
  1646. polyPts[3].y = polyPts[4].y = toPt.y;
  1647. polyPts[5].y = toPt.y + brushSize.cy;
  1648. break;
  1649. case 3 :
  1650. polyPts[0].x = fromPt.x + brushSize.cy + 1;
  1651. polyPts[1].x = fromPt.x + brushSize.cy;
  1652. polyPts[2].x = toPt.x + brushSize.cy;
  1653. polyPts[3].x = toPt.x;
  1654. polyPts[4].x = toPt.x + 1;
  1655. polyPts[5].x = fromPt.x + 1;
  1656. polyPts[0].y = polyPts[1].y = fromPt.y + brushSize.cy;
  1657. polyPts[2].y = toPt.y + brushSize.cy;
  1658. polyPts[3].y = polyPts[4].y = toPt.y;
  1659. polyPts[5].y = fromPt.y;
  1660. break;
  1661. case 4 :
  1662. case 5 :
  1663. polyPts[0].x = fromPt.x + 1;
  1664. polyPts[1].x = fromPt.x;
  1665. polyPts[2].x = toPt.x;
  1666. polyPts[3].x = toPt.x + brushSize.cy;
  1667. polyPts[4].x = toPt.x + brushSize.cy + 1;
  1668. polyPts[5].x = fromPt.x + brushSize.cy + 1;
  1669. polyPts[0].y = polyPts[1].y = fromPt.y;
  1670. polyPts[2].y = toPt.y;
  1671. polyPts[3].y = polyPts[4].y = toPt.y + brushSize.cy;
  1672. polyPts[5].y = fromPt.y + brushSize.cy;
  1673. break;
  1674. case 6 :
  1675. polyPts[0].x = fromPt.x;
  1676. polyPts[1].x = fromPt.x + 1;
  1677. polyPts[2].x = fromPt.x + brushSize.cy + 1;
  1678. polyPts[3].x = toPt.x + brushSize.cy + 1;
  1679. polyPts[4].x = toPt.x + brushSize.cy;
  1680. polyPts[5].x = toPt.x;
  1681. polyPts[0].y = polyPts[1].y = fromPt.y;
  1682. polyPts[2].y = fromPt.y + brushSize.cy;
  1683. polyPts[3].y = polyPts[4].y = toPt.y + brushSize.cy;
  1684. polyPts[5].y = toPt.y;
  1685. break;
  1686. default :
  1687. polyPts[0].x = fromPt.x;
  1688. polyPts[1].x = fromPt.x + 1;
  1689. polyPts[2].x = toPt.x + 1;
  1690. polyPts[3].x = toPt.x + brushSize.cy + 1;
  1691. polyPts[4].x = toPt.x + brushSize.cy;
  1692. polyPts[5].x = fromPt.x + brushSize.cy;
  1693. polyPts[0].y = polyPts[1].y = fromPt.y;
  1694. polyPts[2].y = toPt.y;
  1695. polyPts[3].y = polyPts[4].y = toPt.y + brushSize.cy;
  1696. polyPts[5].y = fromPt.y + brushSize.cy;
  1697. break;
  1698. }
  1699. pDC->Polygon(polyPts, 6);
  1700. }
  1701. break;
  1702. }
  1703. pDC->SelectObject(pOldPen);
  1704. }
  1705. /***************************************************************************/
  1706. void SetCombineMode(int wNewCombineMode)
  1707. {
  1708. wCombineMode = wNewCombineMode;
  1709. }
  1710. /***************************************************************************/
  1711. static int cxLastShape;
  1712. static int cyLastShape;
  1713. static int cxShapeBitmap;
  1714. static int cyShapeBitmap;
  1715. static CBitmap shapeBitmap;
  1716. static enum { ellipse, roundRect } nLastShape;
  1717. void Mylipse(HDC hDC, int x1, int y1, int x2, int y2, BOOL bFilled)
  1718. {
  1719. COLORREF crNewBk, crNewText;
  1720. GetMonoBltColors(hDC, NULL, crNewBk, crNewText);
  1721. COLORREF crOldText = SetTextColor(hDC, crNewText);
  1722. COLORREF crOldBk = SetBkColor (hDC, crNewBk);
  1723. int cx = x2 - x1;
  1724. int cy = y2 - y1;
  1725. if (!bFilled)
  1726. {
  1727. Ellipse(hDC, x1, y1, x2, y2);
  1728. }
  1729. else
  1730. if (cx == cy && cx > 0 && cx <= 8)
  1731. {
  1732. // HACK: The Windows Ellipse function is no good for small ellipses, so I
  1733. // use some little bitmaps here for filled circles 1 to 8 pixels in
  1734. // diameter.
  1735. static CBitmap g_ellipses [8];
  1736. if (g_ellipses[cx - 1].m_hObject == NULL &&
  1737. ! g_ellipses[cx - 1].LoadBitmap(IDB_ELLIPSE1 + cx - 1))
  1738. {
  1739. theApp.SetMemoryEmergency();
  1740. SetTextColor(hDC, crOldText);
  1741. SetBkColor(hDC, crOldBk);
  1742. return;
  1743. }
  1744. HDC hTempDC = CreateCompatibleDC(hDC);
  1745. if (hTempDC == NULL)
  1746. {
  1747. theApp.SetGdiEmergency();
  1748. SetTextColor(hDC, crOldText);
  1749. SetBkColor(hDC, crOldBk);
  1750. return;
  1751. }
  1752. HBITMAP hOldBitmap = (HBITMAP) SelectObject(hTempDC,
  1753. g_ellipses[cx - 1].m_hObject);
  1754. BitBlt(hDC, x1, y1, cx, cy, hTempDC, 0, 0, DSPDxax);
  1755. SelectObject(hTempDC, hOldBitmap);
  1756. DeleteDC(hTempDC);
  1757. }
  1758. else
  1759. if (cx > 0 && cy > 0)
  1760. {
  1761. // Actually, Ellipse() is just no good... Let's do as much
  1762. // as possible our selves to fix it! Here we draw the ellipse
  1763. // into a monochrome bitmap to get the shape and then use that
  1764. // as a mask to get the current pattern into the imge.
  1765. HDC hTempDC = CreateCompatibleDC(hDC);
  1766. if (hTempDC == NULL)
  1767. {
  1768. theApp.SetGdiEmergency();
  1769. SetTextColor(hDC, crOldText);
  1770. SetBkColor(hDC, crOldBk);
  1771. return;
  1772. }
  1773. BOOL bRefill = FALSE;
  1774. if (cx > cxShapeBitmap || cy > cyShapeBitmap)
  1775. {
  1776. shapeBitmap.DeleteObject();
  1777. if (shapeBitmap.CreateBitmap(cx, cy, 1, 1, NULL))
  1778. {
  1779. cxShapeBitmap = cx;
  1780. cyShapeBitmap = cy;
  1781. bRefill = TRUE;
  1782. }
  1783. }
  1784. if (shapeBitmap.m_hObject == NULL)
  1785. {
  1786. theApp.SetMemoryEmergency();
  1787. DeleteDC(hTempDC);
  1788. SetTextColor(hDC, crOldText);
  1789. SetBkColor(hDC, crOldBk);
  1790. return;
  1791. }
  1792. if (cx != cxLastShape || cy != cyLastShape || nLastShape != ellipse)
  1793. {
  1794. cxLastShape = cx;
  1795. cyLastShape = cy;
  1796. nLastShape = ellipse;
  1797. bRefill = TRUE;
  1798. }
  1799. HBITMAP hOldBitmap = (HBITMAP)SelectObject(hTempDC,
  1800. shapeBitmap.m_hObject);
  1801. if (bRefill)
  1802. {
  1803. PatBlt(hTempDC, 0, 0, cx, cy, BLACKNESS);
  1804. SelectObject(hTempDC, GetStockObject(WHITE_BRUSH));
  1805. SelectObject(hTempDC, GetStockObject(WHITE_PEN));
  1806. Ellipse(hTempDC, 0, 0, cx, cy);
  1807. }
  1808. BitBlt(hDC, x1, y1, cx, cy, hTempDC, 0, 0, DSPDxax);
  1809. SelectObject(hTempDC, hOldBitmap);
  1810. DeleteDC(hTempDC);
  1811. }
  1812. SetTextColor(hDC, crOldText);
  1813. SetBkColor(hDC, crOldBk);
  1814. }
  1815. /***************************************************************************/
  1816. #ifdef XYZZYZ
  1817. void MyRoundRect(HDC hDC, int x1, int y1, int x2, int y2,
  1818. int nEllipseWidth, int nEllipseHeight, BOOL bFilled)
  1819. {
  1820. int cx = x2 - x1;
  1821. int cy = y2 - y1;
  1822. if (!bFilled)
  1823. {
  1824. RoundRect(hDC, x1, y1, x2, y2, nEllipseWidth, nEllipseHeight);
  1825. return;
  1826. }
  1827. if (cx > 0 && cy > 0)
  1828. {
  1829. HDC hTempDC = CreateCompatibleDC(hDC);
  1830. if (hTempDC == NULL)
  1831. {
  1832. theApp.SetGdiEmergency();
  1833. return;
  1834. }
  1835. BOOL bRefill = FALSE;
  1836. if (cx > cxShapeBitmap || cy > cyShapeBitmap)
  1837. {
  1838. shapeBitmap.DeleteObject();
  1839. if (shapeBitmap.CreateBitmap(cx, cy, 1, 1, NULL))
  1840. {
  1841. cxShapeBitmap = cx;
  1842. cyShapeBitmap = cy;
  1843. bRefill = TRUE;
  1844. }
  1845. }
  1846. if (shapeBitmap.m_hObject == NULL)
  1847. {
  1848. theApp.SetMemoryEmergency();
  1849. DeleteDC(hTempDC);
  1850. return;
  1851. }
  1852. if (cx != cxLastShape || cy != cyLastShape || nLastShape != roundRect)
  1853. {
  1854. cxLastShape = cx;
  1855. cyLastShape = cy;
  1856. nLastShape = roundRect;
  1857. bRefill = TRUE;
  1858. }
  1859. HBITMAP hOldBitmap = (HBITMAP)SelectObject(hTempDC,
  1860. shapeBitmap.m_hObject);
  1861. if (bRefill)
  1862. {
  1863. PatBlt(hTempDC, 0, 0, cx, cy, BLACKNESS);
  1864. SelectObject(hTempDC, GetStockObject(WHITE_BRUSH));
  1865. SelectObject(hTempDC, GetStockObject(WHITE_PEN));
  1866. RoundRect(hTempDC, 0, 0, cx, cy, nEllipseWidth, nEllipseHeight);
  1867. }
  1868. BitBlt(hDC, x1, y1, cx, cy, hTempDC, 0, 0, DSna);
  1869. BitBlt(hDC, x1, y1, cx, cy, hTempDC, 0, 0, DSPao);
  1870. SelectObject(hTempDC, hOldBitmap);
  1871. DeleteDC(hTempDC);
  1872. }
  1873. }
  1874. #endif
  1875. /***************************************************************************/
  1876. void PolyTo(CDC* pDC, CPoint fromPt, CPoint toPt, CSize size)
  1877. {
  1878. CPoint polyPts [6];
  1879. if (toPt.x > fromPt.x)
  1880. {
  1881. polyPts[0].x = polyPts[1].x = fromPt.x;
  1882. polyPts[2].x = toPt.x;
  1883. polyPts[3].x = polyPts[4].x = toPt.x + size.cx;
  1884. polyPts[5].x = fromPt.x + size.cx;
  1885. }
  1886. else
  1887. {
  1888. polyPts[0].x = polyPts[1].x = fromPt.x + size.cx;
  1889. polyPts[2].x = toPt.x + size.cx;
  1890. polyPts[3].x = polyPts[4].x = toPt.x;
  1891. polyPts[5].x = fromPt.x;
  1892. }
  1893. if (toPt.y > fromPt.y)
  1894. {
  1895. polyPts[0].y = polyPts[5].y = fromPt.y;
  1896. polyPts[1].y = fromPt.y + size.cy;
  1897. polyPts[2].y = polyPts[3].y = toPt.y + size.cy;
  1898. polyPts[4].y = toPt.y;
  1899. }
  1900. else
  1901. {
  1902. polyPts[0].y = polyPts[5].y = fromPt.y + size.cy;
  1903. polyPts[1].y = fromPt.y;
  1904. polyPts[2].y = polyPts[3].y = toPt.y;
  1905. polyPts[4].y = toPt.y + size.cy;
  1906. }
  1907. if (pDC)
  1908. pDC->Polygon(polyPts, 6);
  1909. }
  1910. /***************************************************************************/
  1911. BOOL GetTanPt(CSize size, CPoint delta, CRect& tan)
  1912. {
  1913. int x, y;
  1914. int xExt, yExt, theExt, xTemp;
  1915. CDC dc;
  1916. CBitmap* pOldBitmap, bitmap;
  1917. size.cx += 1;
  1918. size.cy += 1;
  1919. tan.SetRect(0, 0, 0, 0);
  1920. if (!dc.CreateCompatibleDC(NULL))
  1921. {
  1922. theApp.SetGdiEmergency();
  1923. return FALSE;
  1924. }
  1925. if (!bitmap.CreateCompatibleBitmap(&dc, size.cx, size.cy))
  1926. {
  1927. theApp.SetMemoryEmergency();
  1928. return FALSE;
  1929. }
  1930. VERIFY((pOldBitmap = dc.SelectObject(&bitmap)));
  1931. TRY
  1932. {
  1933. CBrush cBrushWhite(PALETTERGB(0xff, 0xff, 0xff));
  1934. CRect cRectTmp(0,0,size.cx, size.cy);
  1935. dc.FillRect(&cRectTmp, &cBrushWhite);
  1936. // dc.PatBlt(0, 0, size.cx, size.cy, WHITENESS);
  1937. }
  1938. CATCH(CResourceException, e)
  1939. {
  1940. }
  1941. END_CATCH
  1942. dc.SelectStockObject(NULL_PEN);
  1943. dc.SelectStockObject(BLACK_BRUSH);
  1944. Mylipse(dc.m_hDC, 0, 0, size.cx, size.cy, TRUE);
  1945. yExt = 0;
  1946. for (xExt = 0; xExt < size.cx - 1; xExt++)
  1947. {
  1948. if (dc.GetPixel(xExt, 0) == 0)
  1949. break;
  1950. }
  1951. theExt = 10 * xExt;
  1952. if (delta.y == 0)
  1953. {
  1954. tan.SetRect(xExt, 0, xExt, size.cy - 1);
  1955. }
  1956. else
  1957. {
  1958. for (y = 0; y < size.cy; y++)
  1959. {
  1960. for (x = 0; x < size.cx - 1; x++)
  1961. {
  1962. if (dc.GetPixel(x, y) == 0)
  1963. break;
  1964. }
  1965. xTemp = 10 * x - 10 * y * delta.x / delta.y;
  1966. if (theExt > xTemp)
  1967. {
  1968. xExt = x;
  1969. yExt = y;
  1970. theExt = xTemp;
  1971. }
  1972. else
  1973. if (theExt < xTemp)
  1974. {
  1975. break;
  1976. }
  1977. }
  1978. tan.left = xExt;
  1979. tan.top = yExt;
  1980. for (y = 0; y < size.cy; y++)
  1981. {
  1982. for (x = size.cx - 1; x > 0; x--)
  1983. {
  1984. if (dc.GetPixel(x, y) == 0)
  1985. break;
  1986. }
  1987. xTemp = 10 * x - 10 * y * delta.x / delta.y;
  1988. if (theExt < xTemp)
  1989. {
  1990. xExt = x;
  1991. yExt = y;
  1992. theExt = xTemp;
  1993. }
  1994. else
  1995. if (theExt > xTemp)
  1996. {
  1997. break;
  1998. }
  1999. }
  2000. tan.right = xExt;
  2001. tan.bottom = yExt;
  2002. }
  2003. dc.SelectObject(pOldBitmap);
  2004. return TRUE;
  2005. }
  2006. /***************************************************************************/
  2007. void PickupSelection()
  2008. {
  2009. // Time to pick up the bits!
  2010. ASSERT(theImgBrush.m_pImg);
  2011. if (theImgBrush.m_pImg == NULL)
  2012. return;
  2013. CPalette* ppalOld = theImgBrush.SetBrushPalette( &theImgBrush.m_dc, FALSE ); // Background ??
  2014. CDC* pImgDC = CDC::FromHandle( theImgBrush.m_pImg->hDC );
  2015. if (CImgTool::GetCurrentID() == IDMB_PICKRGNTOOL)
  2016. {
  2017. TRY {
  2018. CBrush cBrushBk( crRight );
  2019. CRect cRectTmp( 0, 0, theImgBrush.m_size.cx,
  2020. theImgBrush.m_size.cy );
  2021. theImgBrush.m_dc.FillRect( &cRectTmp, &cBrushBk );
  2022. }
  2023. CATCH(CResourceException, e)
  2024. {
  2025. theApp.SetGdiEmergency();
  2026. return;
  2027. }
  2028. END_CATCH
  2029. if (theImgBrush.m_cRgnPolyFreeHandSel.GetSafeHandle())
  2030. {
  2031. theImgBrush.m_dc.SelectClipRgn(&theImgBrush.m_cRgnPolyFreeHandSel);
  2032. theImgBrush.m_dc.StretchBlt( 0, 0, theImgBrush.m_size.cx,
  2033. theImgBrush.m_size.cy,
  2034. pImgDC, theImgBrush.m_rcSelection.left,
  2035. theImgBrush.m_rcSelection.top,
  2036. theImgBrush.m_rcSelection.Width(),
  2037. theImgBrush.m_rcSelection.Height(),
  2038. SRCCOPY );
  2039. theImgBrush.m_dc.SelectClipRgn(NULL);
  2040. }
  2041. }
  2042. else
  2043. {
  2044. theImgBrush.m_dc.BitBlt( 0, 0, theImgBrush.m_size.cx,
  2045. theImgBrush.m_size.cy,
  2046. pImgDC, theImgBrush.m_rcSelection.left,
  2047. theImgBrush.m_rcSelection.top, SRCCOPY );
  2048. }
  2049. if (ppalOld)
  2050. theImgBrush.m_dc.SelectPalette( ppalOld, FALSE );
  2051. theImgBrush.RecalcMask( crRight );
  2052. }
  2053. /***************************************************************************/
  2054. void CommitSelection(BOOL bSetUndo)
  2055. {
  2056. if (theImgBrush.m_bMakingSelection)
  2057. return;
  2058. if (! theImgBrush.m_bSmearSel
  2059. && ( theImgBrush.m_pImg == NULL
  2060. || theImgBrush.m_bFirstDrag
  2061. || theImgBrush.m_bLastDragWasASmear))
  2062. {
  2063. return;
  2064. }
  2065. if (theImgBrush.m_bLastDragWasFirst
  2066. && (theImgBrush.m_bMoveSel
  2067. || theImgBrush.m_bSmearSel))
  2068. {
  2069. return;
  2070. }
  2071. TRACE1( "CommitSelection(%d)\n", bSetUndo );
  2072. if (bSetUndo)
  2073. {
  2074. HideBrush();
  2075. CRect rectUndo = theImgBrush.m_rcSelection;
  2076. if (theImgBrush.m_bLastDragWasFirst)
  2077. {
  2078. theImgBrush.m_bLastDragWasFirst = FALSE;
  2079. rectUndo |= theImgBrush.m_rcDraggedFrom;
  2080. }
  2081. else
  2082. {
  2083. SetUndo(theImgBrush.m_pImg);
  2084. }
  2085. CImgWnd::c_pImgWndCur->FinishUndo(rectUndo);
  2086. }
  2087. if (CImgTool::GetCurrentID() != IDMX_TEXTTOOL)
  2088. {
  2089. if (theImgBrush.m_bOpaque)
  2090. {
  2091. theImgBrush.BltReplace( theImgBrush.m_pImg,
  2092. theImgBrush.m_rcSelection.TopLeft() );
  2093. }
  2094. else
  2095. {
  2096. theImgBrush.BltMatte( theImgBrush.m_pImg,
  2097. theImgBrush.m_rcSelection.TopLeft() );
  2098. }
  2099. }
  2100. InvalImgRect ( theImgBrush.m_pImg, &theImgBrush.m_rcSelection );
  2101. CommitImgRect( theImgBrush.m_pImg, &theImgBrush.m_rcSelection );
  2102. DirtyImg( theImgBrush.m_pImg );
  2103. }
  2104. /***************************************************************************/
  2105. void AddImgWnd(IMG* pimg, CImgWnd* pImgWnd)
  2106. {
  2107. ASSERT(pImgWnd->m_pNextImgWnd == NULL);
  2108. pImgWnd->m_pNextImgWnd = pimg->m_pFirstImgWnd;
  2109. pimg->m_pFirstImgWnd = pImgWnd;
  2110. }
  2111. /***************************************************************************/
  2112. void GetImgSize(IMG* pImg, CSize& size)
  2113. {
  2114. size.cx = pImg->cxWidth;
  2115. size.cy = pImg->cyHeight;
  2116. }
  2117. /***************************************************************************/
  2118. BOOL SetImgSize(IMG* pImg, CSize newSize, BOOL bStretch)
  2119. {
  2120. if (newSize.cx != pImg->cxWidth
  2121. || newSize.cy != pImg->cyHeight)
  2122. {
  2123. HBITMAP hNewBitmap = CreateCompatibleBitmap( pImg->hDC,
  2124. newSize.cx, newSize.cy );
  2125. if (hNewBitmap == NULL)
  2126. {
  2127. return FALSE;
  2128. }
  2129. HDC hDC = CreateCompatibleDC( pImg->hDC );
  2130. if (hDC == NULL)
  2131. {
  2132. DeleteObject( hNewBitmap );
  2133. return FALSE;
  2134. }
  2135. HBITMAP hOldBitmap = (HBITMAP)SelectObject( hDC, hNewBitmap );
  2136. ASSERT( hOldBitmap );
  2137. HPALETTE hpalOld = NULL;
  2138. if (theApp.m_pPalette
  2139. && theApp.m_pPalette->m_hObject)
  2140. {
  2141. hpalOld = SelectPalette( hDC, (HPALETTE)theApp.m_pPalette->m_hObject, FALSE ); // Background ??
  2142. RealizePalette( hDC );
  2143. }
  2144. if (bStretch)
  2145. {
  2146. UINT uStretch = HALFTONE;
  2147. if (pImg->cPlanes * pImg->cBitCount == 1)
  2148. {
  2149. uStretch = BLACKONWHITE;
  2150. if (GetRValue( crLeft )
  2151. || GetGValue( crLeft )
  2152. || GetBValue( crLeft ))
  2153. uStretch = WHITEONBLACK;
  2154. }
  2155. SetStretchBltMode( hDC, uStretch );
  2156. StretchCopy( hDC, 0, 0, newSize.cx, newSize.cy,
  2157. pImg->hDC, 0, 0, pImg->cxWidth, pImg->cyHeight );
  2158. }
  2159. else
  2160. {
  2161. // Fill it with the background color first!
  2162. HBRUSH hBrush = ::CreateSolidBrush(crRight);
  2163. ASSERT(hBrush);
  2164. if (hBrush)
  2165. {
  2166. HBRUSH hOldBrush = (HBRUSH)SelectObject(hDC, hBrush);
  2167. ASSERT(hOldBrush);
  2168. PatBlt(hDC, 0, 0, newSize.cx, newSize.cy, PATCOPY);
  2169. VERIFY(SelectObject(hDC, hOldBrush) == hBrush);
  2170. DeleteObject(hBrush);
  2171. }
  2172. BitBlt(hDC, 0, 0, newSize.cx, newSize.cy, pImg->hDC, 0, 0, SRCCOPY);
  2173. }
  2174. if (hpalOld)
  2175. SelectPalette( hDC, hpalOld, FALSE ); // Background ??
  2176. VERIFY( SelectObject( hDC, hOldBitmap) == hNewBitmap );
  2177. VERIFY( SelectObject( pImg->hDC, hNewBitmap) == pImg->hBitmap );
  2178. DeleteObject( pImg->hBitmap );
  2179. DeleteDC( hDC );
  2180. pImg->hBitmap = hNewBitmap;
  2181. pImg->cxWidth = newSize.cx;
  2182. pImg->cyHeight = newSize.cy;
  2183. pRubberImg = NULL;
  2184. SetupRubber( pImg );
  2185. InvalImgRect(pImg, NULL);
  2186. CImgWnd* pImgWnd = pImg->m_pFirstImgWnd;
  2187. while (pImgWnd)
  2188. {
  2189. pImgWnd->Invalidate( FALSE );
  2190. pImgWnd->CheckScrollBars();
  2191. pImgWnd = pImgWnd->m_pNextImgWnd;
  2192. }
  2193. }
  2194. return TRUE;
  2195. }
  2196. /***************************************************************************/
  2197. // This may be set to TRUE via the "DriverCanStretch" entry in the INI file.
  2198. // Doing so will speed up the graphics editor, but will cause some device
  2199. // drivers to crash (hence the FALSE default).
  2200. //
  2201. BOOL g_bDriverCanStretch = TRUE;
  2202. void StretchCopy( HDC hdcDest, int xDest, int yDest, int cxDest, int cyDest,
  2203. HDC hdcSrc , int xSrc , int ySrc , int cxSrc , int cySrc )
  2204. {
  2205. if (cxDest == cxSrc && cyDest == cySrc)
  2206. {
  2207. // No point in using the trick if we're not really stretching...
  2208. BitBlt(hdcDest, xDest, yDest, cxDest, cyDest,
  2209. hdcSrc, xSrc, ySrc, SRCCOPY);
  2210. }
  2211. else
  2212. if (g_bDriverCanStretch ||
  2213. cxDest < 0 || cyDest < 0 || cxSrc < 0 || cySrc < 0)
  2214. {
  2215. // We can't use the following trick when flipping, but the
  2216. // driver will usually pass things on to GDI here anyway...
  2217. StretchBlt(hdcDest, xDest, yDest, cxDest, cyDest,
  2218. hdcSrc, xSrc, ySrc, cxSrc, cySrc, SRCCOPY);
  2219. }
  2220. else
  2221. {
  2222. // Some drivers (e.g. Paradise) crash on memory to memory stretches,
  2223. // so we trick them into just using GDI here by not using SRCCOPY...
  2224. PatBlt(hdcDest, xDest, yDest, cxDest, cyDest, BLACKNESS);
  2225. StretchBlt(hdcDest, xDest, yDest, cxDest, cyDest,
  2226. hdcSrc, xSrc, ySrc, cxSrc, cySrc, DSo);
  2227. }
  2228. }
  2229. /***************************************************************************/
  2230. void StandardiseCoords(CPoint* s, CPoint* e)
  2231. {
  2232. if (s->x > e->x)
  2233. {
  2234. int tx;
  2235. tx = s->x;
  2236. s->x = e->x;
  2237. e->x = tx;
  2238. }
  2239. if (s->y > e->y)
  2240. {
  2241. int ty;
  2242. ty = s->y;
  2243. s->y = e->y;
  2244. e->y = ty;
  2245. }
  2246. }
  2247. /***************************************************************************/
  2248. CPalette* MergePalettes( CPalette *pPal1, CPalette *pPal2, int& iAdds )
  2249. {
  2250. int iPal1NumEntries;
  2251. int iPal2NumEntries;
  2252. LOGPALETTE256 LogPal1;
  2253. LOGPALETTE256 LogPal2;
  2254. CPalette* pPalMerged = NULL;
  2255. iAdds = 0;
  2256. if (pPal1 == NULL || pPal2 == NULL)
  2257. return NULL;
  2258. iPal1NumEntries = pPal1->GetPaletteEntries( 0, 256, &LogPal1.palPalEntry[0] );
  2259. pPal1->GetPaletteEntries( 0, iPal1NumEntries, &LogPal1.palPalEntry[0] );
  2260. iPal2NumEntries = pPal2->GetPaletteEntries( 0, 256, &LogPal2.palPalEntry[0] );
  2261. pPal2->GetPaletteEntries( 0, iPal2NumEntries, &LogPal2.palPalEntry[0] );
  2262. // check if room left in 1st palette to merge. If no room, then use 1st palette
  2263. for (int i = 0; i < iPal2NumEntries
  2264. && iPal1NumEntries < MAX_PALETTE_COLORS; i++)
  2265. {
  2266. for (int j = 0; j < iPal1NumEntries; j++)
  2267. {
  2268. if (LogPal1.palPalEntry[j].peRed == LogPal2.palPalEntry[i].peRed
  2269. && LogPal1.palPalEntry[j].peGreen == LogPal2.palPalEntry[i].peGreen
  2270. && LogPal1.palPalEntry[j].peBlue == LogPal2.palPalEntry[i].peBlue)
  2271. break;
  2272. }
  2273. if (j < iPal1NumEntries)
  2274. continue; // found one
  2275. // color was not found in 1st palette add it if room
  2276. LogPal1.palPalEntry[iPal1NumEntries++] = LogPal2.palPalEntry[i];
  2277. iAdds++;
  2278. }
  2279. LogPal1.palVersion = 0x300;
  2280. LogPal1.palNumEntries = (WORD)iPal1NumEntries;
  2281. pPalMerged = new CPalette();
  2282. if (pPalMerged)
  2283. if (! CreateSafePalette(pPalMerged, (LPLOGPALETTE)&LogPal1 ))
  2284. {
  2285. delete pPalMerged;
  2286. pPalMerged = NULL;
  2287. }
  2288. return pPalMerged;
  2289. }
  2290. /******************************************************************************/
  2291. void AdjustPointForGrid(CPoint *ptPointLocation)
  2292. {
  2293. if (theApp.m_iSnapToGrid != 0)
  2294. {
  2295. int iNextGridOffset;
  2296. iNextGridOffset = ptPointLocation->x % theApp.m_iGridExtent;
  2297. // if distance to next grid is less than 1/2 distance between grids
  2298. // closer to previous grid
  2299. if (iNextGridOffset <= theApp.m_iGridExtent/2)
  2300. {
  2301. iNextGridOffset *= -1; // closer to previous grid location
  2302. }
  2303. else
  2304. {
  2305. iNextGridOffset = theApp.m_iGridExtent -iNextGridOffset; // closer to next grid location
  2306. }
  2307. ptPointLocation->x = ptPointLocation->x + iNextGridOffset;
  2308. // if distance to next grid is less than 1/2 distance between grids
  2309. // closer to previous grid
  2310. iNextGridOffset = ptPointLocation->y % theApp.m_iGridExtent;
  2311. if (iNextGridOffset <= theApp.m_iGridExtent/2)
  2312. {
  2313. iNextGridOffset *= -1; // closer to previous grid location
  2314. }
  2315. else
  2316. {
  2317. iNextGridOffset = theApp.m_iGridExtent -iNextGridOffset; // closer to next grid location
  2318. }
  2319. ptPointLocation->y = ptPointLocation->y + iNextGridOffset;
  2320. }
  2321. }
  2322. static unsigned short bmapHorzBorder [] =
  2323. { 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0 };
  2324. static unsigned short bmapVertBorder [] =
  2325. { 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 };
  2326. CBrush g_brSelectHorz;
  2327. CBrush g_brSelectVert;
  2328. static CBitmap m_bmSelectHorz;
  2329. static CBitmap m_bmSelectVert;
  2330. void InitCustomData() // called once in main
  2331. {
  2332. //
  2333. // no windows critical error message box, return errors to open call
  2334. //
  2335. if (m_bmSelectHorz.CreateBitmap( 8, 8, 1, 1, (LPSTR)bmapHorzBorder ))
  2336. g_brSelectHorz.CreatePatternBrush( &m_bmSelectHorz );
  2337. if (m_bmSelectVert.CreateBitmap( 8, 8, 1, 1, (LPSTR)bmapVertBorder ))
  2338. g_brSelectVert.CreatePatternBrush( &m_bmSelectVert );
  2339. SetErrorMode( SEM_FAILCRITICALERRORS );
  2340. }
  2341. //
  2342. // make sure global resoures are freed
  2343. //
  2344. void CustomExit()
  2345. {
  2346. if (g_brSelectHorz.m_hObject)
  2347. g_brSelectHorz.DeleteObject();
  2348. if (m_bmSelectHorz.m_hObject)
  2349. m_bmSelectHorz.DeleteObject();
  2350. if (g_brSelectVert.m_hObject)
  2351. g_brSelectVert.DeleteObject();
  2352. if (m_bmSelectVert.m_hObject)
  2353. m_bmSelectVert.DeleteObject();
  2354. }
  2355. /*
  2356. int FileTypeFromExtension( const TCHAR far* lpcExt )
  2357. {
  2358. if (*lpcExt == TEXT('.')) // skip the . in .*
  2359. lpcExt++;
  2360. // must be redone
  2361. return NULL;
  2362. }
  2363. */
  2364. CPalette *PBSelectPalette(CDC *pDC, CPalette *pPalette, BOOL bForceBk)
  2365. {
  2366. if (!pPalette)
  2367. {
  2368. return(NULL);
  2369. }
  2370. if (IsInPlace())
  2371. {
  2372. bForceBk = TRUE;
  2373. }
  2374. CPalette *ppalOld = pDC->SelectPalette( theApp.m_pPalette, bForceBk );
  2375. pDC->RealizePalette();
  2376. return(ppalOld);
  2377. }